URLhttps://learnscript.net/zh-hant/python/file-system/files/open/
    複製連結移至說明  範例

    如何使用 open 函式開啟檔案?以及編碼,解碼,換行,緩沖等問題

    閱讀 29:08·字數 8744·發佈 
    Youtube 頻道
    訂閱 375

    本節所講述的是如何在 Python 中開啟檔案,至於檔案的讀取和寫入,請參考如何使用 Python 檔案物件讀取及寫入檔案?以及檔案指標,關閉檔案,取得檔案物件資訊等問題一節。本節的「換行₁」一詞是指產生新的一行,類似於在編輯器中按下Enter鍵。

    使用 open 函式開啟檔案

    通過 Python 的內建函式open,你可以快速的開啟某個檔案,這不像其他的一些程式設計語言,比如 C#,需要預先匯入特定的模組或命名空間。當然,open函式的作用是開啟檔案而不是存取檔案中的內容,你需要呼叫其傳回的檔案物件(file object)的相關方法來完成內容的讀取或寫入。

    open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)

    file 參數

    file參數是一個表示檔案路徑的字串,或類路徑(path-like)物件,或整合檔案的 Python 檔案描述器(file descriptor)。如果該參數是檔案路徑,那麽closefd參數必須是True,否則將引發例外狀況ValueError: Cannot use closefd=False with file name

    Python 檔案描述器可通過os模組的open函式建立,但請區別於內建函式open,他們並不相同。

    mode 參數

    mode參數是一個字串,用於指示檔案的開啟模式,比如r(讀取)。該參數的具體用法,請參考指定檔案開啟模式一段。

    buffering 參數

    buffering參數是一個整數,用於表示緩沖策略。該參數的具體用法,請參考指定緩沖策略一段。

    encoding 參數

    encoding參數是一個字串,用於表示被開啟的文字檔案的編碼格式。該參數的具體用法,請參考指定檔案的編碼格式一段。

    errors 參數

    errors參數是一個字串,用於表示如何處理解碼和編碼錯誤。該參數的具體用法,請參考指定編碼和解碼錯誤的處理方式一段。

    newline 參數

    newline參數是一個字串,用於表示處理換行₁的方式。該參數的具體用法,請參考指定換行₁的處理方式一段。

    closefd 參數

    closefd參數是一個布林值(預設值為True),用於設定當檔案關閉時是否同時關閉file參數對應的檔案描述器,如果為False,那麽不會關閉檔案描述器,這意味著你可以使用檔案描述器再次開啟檔案。當file參數是檔案的路徑時,closefd參數必須保持預設值True,否則將導致例外狀況ValueError: Cannot use closefd=False with file name

    opener 參數

    opener參數是一個傳回檔案描述器的函式或方法,傳回的檔案描述器將用於開啟檔案。該參數的具體用法,請參考自訂檔案描述器的建立方式一段。

    在下面的範例中,我們通過os模組的open函式(不是內建函式open)建立了一個檔案描述器,並使用該檔案描述器開啟了檔案,由於closefd參數為False,因此當檔案被關閉之後,你依然可以通過檔案描述器再次開啟檔案。

    需要指出的是,使用檔案描述器是沒有必要的,一般情況下,應直接呼叫函式open來開啟檔案。

    open_fd.py
    # 請將命令列跳躍至腳本檔案 open_fd.py 所在的目錄,然後執行他
    # 使用 os 模組的 open 函式建立檔案描述器
    import os
    fd = os.open('info.txt', os.O_RDONLY)
    
    # 使用檔案描述器開啟檔案 file = open(fd, encoding='utf8', closefd=False) print(file.read())
    # 不會同時關閉檔案描述器 file.close() # 可以使用檔案描述器再次開啟檔案 open(fd, encoding='utf8')
    info.txt
    今天天氣不錯
    今天天氣不錯

    指定檔案開啟模式

    open函式的mode參數可用於設定檔案的開啟模式,並影響接下來的檔案操作,比如,當檔案以唯讀模式開啟時,你將無法對檔案進行寫入。mode參數是一個字串,他可以是以下值之一,或他們的某種組合。

    
    
    模式作用
    r預設值,表示可讀取檔案中的內容
    w清空檔案中的內容,並可將新內容寫入檔案
    a可將內容寫入檔案,預設追加至檔案末尾
    x建立新檔案,並可將內容寫入其中
    t預設值,作為文字檔案開啟
    b作為二進位檔案開啟
    +額外允許讀取或寫入檔案

    一般情況下,rwax中的一個需要存在於open函式的mode參數中,否則例外狀況ValueError: Must have exactly one of create/read/write/append mode and at most one plus將被擲回,並且rwax不能同時出現,比如,rwra這樣的模式是無效的,例外狀況ValueError: must have exactly one of create/read/write/append mode將被擲回。

    由於rwax不能同時出現,如果希望open函式所開啟的檔案同時支援讀取和寫入操作,那麽應在mode參數中增加+,比如,r+w+

    此外,一些模式組合是明顯無效的,比如,rtb是無效的,因為無法將一個檔案同時作為文字檔案和二進位檔案開啟。

    Python 3.11 版本移除了U模式。

    mode.py
    # 請將命令列跳躍至腳本檔案 mode.py 所在的目錄,然後執行他
    # 可以對檔案進行讀取及寫入,若檔案不存在則引發例外狀況
    file = open('info.txt', 'r+', encoding='utf8')
    
    # 讀取檔案中的行 print(file.readlines()) # 寫入新的行 file.writelines(['\n這是新的一行'])
    # 需要 r,w,a,x 中的一個 try: open('info.txt', 't', encoding='utf8') except ValueError as e: print(e) # r,w,a,x 不能同時出現 try: open('info.txt', 'rw', encoding='utf8') except ValueError as e: print(e)
    ['今天天氣不錯']
    Must have exactly one of create/read/write/append mode and at most one plus
    must have exactly one of create/read/write/append mode

    open 函式如何處理檔案不存在的情況?

    當你選擇rwa中的某一個作為mode參數時,open函式將采用不同的方式來處理檔案不存在的情況。

    對於r模式,如果需要開啟的檔案不存在,那麽open函式將擲回例外狀況FileNotFoundError: [Errno …] No such file or directory: '…'。對於wa模式,如果需要開啟的檔案不存在,那麽open函式將立刻建立該檔案。

    與以上提到的三種模式不同,x模式並不處理檔案不存在的情況,相反的,如果被開啟的檔案已經存在,那麽open函式將擲回例外狀況FileExistsError: [Errno …] File exists: '…'

    在下面的範例中,使用a模式開啟檔案no.md,將導致該檔案被自動建立。

    file_exists.py
    # 請將命令列跳躍至腳本檔案 file_exists.py 所在的目錄,然後執行他
    # 使用 r 模式開啟不存在的檔案 no.md
    try: open('no.md', 'r')
    except FileNotFoundError as e: print(e)
    
    # 使用 a 模式將自動建立不存在的檔案 no.md open('no.md', 'a')
    # 使用 x 模式開啟已經存在的檔案 no.md try: open('no.md', 'x') except FileExistsError as e: print(e)
    # r 模式
    [Errno 2] No such file or directory: 'no.md'
    # x 模式
    [Errno 17] File exists: 'no.md'

    無論是否寫入新內容,open 函式都將在 w 模式下清空檔案中的內容

    如果選擇w作為檔案的開啟模式,那麽open函式將清空被開啟檔案中的內容,即便接下來你並沒有使用該函式傳回的檔案物件,將新的內容寫入檔案。

    在下面的範例中,雖然沒有通過檔案物件向檔案寫入資料,但檔案中的內容將被清空。

    w_clear.py
    # 請將命令列跳躍至腳本檔案 w_clear.py 所在的目錄,然後執行他
    # 檔案 data.txt 中的內容將被清空
    open('data.txt', 'w')
    data.txt
    一些資料

    開啟二進位檔案時不需要指定編碼格式

    對於b模式,你不需要為open函式指定檔案的編碼格式(即encoding參數),否則將引發例外狀況ValueError: binary mode doesn't take an encoding argument

    指定緩沖策略

    通過open函式的buffering參數,可以為open函式傳回的檔案物件指定緩沖策略,在緩沖策略的作用下,Python 檔案物件會從緩沖區讀取資料或將資料寫入緩沖區,而不是直接針對檔案進行讀取和寫入,這樣做的目的是為了減少儲存裝置的存取次數,提高程式碼的執行效率。

    對於二進位檔案,open函式的buffering參數可以是0(如果是文字檔案,buffering參數為0將導致例外狀況ValueError: can't have unbuffered text I/O),這表示不進行緩沖,通過檔案物件寫入的資料將直接儲存至二進位檔案,如果buffering參數的值大於1,那麽buffering參數表示緩沖區的大小。

    如果buffering參數為預設值-1,那麽非互動文字檔案和二進位檔案將采用由運算式io.DEFAULT_BUFFER_SIZE所指定的大小來建立緩沖區,互動文字檔案(檔案物件的isatty方法傳回True)則采用行緩沖策略。

    buffer.py
    # 請將命令列跳躍至腳本檔案 buffer.py 所在的目錄,然後執行他
    # 設定緩沖區的大小為 2
    file = open('buffer_b.txt', 'wb', 2)
    
    # b'1' 將被存放在緩沖區 file.write(b'1') # b'2' 將被存放在緩沖區 file.write(b'2') # b'12' 會被立即儲存至檔案,b'3' 將被存放在緩沖區 file.write(b'3') # b'34567' 會被立即儲存至檔案 file.write(b'4567')

    如何指定文字檔案采用行緩沖策略?

    對於文字檔案,如果open函式的buffering參數為1,那麽將采用行緩沖策略,無論open函式的newline參數指定了哪種換行₁方式,當通過檔案物件寫入\n\r\n\r時,都將使緩沖區中的資料被儲存至檔案。

    這裏需要說明的是,你必須明確的通過檔案物件將\n\r\n\r寫入,呼叫檔案物件的writelines方法並不能觸發行緩沖策略,如果被寫入的字串不包含\n\r\n\r

    在下面的範例中,呼叫方法writelines之後,abc被存放在緩沖區,因為沒有出現\n\r\n\r

    buffer_line.py
    # 請將命令列跳躍至腳本檔案 buffer_line.py 所在的目錄,然後執行他
    # 啟用行緩沖策略
    file = open('buffer_line.txt', 'w', 1, encoding='utf8', newline='')
    
    # abc 不會被立即儲存至檔案 file.writelines(['a', 'b', 'c']) # abcd\r 會被立即儲存至檔案 file.write('d\r') # e\n 會被立即儲存至檔案 file.write('e\n') # f\r\n 會被立即儲存至檔案 file.write('f\r\n')

    指定檔案的編碼格式

    當通過open函式開啟文字檔案時,你應該給出文字檔案的編碼,即open函式的encoding參數。當然,如果encoding參數被忽略或被設定為空值None,那麽open函式將采用locale模組的getencoding方法所傳回的編碼格式,即本機預設的編碼格式。

    雖然 Python 支援大部分的檔案編碼格式,比如常見的utf8,但這並不意味著所有的編碼格式都能夠被 Python 處理。

    encoding.py
    # 請將命令列跳躍至腳本檔案 encoding.py 所在的目錄,然後執行他
    # 使用編碼格式 utf-8 開啟檔案 utf8.txt
    file = open('utf8.txt', 'r', encoding='utf8')
    print(file.read())
    utf8.txt
    這是編碼格式為 utf-8 的檔案
    這是編碼格式為 utf-8 的檔案

    open 函式支援編碼格式的別名並且不區分名稱的大小寫

    對於某種編碼格式,Python 可能為其定義了別名,以方便開發人員書寫程式碼,比如,utf8utf-8utf_8在執行結果上是相同的。此外,open函式也不區分編碼格式的名稱的大小寫,書寫utf8Utf8UTF8在執行結果上是相同的。

    你可以匯入encodings模組,並通過運算式encodings.aliases.aliases來獲得所有編碼格式的別名與他們對應的編碼格式名稱。運算式encodings.aliases.aliases將傳回一個形式為{alias:name}的字典物件,其中alias為編碼格式的別名,name為編碼格式在 Python 中的名稱。

    encoding.py
    # …
    # 使用編碼格式 u8 開啟檔案 utf8.txt
    file = open('utf8.txt', 'r', encoding='u8')
    print(file.read())
    這是編碼格式為 utf-8 的檔案

    解碼或編碼的字元應該與 encoding 參數對應的編碼格式相容

    事實上,在呼叫open函式時,encoding參數所表示編碼格式可以與被開啟的文字檔案的編碼格式不同,但無論如何,在之後通過檔案物件讀取和寫入內容時,被解碼或編碼的字元需要與encoding參數所表示編碼格式相容,否則可能導致例外狀況。

    如果檔案被真實的儲存,那麽最終檔案可能保留其原有的編碼格式,或采用encoding參數所表示編碼格式,或甚至改變為utf8,這取決於編碼格式的相容性(以避免出現亂碼)。

    比如,使用編碼格式utf8開啟編碼格式為ascii的檔案,可以正常的讀取和寫入文字,因為utf8ascii相容,只不過最終檔案的編碼格式可能是utf8,如果檔案被真實儲存的話。

    在下面的範例中,雖然我們使用編碼格式ascii開啟了編碼格式為utf8的檔案diff.txt,但儲存檔案之後,diff.txt的編碼格式依然為utf8

    diff_encoding.py
    # 請將命令列跳躍至腳本檔案 diff_encoding.py 所在的目錄,然後執行他
    # 使用編碼格式 ascii 開啟編碼格式為 utf8 的檔案 diff.txt
    file = open('diff.txt', 'r+', encoding='ascii')
    
    # 無法讀取與 ascii 不相容的 utf8 字元 try: file.readline() except UnicodeDecodeError as e: print(e) # 無法寫入與 ascii 不相容的 utf8 字元 try: file.write('你好!') except UnicodeEncodeError as e: print(e)
    # 可以寫入 ascii 字元 file.writelines(['\nHello!']) # 檔案 diff.txt 被儲存之後,編碼格式依然為 utf8
    diff.txt
    這裏的字元將以編碼格式 ascii 被讀取
    # 讀取 utf8 字元
    'ascii' codec can't decode byte 0xe8 in position 0: ordinal not in range(128)
    # 寫入 utf8 字元
    'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)

    指定編碼和解碼錯誤的處理方式

    open函式的errors參數可用於設定如何處理編碼或解碼錯誤,該參數的作用可能不會在呼叫open函式時體現,因為編碼和解碼通常由open函式傳回的檔案物件執行,Python 檔案物件將按照errors參數給出的錯誤處理方式來處理可能出現的編碼和解碼錯誤。

    以下是errors參數的有效取值。

    None,'strict'

    errors參數的預設值None'strict'具有相同的效果,他們表示當出現編碼或解碼錯誤時,將擲回例外狀況ValueError

    'ignore'

    'ignore'表示忽略出現的編碼和解碼錯誤,當然,這將導致不可預知的結果,因為出現錯誤的內容會被丟棄。比如,Python 檔案物件讀取的內容不會包含編碼或解碼錯誤的部分,檔案物件不會將編碼或解碼錯誤的內容寫入到檔案中。

    'replace'

    'replace'表示會將出現編碼或解碼錯誤的內容取代為特定的字元,比如問號。

    這裏有個有趣的現象,當你使用編碼格式ascii解碼編碼格式為utf8的文字檔案時,一個漢字可能被取代為多個問號。當你使用編碼格式ascii將漢字寫入文字檔案時,一個漢字只會被取代為一個問號。

    'backslashreplace'

    'backslashreplace'表示會將出現編碼或解碼錯誤的內容取代為表示其值的內容(形式可能為\uHHHH\xHH,其中H為十六進位數值)。比如,當open函式的encoding參數為'ascii'時,將與編碼格式ascii不相容的字元寫入檔案,會導致這些字元被取代為類似於\uHHHH的字串。

    'xmlcharrefreplace'

    'xmlcharrefreplace'表示會將出現編碼錯誤的字元取代為該字元對應的 Unicode 編碼值(形式為&#n[n…];,其中n為十進位數值)。需要指出,'xmlcharrefreplace'並不會處理解碼錯誤,因此,當出現解碼錯誤時,可能會有例外狀況被擲回。

    'namereplace'

    'namereplace'表示會將出現編碼錯誤的字元取代為該字元在編碼格式中的名稱(形式為\N{name},其中name為字元的名稱)。需要指出,'namereplace'並不會處理解碼錯誤,因此,當出現解碼錯誤時,可能會有例外狀況被擲回。

    'surrogateescape'

    'surrogateescape'表示如果 Unicode 編碼值在DC80DCFF之間的字元出現了編碼錯誤,那麽出錯的字元將被取代為代理碼(比如,編碼值為DC80的字元會被取代為值為80的代理碼),這樣在進行解碼時,代理碼便可再次被取代回原本的字元(比如,值為80的代理碼被取代回編碼值為DC80的字元)。

    在下面的範例中,我們采用不同的錯誤處理方式讀取檔案error.txt,該檔案包含了漢字和英文字母,這將導致編碼格式為ascii的 Python 檔案物件在讀取檔案時會出現解碼錯誤。

    error_read.py
    # 請將命令列跳躍至腳本檔案 error_read.py 所在的目錄,然後執行他
    
    # 函式 read 將開啟檔案並讀取其中的內容 def read(e): try: file = open('error.txt', 'r', encoding='ascii', errors=e) # 顯示檔案中的內容 text = file.read() print(f'{e} {text}') except Exception as err: print(f'{e} {err}')
    # 使用不同的錯誤處理方式讀取檔案 error.txt read('strict') read('ignore') read('replace') read('backslashreplace')
    error.txt
    今天 is good
    # strict 會擲回例外狀況
    strict 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)
    # ignore 會丟棄出錯的內容
    ignore  is good
    # replace 會將出錯的內容取代為特定字元
    replace ������ is good
    # backslashreplace 會將出錯的內容取代為表示其值的內容
    backslashreplace \xe4\xbb\x8a\xe5\xa4\xa9 is good

    在下面的範例中,我們采用不同的錯誤處理方式,將包含漢字和英文字母的字串寫入文字檔案error.txt,由於 Python 檔案物件的編碼格式為ascii,因此將出現編碼錯誤。

    error_write.py
    # 請將命令列跳躍至腳本檔案 error_write.py 所在的目錄,然後執行他
    
    # 函式 write 將開啟檔案並寫入一些內容 def write(e): try: file = open(f'error_{e}.txt', 'w', encoding='ascii', errors=e) # 將內容寫入檔案 file.write('今天 is good') except Exception as err: print(f'{e} {err}')
    # 使用不同的錯誤處理方式寫入檔案 write('strict') write('ignore') write('replace') write('backslashreplace') write('xmlcharrefreplace') write('namereplace')
    # 檢視檔案中被寫入的內容 for i in ('strict', 'ignore', 'replace', 'backslashreplace', 'xmlcharrefreplace', 'namereplace'): fn = f'error_{i}.txt' file = open(fn, 'r', encoding='ascii') print(f'{fn} {file.read()}')
    # strict 會擲回例外狀況
    strict 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
    error_strict.txt
    # ignore 會丟棄出錯的字元
    error_ignore.txt  is good
    # replace 會將出錯的字元取代為特定字元
    error_replace.txt ?? is good
    # backslashreplace 會將出錯的字元取代為表示其值的內容
    error_backslashreplace.txt \u4eca\u5929 is good
    # xmlcharrefreplace 會將出錯的字元取代為該字元對應的 Unicode 編碼值
    error_xmlcharrefreplace.txt 今天 is good
    # namereplace 會將出錯的字元取代為該字元在編碼格式中的名稱
    error_namereplace.txt \N{CJK UNIFIED IDEOGRAPH-4ECA}\N{CJK UNIFIED IDEOGRAPH-5929} is good

    在下面的範例中,我們采用錯誤處理方式surrogateescape,將內容\udc80\udc81\udc82寫入檔案surrogate.txt,然後讀取該檔案,發現其內容依然為\udc80\udc81\udc82

    如果改為其他的錯誤處理方式,比如replace,那麽再次讀取檔案後,內容將不再是\udc80\udc81\udc82

    surrogateescape.py
    # 請將命令列跳躍至腳本檔案 surrogateescape.py 所在的目錄,然後執行他
    # 嘗試將 \udc80\udc81\udc82 寫入檔案 surrogate.txt
    file = open('surrogate.txt', 'w', encoding='utf8', errors='surrogateescape')
    file.write('\udc80\udc81\udc82')
    
    # 讀取檔案 surrogate.txt 中的內容,並顯示其 Unicode 編碼值 file = open('surrogate.txt', 'r', encoding='utf8', errors='surrogateescape') for c in file.read(): print(hex(ord(c)))
    0xdc80
    0xdc81
    0xdc82

    指定換行₁的處理方式

    不同的作業系統,可能會以不同的字元來表示文字檔案中的換行₁,比如,UNIX/Linux/macOS 通常會將\n視為換行₁(較早版本的 macOS 將\r視為換行₁),Windows 通常會將\r\n視為換行₁。

    在使用open函式時,你可以通過該函式的newline參數來設定如何處理文字檔案中的換行₁,這主要影響 Python 檔案物件的readlinereadlines方法,不同的newline參數會導致readlinereadlines方法將不同的字元視為一行的結束。

    newline參數可以是以下有效取值之一。

    None

    None是參數newline的預設值,他表示當你讀取文字檔案時,檔案中的\n\r\n\r均被視為一行的結束,並且\r\n\r會被取代為\n,當你向檔案寫入\n時,\n將被轉換為系統換行₁方式所對應的字元(即運算式os.linesep的傳回值,他可能是\n\r\n\r)。

    ''

    None類似,''表示當你讀取文字檔案時,檔案中的\n\r\n\r均被視為一行的結束,但\r\n\r不會被取代為\n,當你向檔案寫入\n時,\n不會發生任何變化。

    '\n','\r\n','\r'

    '\n''\r\n''\r'表示當你讀取文字檔案時,分別將檔案中的\n\r\n\r視為一行的結束,當你向檔案寫入\n時,將根據需要將其轉換為\r\n\r

    在下面的範例中,我們有三個文字檔案line_n.txtline_rn.txtline_r.txt,他們分別包含內容\n\n\r\n\r\n\r\r。以不同的換行₁方式開啟他們之後,Python 檔案物件的readlines方法將傳回不同的結果。

    newline_read.py
    # 請將命令列跳躍至腳本檔案 newline_read.py 所在的目錄,然後執行他
    
    # 函式 read_newline 將采用指定的換行₁方式讀取不同的檔案 def read_newline(nl=None): # 依次讀取以 \n,\r\n,\r 為換行₁的檔案 for name in ('n', 'rn', 'r'): fn = f'line_{name}.txt' file = open(fn, 'r', encoding='utf8', newline=nl)
    # 顯示檔案中的每一行 print(file.readlines())

    # 采用不同的換行₁方式讀取不同的檔案 read_newline() read_newline('') read_newline('\n') read_newline('\r\n') read_newline('\r')
    # 預設換行₁方式將 \n,\r\n,\r 視為行的結束,並取代為 \n
    ['\n', '\n']
    ['\n', '\n']
    ['\n', '\n']
    # 換行₁方式 '' 將 \n,\r\n,\r 視為行的結束
    ['\n', '\n']
    ['\r\n', '\r\n']
    ['\r', '\r']
    # 換行₁方式 '\n' 將 \n 視為行的結束
    ['\n', '\n']
    ['\r\n', '\r\n']
    ['\r\r']
    # 換行₁方式 '\r\n' 將 \r\n 視為行的結束
    ['\n\n']
    ['\r\n', '\r\n']
    ['\r\r']
    # 換行₁方式 '\r' 將 \r 視為行的結束
    ['\n\n']
    ['\r', '\n\r', '\n']
    ['\r', '\r']

    在下面的範例中,我們采用不同的換行₁方式將相同的內容\n\r\n\r寫入到不同的文字檔案中,然後檢視他們對字元\n的處理情況。

    newline_write.py
    # 請將命令列跳躍至腳本檔案 newline_write.py 所在的目錄,然後執行他
    no = 1
    
    # 采用不同的換行₁方式寫入相同的內容 for nl in (None, '', '\n', '\r\n', '\r'): fn = f'line_w_{no}.txt' file = open(fn, 'w', encoding='utf8', newline=nl) file.writelines(['\n', '\r\n', '\r'])
    no += 1
    # 檢視檔案中被寫入的內容 for i in range(1, 6): file = open(f'line_w_{i}.txt', 'r', encoding='utf8', newline='') print(file.read().encode())
    # 預設換行₁方式會將 \n 取代為 \r\n
    b'\r\n\r\r\n\r'
    # 換行₁方式 '' 不會改變 \n
    b'\n\r\n\r'
    # 換行₁方式 '\n' 不會改變 \n
    b'\n\r\n\r'
    # 換行₁方式 '\r\n' 會將 \n 取代為 \r\n
    b'\r\n\r\r\n\r'
    # 換行₁方式 '\r' 會將 \n 取代為 \r
    b'\r\r\r\r'

    自訂檔案描述器的建立方式

    open函式的opener參數是一個傳回檔案描述器的函式(或方法),他應擁有形式類似於(file,flags)的參數,其中fileflags的值將根據open函式的其他參數來確定,傳回的檔案描述器將用於開啟檔案。

    在下面的範例中,我們定義了函式myopener作為opener參數的值,該函式只會傳回用於讀取操作的檔案描述器,因此,所有對檔案的寫入操作都將是無效的。

    open_opener.py
    # 請將命令列跳躍至腳本檔案 open_opener.py 所在的目錄,然後執行他
    import os
    
    # 只會傳回用於讀取操作的檔案描述器 def myopener(file, flags): print(f'file {file} flags {flags}') return os.open(file, os.O_RDONLY)
    # 無論選擇哪種開啟模式,檔案都是唯讀的 file = open('opener.txt', 'r', encoding='utf8', opener=myopener) print(file.read()) file = open('opener.txt', 'w', encoding='utf8', opener=myopener) # 雖然沒有例外狀況發生,但檔案 opener.txt 中的內容不會發生變化 file.write('寫點東西')
    opener.txt
    我始終是唯讀的
    file opener.txt flags 32896
    我始終是唯讀的
    file opener.txt flags 33665

    open 函式所傳回的檔案物件的型別

    open函式的傳回值是一個檔案物件,該檔案物件的型別由open函式的參數來決定。

    open函式嘗試開啟文字檔案時,其傳回的檔案物件的型別為TextIOWrapper

    open函式嘗試使用緩沖區開啟二進位檔案時,其傳回的檔案物件的型別可能是BufferedReader(唯讀),BufferedWriter(唯寫),BufferedRandom(讀取及寫入)中的一種。

    open函式嘗試開啟二進位檔案並停用緩沖區時,其傳回的檔案物件的型別為FileIO

    file_object.py
    # 請將命令列跳躍至腳本檔案 file_object.py 所在的目錄,然後執行他
    # 讀取文字檔案
    print(type(open('file_object.txt', 'r')))
    # 讀取二進位檔案
    print(type(open('file_object.txt', 'rb')))
    # 寫入二進位檔案
    print(type(open('file_object.txt', 'wb')))
    # 讀取及寫入二進位檔案
    print(type(open('file_object.txt', 'w+b')))
    # 停用緩沖
    print(type(open('file_object.txt', 'rb', 0)))
    <class '_io.TextIOWrapper'>
    <class '_io.BufferedReader'>
    <class '_io.BufferedWriter'>
    <class '_io.BufferedRandom'>
    <class '_io.FileIO'>

    原始碼

    src/zh-hant/file_system/files/open·codebeatme/python·GitHub