open() <Python 內(nèi)置函數(shù)>

轉(zhuǎn)載須注明出處:簡書@Orca_J35 | GitHub@orca-j35

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

該函數(shù)用于打開 file 并返回相應(yīng)的 I/O 對象「也稱文件對象(file object)笼蛛,詳見 "I/O 對象" 小節(jié)」,如果打開失敗則會(huì)拋出 OSError茎截。

io.open() 其實(shí)是 open() 函數(shù)的別名别渔,而 os.open 被用于創(chuàng)建文件描述符绎谦。新創(chuàng)建的文件和文件描述符都是不可繼承的(non-inheritable)——文件描述符具有"inheritable"標(biāo)志钉凌,該標(biāo)志指示子進(jìn)程是否可以繼承該文件描述符(可閱讀 Inheritance of File Descriptorsos.open遏考,以了解更多信息)

還可查看文件處理模塊翩腐,以了解更多信息鸟款,例如:fileinputio (聲明 open() 函數(shù)的模塊)茂卦、os何什、os.pathtempfile等龙、shutil处渣。

更新情況:

  • Changed in version 3.3:

    • 添加 opener 參數(shù)

    • 添加 'x' 模式

    • 曾經(jīng)會(huì)拋出的 IOError 異常,現(xiàn)在是 OSError 的別名而咆。

    • 如果以獨(dú)占創(chuàng)建模式 ('x') 打開的文件已存在霍比,則會(huì)拋出 FileExistsError

  • Changed in version 3.4:

    • file 現(xiàn)在屬于 non-inheritable

    • 從 3.4 版本開始已棄用 'U' 模式,待到 4.0 版本時(shí)將移除該模式暴备。

  • Changed in version 3.5:

    • 如果系統(tǒng)調(diào)用被中斷悠瞬,并且信號(hào)處理器(signal handler)沒有拋出異常,open() 函數(shù)現(xiàn)在會(huì)再次嘗試系統(tǒng)調(diào)用涯捻,而不是拋出InterruptedError 異常( 其基本原理詳見 PEP 475)

    • 添加 'namereplace' 錯(cuò)誤處理方案

  • Changed in version 3.6:

    • 支持接收實(shí)現(xiàn) os.PathLike 的對象

    • 在 Windows 上浅妆,打開控制臺(tái)緩沖區(qū)可能會(huì)返回除 io.FileIO 之外的 io.RawIOBase 的子類。

參數(shù)說明

file

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

file 用于設(shè)置需要打開的文件障癌,有以下兩種形式:

  • 可以是一個(gè)表示文件系統(tǒng)路徑(絕對路徑或相對路徑均可)的對象凌外,即 path-like 對象。該對象可以是文本字符串或 byte 字符串涛浙,也可是實(shí)現(xiàn)了 os.PathLike 協(xié)議的對象康辑。

    """./somefile.txt中的內(nèi)容
    first line
    second line
    """
    fin = open(b'somefile.txt')
    print(fin.read())
    print(fin.fileno())  # fileno()會(huì)返回文件描述符
    fin.close()
    """Out:
    first line
    second line
    3
    """
    
  • 還可以是一個(gè)整型文件描述符(integer file descriptor),該描述符代表一個(gè)被打包(wrapped)的文件轿亮,可通過 os.open 創(chuàng)建疮薇。如果給出了文件描述符,那么當(dāng)我們關(guān)閉 open() 返回的 I/O 對象時(shí)我注,該文件描述符也將被關(guān)閉按咒,除非將 closefd 設(shè)置為 False。另外但骨,有些文檔中可能會(huì)混用文件描述符和文件句柄励七,需要注意區(qū)分這兩個(gè)概念。

    """./somefile.txt中的內(nèi)容
    first line
    second line
    """
    import os
    # 使用底層IO打開一個(gè)文件奔缠,并返回其文件描述符(integer)
    fd = os.open('somefile.txt', os.O_RDONLY)
    print("文件描述符的值是 {0}掠抬,類型是 {1}".format(fd, type(fd)))
    f = open(fd, 'r')
    print(f.read())
    f.close()
    # f被關(guān)閉后,對應(yīng)的文件描述符也將被關(guān)閉校哎,
    # 但文件描述符被關(guān)閉后不能再次被打開
    f = open(fd, 'r')
    """Out:
    文件描述符的值是 3两波,類型是 <class 'int'>
    first line
    second line
    Traceback (most recent call last):
      File "c:/Users/iwhal/Desktop/內(nèi)置函數(shù)/BI_open.py", line 13, in <module>
        f = open(fd, 'r')
    OSError: [WinError 6] 句柄無效。
    """
    

    如果需要再次打開文件描述,則需將 closefd 參數(shù)設(shè)置為 False

    """./somefile.txt中的內(nèi)容
    first line
    second line
    """
    import os
    fd = os.open('somefile.txt', os.O_RDONLY)
    # 將closefd設(shè)置為False
    f = open(fd, 'r', closefd=False)
    f.close()
    f = open(fd, 'r')
    print(f.read())
    """Out:
    first line
    second line
    """
    

    擴(kuò)展閱讀: 5.18 將文件描述符包裝成文件對象 - Python Cookbook

mode

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

mode 用于設(shè)定文件的打開模式雨女,默認(rèn)值是 'rt',有如下可用模式:

Character Meaning
'r' open for reading (default)<br />必須保證文件存在阳准,否則會(huì)拋出異常
'w' open for writing , truncating the file first <br />如果文件已存在氛堕,則會(huì)清空現(xiàn)有內(nèi)容;如果文件不存在野蝇,則會(huì)創(chuàng)建該文件讼稚。必須保證文件所在目錄存在,否則會(huì)拋出異常
'x' open for exclusive creation, failing if the file already exists<br />如果文件不存在绕沈,則會(huì)創(chuàng)建該文件锐想,并默認(rèn)以 'wt' 打開;如果文件已存在乍狐,則會(huì)拋出 FileExistsError
'a' open for writing, appending to the end of the file if it exists<br />在某些 Unix 系統(tǒng)中赠摇,這意味著所有寫入都會(huì)被附加到文件的末尾,并且無視 seek 位置
'b' binary mode (以字節(jié)形式讀寫數(shù)據(jù)浅蚪,用于不包含文本的所有文件)<br />在讀寫 raw bytes 時(shí)藕帜,需使用 binary 模式,并且不需要指定編碼方式
't' text mode (default)<br />在文本模式下惜傲,如果未指定 encoding洽故,則依賴平臺(tái)的編碼方式,即調(diào)用locale.getpreferredencoding(False) 來獲取當(dāng)前本地編碼方式盗誊。
'+' open a disk file for updating (reading and writing)
'U' universal newlines mode (deprecated), Use newline to control universal newlines mode.<br />'U' 模式已被棄用时甚,在未來的 Python 版本中將會(huì)引發(fā)異常。該模式在 Python 3 中無效哈踱。

前面四個(gè)( 'r'荒适、'w''x'嚣鄙、'a' )需要和后面三個(gè)( 'b'吻贿、't''+' )組合使用哑子。

對于二進(jìn)制(binary)讀寫訪問舅列,'w+b' 會(huì)截?cái)辔募?0 字節(jié),但 'r+b' 不會(huì)截?cái)辔募则眩@兩種模式在流中都以 0 偏移量為起點(diǎn)帐要。

io 模塊中概述部分所言,Python 會(huì)區(qū)分 binary I/O 和 text I/O: (即使底層操作系統(tǒng)并不會(huì)區(qū)分這兩者弥奸,Python 仍然會(huì)進(jìn)行區(qū)別)

  • 以 binary 模式( 'b' )打開文件后:在讀取文件時(shí)榨惠,會(huì)將文件中的內(nèi)容以 bytes 對象返回,不會(huì)進(jìn)行任何解碼操作;在寫入文件時(shí)赠橙,會(huì)將 bytes 對象直接寫入文件耽装,不會(huì)進(jìn)行任何編碼操作。在使用 binary 模式時(shí)期揪,需保持 encoding=None掉奄。

  • 以 text 模式( 't' )打開文件后:在讀取文件時(shí),會(huì)先對讀取到的字節(jié)進(jìn)行解碼凤薛,再以 str 對象返回解碼后的內(nèi)容姓建;在寫入文件時(shí),會(huì)先對被寫入的 str 對象進(jìn)行編碼缤苫,再將編碼得到的字節(jié)寫入文件速兔。在 text 模式下,如果未指定 encoding活玲,則依賴平臺(tái)的編碼方案涣狗,即調(diào)用locale.getpreferredencoding(False) 來獲取當(dāng)前本地編碼方案。

    在 Windows 下舒憾,默認(rèn)的編碼方式是 cp936:

    >>> import locale
    >>> locale.getpreferredencoding(False)
    'cp936'
    

注意:Python 不依賴于底層操作系統(tǒng)定義的文本文件的概念屑柔;所有處理都由 Python 本身完成,因此與平臺(tái)無關(guān)珍剑。

示例 - 展示 binary 模式和 text 模式的區(qū)別

with open('a_file.txt', 'r+b') as fin:
    # 在binary模式下會(huì)直接向文件寫入字節(jié)
    fin.write(b'orca_j35 ' + bytes('鯨', 'utf8'))
    fin.seek(0)
    # 讀取之前寫入的字節(jié)
    print(fin.read())

with open('a_file.txt', 'r+', encoding='utf8') as fin:
    # 在text模式下掸宛,會(huì)先對讀取到的字節(jié)進(jìn)行解碼,再以字符串對象返回解碼后的內(nèi)容
    print(fin.read())
"""Out:
b'orca_j35 \xe9\xb2\xb8'
orca_j35 鯨
"""

buffering

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

buffering 用于設(shè)置緩沖策略(buffering policy)招拙,可以是以下整數(shù)值:

  • 0 to switch buffering off (only allowed in binary mode, raise ValueError in text mode) - 會(huì)立即把內(nèi)容輸出至流文件唧瘾,不會(huì)進(jìn)行緩存

    >>> f=open('test.txt', 'w+b')
    # 此時(shí)test.txt中沒有何內(nèi)容
    >>> f.write(b'a')
    1
    # 此時(shí)test.txt中仍然沒有何內(nèi)容,會(huì)先將輸出至文件對象的數(shù)據(jù)進(jìn)行緩存
    # 待文件對象關(guān)閉時(shí)别凤,才會(huì)將緩存的數(shù)據(jù)寫入文件對象
    >>> f.close()
    # 此時(shí)test.txt中出現(xiàn)'a'
    
    >>> f=open('test.txt', 'w+b', 0)
    # 此時(shí)test.txt中沒有何內(nèi)容
    >>> f.write(b'a')
    1
    # 此時(shí)test.txt中出現(xiàn)'a'
    # buffering=0時(shí)不會(huì)緩存數(shù)據(jù)饰序,會(huì)立即把內(nèi)容輸出到流文件,不用等文件對象關(guān)閉后再寫入
    >>> f.close()
    
    # buffering=0不能用于text模式,否則會(huì)拋出異常
    >>> f=open('test.txt', 'wt', 0)
    Traceback (most recent call last):
      File "<pyshell#15>", line 1, in <module>
        f=open('test.txt', 'wt', 0)
    ValueError: can't have unbuffered text I/O
    
  • 1 to select line buffering (only usable in text mode) - 每次緩存一行數(shù)據(jù)规哪,行分隔符由 newline 參數(shù)決定求豫。

    >>> f=open('test.txt', 'w+t', 1)
    # 此時(shí)test.txt中沒有何內(nèi)容
    >>> f.write('abc')
    3
    # 此時(shí)test.txt中仍沒有何內(nèi)容
    >>> f.write('cde\n')
    4
    # 此時(shí)test.txt中出現(xiàn)'abccde'
    >>> f.write('efg\r')
    4
    # 此時(shí)test.txt中出現(xiàn)'efg'
    
    # buffering=1對binary模式無效
    >>> f=open('test.txt', 'w+b', 1)
    # 此時(shí)test.txt中沒有何內(nèi)容
    >>> f=open('test.txt', 'w+b', 1)
    >>> f.write(b'abc\n')
    4
    >>> f.write(b'def\r')
    4
    # 此時(shí)test.txt中仍沒有何內(nèi)容
    >>> f.close()
    # 此時(shí)test.txt中出現(xiàn)'abc'和'def'
    
  • an integer > 1 to indicate the size in bytes of a fixed-size chunk buffer - 將緩沖器設(shè)置為給定的尺寸,當(dāng)緩沖器中數(shù)據(jù)的尺寸大于該長度時(shí)诉稍,便會(huì)向文件對象寫入一次數(shù)據(jù)蝠嘉。似乎只對 binary 模式有效,對 text 模式無效杯巨。

    >>> f=open('test.txt', 'w+b', 2)
    >>> f.write(b'ab')
    2
    # 此時(shí)test.txt中沒有何內(nèi)容
    >>> f.write(b'c')
    1
    # 此時(shí)test.txt中出現(xiàn) 'ab'蚤告,但沒有'c'
    >>> f.close()
    # 此時(shí)test.txt中出現(xiàn) 'ab'和'c'
    

如果沒有給出 buffering 參數(shù),默認(rèn)緩沖策略的工作方式如下:

  • Binary files are buffered in fixed-size chunks; the size of the buffer is chosen using a heuristic trying to determine the underlying device’s “block size” and falling back on io.DEFAULT_BUFFER_SIZE. On many systems, the buffer will typically be 4096 or 8192 bytes long.

    即服爷,二進(jìn)制文件會(huì)以固定尺寸的緩沖器塊進(jìn)行緩存

  • “Interactive” text files (files for which isatty() returns True) use line buffering. Other text files use the policy described above for binary files.

encoding

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

encoding 用于設(shè)置字符編碼方案杜恰,在編碼(或解碼)文件內(nèi)容時(shí)便會(huì)使用該編碼方案获诈,該參數(shù)只能用于 text 模式。在 codecs 模塊中列舉了 Python 支持的編碼方案心褐。

當(dāng) encoding=None 時(shí)舔涎,編碼方案取決于當(dāng)前平臺(tái),會(huì)通過 locale.getpreferredencoding(False) 來獲取當(dāng)前本地編碼方案逗爹。在 Windows 下终抽,默認(rèn)的編碼方式是 cp936:

>>> import locale
>>> locale.getpreferredencoding(False)
'cp936'

errors

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

errors 用于設(shè)置錯(cuò)誤處理方案,當(dāng)出現(xiàn)編碼(或解碼)錯(cuò)誤時(shí)桶至,便會(huì)使用此錯(cuò)誤處理方案,該參數(shù)不能用于 binary 模式匾旭,默認(rèn)采用 'strict'镣屹。

errors 的實(shí)參值可以是 Error Handlers 中列出的標(biāo)準(zhǔn)錯(cuò)誤處理方案;也可以是已在 codecs.register_error() 注冊過的任何錯(cuò)誤處理方案的名稱价涝。

標(biāo)準(zhǔn)錯(cuò)誤處理方案包括:

  • 'strict' to raise a ValueError exception if there is an encoding error. The default value of None has the same effect.
  • 'ignore' ignores errors. Note that ignoring encoding errors can lead to data loss.
  • 'replace' causes a replacement marker (such as '?') to be inserted where there is malformed data.
  • 'surrogateescape' will represent any incorrect bytes as code points in the Unicode Private Use Area ranging from U+DC80 to U+DCFF. These private code points will then be turned back into the same bytes when the surrogateescape error handler is used when writing data. This is useful for processing files in an unknown encoding.
  • 'xmlcharrefreplace' is only supported when writing to a file. Characters not supported by the encoding are replaced with the appropriate XML character reference &#nnn;.
  • 'backslashreplace' replaces malformed data by Python’s backslashed escape sequences.
  • 'namereplace' (also only supported when writing) replaces unsupported characters with \N{...} escape sequences.

還可閱讀 codecs.register 的文檔或是運(yùn)行 'help(codecs.Codec)' 女蜈,來了解各種錯(cuò)誤處理方案。

with open('a_file.txt', 'w', encoding='utf8') as fin:
    fin.write('逆戟鯨 orca_j35')
with open('a_file.txt', 'r', encoding='utf8') as fin:
    print(fin.read())
with open('a_file.txt', 'r', encoding='ascii', errors='ignore') as fin:
    print(fin.read())
with open('a_file.txt', 'r', encoding='ascii', errors='replace') as fin:
    print(fin.read())
'''Out:
逆戟鯨 orca_j35
 orca_j35
????????? orca_j35
'''

newline

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

newline 用于控制通用換行符模式( 'U' )的工作方式色瘩,只能用于 text 模式伪窖,其值可以是None''居兆、'\n'覆山、'\r''\r\n'泥栖,具體工作方式如下:

  • 從流中讀取輸入數(shù)據(jù)時(shí):
    • 如果 newline=None簇宽,則會(huì)啟用通用換行符模式。輸入數(shù)據(jù)中的行分隔符可以是 '\n'吧享、'\r''\r\n'魏割,但在將數(shù)據(jù)返回給調(diào)用者之前,這三種換行符均會(huì)被轉(zhuǎn)換為 '\n'钢颂。
    • 如果 newline=''钞它,同樣會(huì)啟用通用換行符模式,但會(huì)將換行符原樣返回給調(diào)用者殊鞭,不會(huì)對換行符進(jìn)行轉(zhuǎn)換遭垛。
    • 如果 newline'\n''\r'操灿、'\r\n' 三者之一耻卡,則在讀取數(shù)據(jù)時(shí)僅會(huì)將 newline 視作行分隔符,并且會(huì)將換行符原樣返回給調(diào)用者牲尺,不會(huì)對換行符進(jìn)行轉(zhuǎn)換卵酪。
  • 向流中寫入輸出數(shù)據(jù)時(shí):
    • 如果 newline=None幌蚊,則會(huì)將輸出數(shù)據(jù)中所有的 '\n' 字符轉(zhuǎn)換為系統(tǒng)默認(rèn)的行分隔符(即,os.linesep)溃卡。

      with open('a_file.txt', 'w+t', newline=None) as fin:
          fin.write('a_\r')
          fin.write('b_\n')
          fin.write('c_\r\n')
      '''a_file.txt中的內(nèi)容如下:
      a_?
      b_??
      c_?
      ??
      '''
      
    • 如果 newline'''\n'溢豆,則會(huì)將輸出數(shù)據(jù)中的行分隔符原樣保留。

      with open('a_file.txt', 'w+t', newline='') as fin:
          fin.write('a_\r')
          fin.write('b_\n')
          fin.write('c_\r\n')
      '''a_file.txt中的內(nèi)容如下:
      a_?
      b_?
      c_??
      '''
      
    • 如果 newline'\r''\r\n'瘸羡,則會(huì)將輸出數(shù)據(jù)中所有的 '\n' 字符裝換為 newline漩仙。

      with open('a_file.txt', 'w+t', newline='\r') as fin:
          fin.write('a_\r')
          fin.write('b_\n')
          fin.write('c_\r\n')
      '''a_file.txt中的內(nèi)容如下:
      a_?
      b_?
      c_?
      ?
      '''
      with open('a_file.txt', 'w+t', newline='\r\n') as fin:
          fin.write('a_\r')
          fin.write('b_\n')
          fin.write('c_\r\n')
      '''a_file.txt中的內(nèi)容如下:
      a_?
      b_??
      c_?
      ??
      '''
      

closefd

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

如果 closefd=False 并且 file 的值是文件描述符,當(dāng)我們關(guān)閉 open() 返回的文件對象時(shí)犹赖,底層文件描述符依舊會(huì)保持打開狀態(tài)队他。

如果 closefd=True 并且 file 的值是文件描述符,當(dāng)我們關(guān)閉 open() 返回的文件對象時(shí)峻村,底層文件描述符也將被關(guān)閉麸折。

如果 file 的值是某個(gè)路徑,那么 closefd 必須保持默認(rèn)狀態(tài)(True)粘昨,否則會(huì)拋出異常垢啼。

opener

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

opener 用于設(shè)置自定義開啟器(opener)。調(diào)用開啟器( 即 opener(file, flags) )后张肾,可獲得文件對象的底層文件描述符芭析。開啟器的返回值必須是一個(gè)打開的文件描述符。opener=os.openopener=None 的等效吞瞪。

The following example uses the dir_fd parameter of the os.open() function to open a file relative to a given directory:

在下面這個(gè)示例中馁启,將使用 os.open() 函數(shù)的 dir_fd 參數(shù)來打開相對于給定目錄的文件:

>>> import os
>>> dir_fd = os.open('somedir', os.O_RDONLY)
>>> def opener(path, flags):
...     return os.open(path, flags, dir_fd=dir_fd)
...
>>> with open('spamspam.txt', 'w', opener=opener) as f:
...     print('This will be written to somedir/spamspam.txt', file=f)
...
>>> os.close(dir_fd)  # don't leak a file descriptor

I/O 對象

如需了解以下 I/O 對象包含的屬性,請查看筆記『io — Core tools for working with streams.md』

open() 函數(shù)返回的 I/O 對象的類型取決于 mode 參數(shù):

  • 當(dāng)以 text 模式('w', 'r', 'wt', 'rt', etc.)打開某個(gè)文件時(shí)芍秆,將返回 io.TextIOBase 的子類( io.TextIOWrapper)的實(shí)例

    with open('a_file.txt', 'r') as fin:
        print(type(fin)) # Out:<class '_io.TextIOWrapper'>
    with open('a_file.txt', 'w') as fin:
        print(type(fin)) # Out:<class '_io.TextIOWrapper'>
    with open('a_file.txt', 'r+') as fin:
        print(type(fin)) # Out:<class '_io.TextIOWrapper'>
    
  • 當(dāng)以 binary 模式打開某個(gè)啟用 buffering 的文件時(shí)进统,將返回 io.BufferedIOBase 的子類的實(shí)例,具體的子類如下:

    • 在 read binary 模式下浪听,將返回 io.BufferedReader 類的實(shí)例
    • 在 write(or append) binary 模式下螟碎,將返回 io.BufferedWriter 類的實(shí)例
    • 在 read/write binary 模式下,將返回 io.BufferedRandom 類的實(shí)例
    # 注意,已啟用buffering,詳見之后的buffering小節(jié)
    with open('a_file.txt', 'rb') as fin:
        print(type(fin)) # Out:<class '_io.BufferedReader'>
    with open('a_file.txt', 'wb') as fin:
        print(type(fin)) # Out:<class '_io.BufferedWriter'>
    with open('a_file.txt', 'r+b') as fin:
        print(type(fin)) # Out:<class '_io.BufferedRandom'>
    
  • 當(dāng)禁用 buffering 時(shí)迹栓,將返回原始流(raw stream)掉分,即 io.RawIOBase 的子類(io.FileIO)的實(shí)例

    # 注意,buffering=0便會(huì)禁用緩沖器,詳見之后的buffering小節(jié)
    with open('a_file.txt', 'rb', 0) as fin:
        print(type(fin)) # Out:<class '_io.FileIO'>
    with open('a_file.txt', 'wb', 0) as fin:
        print(type(fin)) # Out:<class '_io.FileIO'>
    with open('a_file.txt', 'r+b', 0) as fin:
        print(type(fin)) # Out:<class '_io.FileIO'>
    

io 模塊中,各個(gè) I/O 類間的繼承關(guān)系如下:

IOBase
|--RawIOBase
    |--FileIO
|--BufferedIOBase
    |--BytesIO
    |--BufferedReader
    |--BufferedWriter
    |--BufferedRandom
    |--BufferedRWPair
|--TextIOBase
    |--TextIOWrapper
    |--StringIO

可迭代

以上提到的三種 I/O 對象均是可迭代對象:

from collections import abc
with open('a_file.txt', 'r') as fin:
    assert isinstance(fin, abc.Iterable)
with open('a_file.txt', 'rb') as fin:
    assert isinstance(fin, abc.Iterable)
with open('a_file.txt', 'rb', 0) as fin:
    assert isinstance(fin, abc.Iterable)

因此克伊, for line in file: ... 等效于 for line in file.readlines()酥郭。

關(guān)閉 I/O 對象

現(xiàn)代操作系統(tǒng)不允許普通程序直接操作磁盤,對磁盤內(nèi)文件的讀寫功能愿吹,均由操作系統(tǒng)提供的不从。對文件進(jìn)行讀寫,其實(shí)就是請求操作系統(tǒng)打開一個(gè)文件對象(通常稱為文件描述符)犁跪,然后通過操作系統(tǒng)提供的接口向該對象讀/寫數(shù)據(jù)椿息。

在執(zhí)行寫操作時(shí)歹袁,部分 I/O 對象會(huì)先將數(shù)據(jù)緩存到內(nèi)存中(參考 buffering 小節(jié)),并不會(huì)立刻把數(shù)據(jù)寫入磁盤寝优。只有在關(guān)閉 I/O 對象時(shí)条舔,才會(huì)保證把沒有寫入的數(shù)據(jù)全部寫入磁盤(也被稱作 flush)。因此乏矾,在執(zhí)行寫入操作后孟抗,如果沒有關(guān)閉 I/O 對象,則很有可能會(huì)丟失數(shù)據(jù)钻心。另外凄硼,被打開的 I/O 對象還會(huì)占用系統(tǒng)資源。所有捷沸,在使用完 I/O 對象后摊沉,必須確保其正確關(guān)閉。

關(guān)閉 I/O 對象最直接方式是調(diào)用 close() 方法:

fin = open('a_file.txt', 'r')
"""--snip--:操作IO對象亿胸,最后關(guān)閉IO對象"""
fin.close()

這種方式的缺點(diǎn)是,如果在讀寫 I/O 對象的過程中拋出 IOError 異常预皇,便無法關(guān)閉 I/O 對象侈玄。為了確保 I/O 對象被順利關(guān)閉,可使用如下兩種方法:

  • 使用 try...finally 語句

    try:
        fin = open('/path/to/file', 'r')
        """--snip--:操作IO對象吟温,最后關(guān)閉IO對象"""
    finally:
        fin.close()
    
  • 使用 with 語句

    with open("myfile.txt") as f:
        for line in f:
            print(line, end="")
    

關(guān)于 try...finallywith 語句序仙,可閱讀筆記『0x11 錯(cuò)誤、調(diào)試和測試.md 』-> 2. 處理異常

StringIO & BytesIO

io.StringIO 會(huì)在內(nèi)存中創(chuàng)建一個(gè) text I/O 流鲁豪;io.BytesIO 會(huì)在內(nèi)存中創(chuàng)建一個(gè) bytes I/O 流潘悼。
詳見筆記『io — Core tools for working with streams.md』

術(shù)語

file object

An object exposing a file-oriented API (with methods such as read() or write()) to an underlying resource. Depending on the way it was created, a file object can mediate access to a real on-disk file or to another type of storage or communication device (for example standard input/output, in-memory buffers, sockets, pipes, etc.). File objects are also called file-like objects or streams.

There are actually three categories of file objects: raw binary files, buffered binary filesand text files. Their interfaces are defined in the io module. The canonical way to create a file object is by using the open() function.

file-like object

A synonym for file object.

path-like object

An object representing a file system path. A path-like object is either a str or bytesobject representing a path, or an object implementing the os.PathLike protocol. An object that supports the os.PathLike protocol can be converted to a str or bytes file system path by calling the os.fspath() function; os.fsdecode() and os.fsencode() can be used to guarantee a str or bytes result instead, respectively. Introduced by PEP 519.

text file

A file object able to read and write str objects. Often, a text file actually accesses a byte-oriented datastream and handles the text encoding automatically. Examples of text files are files opened in text mode ('r' or 'w'), sys.stdin, sys.stdout, and instances ofio.StringIO.

See also binary file for a file object able to read and write bytes-like objects.

text encoding

A codec which encodes Unicode strings to bytes.

universal newlines

A manner of interpreting text streams in which all of the following are recognized as ending a line: the Unix end-of-line convention '\n', the Windows convention '\r\n', and the old Macintosh convention '\r'. See PEP 278 and PEP 3116, as well asbytes.splitlines() for an additional use.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市爬橡,隨后出現(xiàn)的幾起案子治唤,更是在濱河造成了極大的恐慌,老刑警劉巖糙申,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宾添,死亡現(xiàn)場離奇詭異,居然都是意外死亡柜裸,警方通過查閱死者的電腦和手機(jī)缕陕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來疙挺,“玉大人扛邑,你說我怎么就攤上這事☆砣唬” “怎么了蔬崩?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵恶座,是天一觀的道長。 經(jīng)常有香客問我舱殿,道長奥裸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任沪袭,我火速辦了婚禮湾宙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘冈绊。我一直安慰自己侠鳄,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布死宣。 她就那樣靜靜地躺著伟恶,像睡著了一般。 火紅的嫁衣襯著肌膚如雪毅该。 梳的紋絲不亂的頭發(fā)上博秫,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天,我揣著相機(jī)與錄音眶掌,去河邊找鬼挡育。 笑死,一個(gè)胖子當(dāng)著我的面吹牛朴爬,可吹牛的內(nèi)容都是我干的即寒。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼召噩,長吁一口氣:“原來是場噩夢啊……” “哼母赵!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起具滴,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤凹嘲,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后构韵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體施绎,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年贞绳,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了谷醉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,834評論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡冈闭,死狀恐怖俱尼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情萎攒,我是刑警寧澤遇八,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布矛绘,位于F島的核電站,受9級特大地震影響刃永,放射性物質(zhì)發(fā)生泄漏货矮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一斯够、第九天 我趴在偏房一處隱蔽的房頂上張望囚玫。 院中可真熱鬧,春花似錦读规、人聲如沸抓督。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽铃在。三九已至,卻和暖如春碍遍,著一層夾襖步出監(jiān)牢的瞬間定铜,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工怕敬, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留揣炕,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓赖捌,卻偏偏與公主長得像祝沸,于是被迫代替她去往敵國和親矮烹。 傳聞我的和親對象是個(gè)殘疾皇子越庇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 傷心來襲,我甚至都不知道該不該哭奉狈。
    米粒子閱讀 181評論 0 0
  • 01 昨天二舅父女倆離哈回滬了卤唉。我們所有人都前往火車站為之送行,80歲的二姨也跟著去了仁期。他們兄妹倆估計(jì)是今生最后一...
    魅力春天閱讀 466評論 5 5
  • 一個(gè)關(guān)系好的男生朋友問我: " 你覺得分手后桑驱,給前任的父母發(fā)節(jié)日祝福短信,合理嗎跛蛋? " 我反問他熬的,問他覺得合理嗎?...
    蕭千痕閱讀 322評論 0 0
  • 為什么需要工業(yè)視覺 所謂工業(yè)視覺主要指機(jī)器視覺在工業(yè)上的應(yīng)用赊级,機(jī)器視覺系統(tǒng)主要由圖像的獲取押框、圖像的處理和分析、輸出...
    ZXWD閱讀 2,674評論 0 8