本文 AI 產出,尚未審核
Python 檔案操作(File I/O) – 讀寫模式(r, w, a, b)
簡介
在日常開發中,檔案讀寫是最常見的 I/O 工作之一。無論是寫日誌、儲存使用者設定、還是批次處理大量資料,都離不開對本機檔案的存取。Python 內建的 open() 函式提供了簡潔且統一的介面,讓開發者只需要指定檔案路徑與模式(mode)即可完成讀寫操作。
模式的選擇直接影響檔案的行為:是要讀取、覆寫、追加,還是以二進位方式處理?了解每個模式的意義與適用情境,是寫出安全、效能良好的檔案程式的第一步。本篇文章將深入說明 r、w、a、b 四種基礎模式,搭配實用範例、常見陷阱與最佳實踐,幫助初學者快速上手,也讓中級開發者在大型專案中能更得心應手。
核心概念
open() 的語法如下:
file_obj = open(file_path, mode='r', encoding='utf-8')
file_path:欲開啟的檔案路徑(相對或絕對)。mode:檔案的開啟模式,預設為'r'(唯讀)。encoding:文字檔的編碼,常用utf-8。二進位模式(b)下不需要此參數。
以下分別說明四種最常見的模式,並提供實作範例。
1. 讀取模式 r(Read)
- 用途:從檔案讀取資料。檔案必須已存在,否則會拋出
FileNotFoundError。 - 預設:若未指定 mode,
open()會以'r'開啟。 - 文字 vs 二進位:
'r'為文字模式,會自動根據encoding轉換為str;若加上b('rb'),則回傳bytes。
範例 1:逐行讀取文字檔
# 讀取檔案內容,逐行印出
with open('data.txt', mode='r', encoding='utf-8') as f:
for line in f:
print(line.strip()) # strip() 移除行尾換行符號
說明:使用
with語法可確保檔案在使用完畢後自動關閉,避免資源泄漏。
範例 2:一次讀取全部內容
with open('data.txt', 'r', encoding='utf-8') as f:
content = f.read() # 讀入整個檔案成為單一字串
print('檔案長度:', len(content))
2. 寫入模式 w(Write)
- 用途:將資料寫入檔案。若檔案已存在,會 截斷(清空)檔案內容;若檔案不存在,則會自動建立。
- 文字 vs 二進位:
'w'為文字模式,寫入前會根據encoding編碼;'wb'為二進位模式,直接寫入bytes。
⚠️ 注意:
w會「覆寫」舊檔案,請務必確認不會意外刪除重要資料。
範例 3:寫入文字檔
lines = [
'第一行:Hello, World!',
'第二行:Python 檔案寫入示範',
'第三行:結束'
]
with open('output.txt', 'w', encoding='utf-8') as f:
for line in lines:
f.write(line + '\n') # 必須自行加入換行符號
範例 4:寫入二進位檔(如圖片)
# 假設已有一段二進位資料 (bytes)
binary_data = b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR...'
with open('image.png', 'wb') as f:
f.write(binary_data) # 直接寫入 bytes
3. 追加模式 a(Append)
- 用途:在檔案末端 追加 資料。若檔案不存在,會自動建立。
- 特性:不會截斷原有內容,適合寫入日誌、累積結果等情境。
- 文字 vs 二進位:同樣支援
'a'(文字)與'ab'(二進位)。
範例 5:寫入日誌檔
import datetime
def log(message: str):
timestamp = datetime.datetime.now().isoformat()
with open('app.log', 'a', encoding='utf-8') as f:
f.write(f'[{timestamp}] {message}\n')
log('程式啟動')
log('執行資料處理')
log('程式結束')
重點:每次呼叫
log()都會在檔案末端新增一行,不會覆蓋先前的紀錄。
4. 二進位模式 b(Binary)
- 用途:處理非文字檔案(如圖片、音訊、壓縮檔),或需要精確控制位元組的情況。
- 結合方式:
b必須與其他模式結合,例如rb(讀取二進位)、wb(寫入二進位)或ab(二進位追加)。 - 差異:在二進位模式下,讀寫的資料類型是
bytes,不會自動進行編碼/解碼。
範例 6:複製二進位檔(檔案備份)
def copy_binary(src: str, dst: str):
# 以 64KB 為單位分塊讀寫,降低記憶體佔用
chunk_size = 64 * 1024
with open(src, 'rb') as f_src, open(dst, 'wb') as f_dst:
while True:
chunk = f_src.read(chunk_size)
if not chunk: # 讀到檔案結尾
break
f_dst.write(chunk)
copy_binary('original.jpg', 'backup.jpg')
常見陷阱與最佳實踐
| 陷阱 | 原因 | 解決方式 |
|---|---|---|
忘記使用 with |
手動 close() 容易遺漏,導致檔案鎖定或資源泄漏 |
永遠 使用 with open(...) as f: |
| 使用錯誤的模式 | 例如用 'r' 讀取不存在的檔案會拋 FileNotFoundError;用 'w' 不小心覆寫重要資料 |
先檢查檔案是否存在 (os.path.exists) 或改用 'a' 追加 |
| 文字編碼不一致 | 讀寫時編碼不匹配會出現 UnicodeDecodeError 或亂碼 |
明確指定 encoding='utf-8'(或其他正確編碼),保持前後一致 |
| 一次讀取過大檔案 | f.read() 會一次把整個檔案載入記憶體,對大檔案會耗盡資源 |
使用 分塊讀取(read(size))或 逐行迭代 |
| 在二進位模式下寫入文字 | f.write('文字') 會因型別不符拋 TypeError |
先將文字編碼為 bytes('文字'.encode('utf-8'))或改用文字模式 |
最佳實踐清單
- 使用
with管理檔案生命週期with open('file.txt', 'r') as f: data = f.read() - 明確設定編碼(尤其跨平台時)
open('file.txt', 'w', encoding='utf-8') - 避免一次讀入過大檔案
for chunk in iter(lambda: f.read(8192), b''): process(chunk) - 在寫入前檢查目錄是否存在
import os os.makedirs('logs', exist_ok=True) - 使用例外處理捕捉 I/O 錯誤
try: with open('config.json', 'r') as f: cfg = json.load(f) except FileNotFoundError: print('設定檔不存在,使用預設值')
實際應用場景
日誌系統
- 使用
a追加模式寫入時間戳記,確保每次執行都不會丟失先前紀錄。 - 搭配
logging模組的FileHandler,自動切割檔案大小。
- 使用
資料前處理
- 大型 CSV 檔案常以
r逐行讀取,配合csv模組進行分欄解析,避免一次載入全部資料。
- 大型 CSV 檔案常以
檔案備份與同步
- 以
rb/wb二進位模式配合 分塊讀寫,在網路傳輸或磁碟備份時降低記憶體使用。
- 以
設定檔管理
w用於產生或重寫 JSON/YAML 設定檔;若需要保留舊設定,可先備份再寫入。
多執行緒/多行程寫入
- 針對同一檔案使用
a模式,配合檔案鎖 (threading.Lock或multiprocessing.Lock) 防止競爭條件。
- 針對同一檔案使用
總結
r、w、a、b是 Python 檔案 I/O 的基礎模式,分別代表讀取、寫入(覆寫)、追加與二進位操作。- 正確選擇模式能避免 資料遺失、編碼錯誤、資源浪費 等常見問題。
- 使用
with管理檔案、明確指定編碼、分塊讀寫以及適當的例外處理,是寫出 安全、可維護 檔案程式的關鍵。 - 了解這些模式後,你即可在 日誌、資料前處理、檔案備份 等實務情境中自如應對,為 Python 應用奠定穩固的基礎。
掌握檔案的讀寫模式,就等於掌握了 Python 與外部世界溝通的第一扇門。祝你寫程式愉快,檔案永不遺失!