初學者常在 re.search(pattern, file_object) 時遇到 TypeError: expected string or bytes-like object。本文解釋錯誤根因:re 模組只接受 str/bytes,不支援 _io.TextIOWrapper、list 等可迭代物件,並提供三種標準修正模式。
with open('data.txt', 'r', encoding='utf-8') as f:
# 錯誤:直接傳遞 file object
match = re.search(r'\d+', f) # TypeError!
open() 回傳 _io.TextIOWrapper (文字模式) 或 _io.BufferedReader (二進位模式)。re.search() 簽名:re.search(pattern, string, flags=0),string 必須是 str 或 bytes。with open('data.txt', 'r', encoding='utf-8') as f:
content = f.read() # 讀成完整字串
match = re.search(r'\d+', content)
with open('data.txt', 'r', encoding='utf-8') as f:
for line in f: # 逐行迭代,每行是 str
match = re.search(r'\d+', line)
if match:
print(match.group())
import mmap
with open('data.txt', 'r+b') as f:
mm = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
match = re.search(rb'\d+', mm) # 注意:bytes 模式需用 rb 前綴
mm.close()
| 錯誤寫法 | 錯誤原因 | 正確寫法 |
|---|---|---|
re.search(pat, open(...)) | 傳遞 file object | re.search(pat, open(...).read()) |
re.search(pat, f.readlines()) | 傳遞 list[str] | 逐行迭代 for line in f: |
re.search(pat, f.buffer) | 傳遞 BufferedReader | re.search(pat, f.buffer.read()) 或 mmap |
str(f) 強制轉換 | 得到 "<_io.TextIOWrapper ...>" 而非檔案內容 | 同上 |
import re
PATTERN = re.compile(r'\d{4}-\d{2}-\d{2}') # 編譯一次,多次使用
with open('log.txt', 'r', encoding='utf-8') as f:
for line in f:
m = PATTERN.search(line)
if m:
print(m.group())
string 參數型別要求。re 模組只吃字串/位元組,不吃檔案物件、列表、生成器。養成「先讀取再匹配」或「逐行讀取匹配」的習慣,並善用 re.compile 提升效能,即可徹底避開 TypeError: expected string or bytes-like object。