本文 AI 產出,尚未審核

Python 檔案操作(File I/O) – 讀寫模式(r, w, a, b)


簡介

在日常開發中,檔案讀寫是最常見的 I/O 工作之一。無論是寫日誌、儲存使用者設定、還是批次處理大量資料,都離不開對本機檔案的存取。Python 內建的 open() 函式提供了簡潔且統一的介面,讓開發者只需要指定檔案路徑與模式(mode)即可完成讀寫操作。

模式的選擇直接影響檔案的行為:是要讀取覆寫追加,還是以二進位方式處理?了解每個模式的意義與適用情境,是寫出安全、效能良好的檔案程式的第一步。本篇文章將深入說明 rwab 四種基礎模式,搭配實用範例、常見陷阱與最佳實踐,幫助初學者快速上手,也讓中級開發者在大型專案中能更得心應手。


核心概念

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'))或改用文字模式

最佳實踐清單

  1. 使用 with 管理檔案生命週期
    with open('file.txt', 'r') as f:
        data = f.read()
    
  2. 明確設定編碼(尤其跨平台時)
    open('file.txt', 'w', encoding='utf-8')
    
  3. 避免一次讀入過大檔案
    for chunk in iter(lambda: f.read(8192), b''):
        process(chunk)
    
  4. 在寫入前檢查目錄是否存在
    import os
    os.makedirs('logs', exist_ok=True)
    
  5. 使用例外處理捕捉 I/O 錯誤
    try:
        with open('config.json', 'r') as f:
            cfg = json.load(f)
    except FileNotFoundError:
        print('設定檔不存在,使用預設值')
    

實際應用場景

  1. 日誌系統

    • 使用 a 追加模式寫入時間戳記,確保每次執行都不會丟失先前紀錄。
    • 搭配 logging 模組的 FileHandler,自動切割檔案大小。
  2. 資料前處理

    • 大型 CSV 檔案常以 r 逐行讀取,配合 csv 模組進行分欄解析,避免一次載入全部資料。
  3. 檔案備份與同步

    • rb/wb 二進位模式配合 分塊讀寫,在網路傳輸或磁碟備份時降低記憶體使用。
  4. 設定檔管理

    • w 用於產生或重寫 JSON/YAML 設定檔;若需要保留舊設定,可先備份再寫入。
  5. 多執行緒/多行程寫入

    • 針對同一檔案使用 a 模式,配合檔案鎖 (threading.Lockmultiprocessing.Lock) 防止競爭條件。

總結

  • rwab 是 Python 檔案 I/O 的基礎模式,分別代表讀取、寫入(覆寫)、追加與二進位操作。
  • 正確選擇模式能避免 資料遺失編碼錯誤資源浪費 等常見問題。
  • 使用 with 管理檔案、明確指定編碼、分塊讀寫以及適當的例外處理,是寫出 安全、可維護 檔案程式的關鍵。
  • 了解這些模式後,你即可在 日誌、資料前處理、檔案備份 等實務情境中自如應對,為 Python 應用奠定穩固的基礎。

掌握檔案的讀寫模式,就等於掌握了 Python 與外部世界溝通的第一扇門。祝你寫程式愉快,檔案永不遺失!