2.27. 讀取與寫入

檔案存在於磁碟上;Python 透過 open() 來存取它們,這個函式會回傳一個檔案物件,其方法可讀取與寫入底層的位元組。

2.27.1. open 與模式

第一個引數是路徑;第二個是模式(mode) -- 一個簡短的字串,告訴 Python 這個檔案將如何被使用:

  • "r" -- 讀取(預設)。開啟一個既有的檔案以供讀取。

  • "w" -- 寫入。建立一個新檔案,或把既有的檔案截斷(truncate)為空。

  • "a" -- 附加。開啟一個檔案以在其結尾寫入,且不會截斷。

  • 在上述任一模式後面附加 "b""rb""wb""ab")-- 二進位模式。檔案的內容是 bytes 而非 str

f = open("notes.txt", "r")
text = f.read()
f.close()

2.27.2. 使用情境管理器

上面的模式,若 open()close 之間有任何東西引發例外,就會洩漏檔案控制代碼。解法是 with 陳述式(參見 情境管理器):

with open("notes.txt") as f:
    text = f.read()

# f is closed here, even if read() failed

這是標準的形式 -- 每次都這樣寫。

2.27.3. 讀取

檔案物件支援數種讀取方式:

  • io.IOBase.read() -- 讀取整個檔案(或 N 個位元組),並將其以單一字串(或 bytes 物件)的形式回傳。

  • io.IOBase.readline() -- 讀取一行,包含結尾的 "\n"

  • 直接迭代檔案會一次產生一行,其記憶體用量遠小於一次讀取整個檔案。

with open("log.txt") as f:
    for line in f:
        print(line.rstrip())

str.rstrip() 會在列印之前移除結尾的換行符號,使輸出不會出現雙倍行距。

2.27.4. 寫入

"w" 模式開啟檔案並使用 io.IOBase.write()

with open("out.txt", "w") as f:
    f.write("hello\n")
    f.write("world\n")

io.IOBase.write() 不會加上換行符號 -- 它只會原原本本寫入你給它的位元組(或在文字模式下為字元)。

2.27.5. 文字模式對二進位模式

文字模式(預設,"r" / "w" 而不帶 "b")會使用預設編碼把進來的位元組解碼成 str,並把出去的 str 編碼回位元組。請用它來處理設定檔、紀錄、JSON -- 任何本質就是文字的東西。

二進位模式("rb" / "wb")會略過解碼步驟並回傳 bytes。請用它來處理影像、struct 封裝的紀錄、網路擷取 -- 任何每個位元組都重要且檔案並非人類可讀的情況。

2.27.6. 列出與移除檔案

os 模組提供了那些不在檔案物件本身上的檔案系統操作:

import os

for name in os.listdir("/"):
    print(name)

當檔案或目錄可能不存在時,請在這些操作周圍攔截 OSError -- 這個操作是實際指令碼中例外經常出現的常見地點之一。