如何使用 Python open 函数打开文件?以及编码,解码,换行,缓冲等问题

我被代码海扁署名-非商业-禁演绎
阅读 29:32·字数 8862·发布 
Bilibili 空间
关注 950

本节所讲述的是如何在 Python 中打开文件,至于文件的读取和写入,请参考如何使用 Python 文件对象读写文件?以及文件指针,关闭文件,获取文件对象信息等问题一节。本节的“换行₁”一词是指产生新的一行,类似于在编辑器中按下Enter键。

使用 Python open 函数打开文件

通过 Python 的内置函数open,你可以快速的打开某个文件,这不像其他的一些编程语言,比如 C#,需要预先导入特定的模块或命名空间。当然,Pythonopen函数的作用是打开文件而不是访问文件中的内容,你需要调用其返回的文件对象(file object)的相关方法来完成内容的读取或写入。

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

file 参数

file参数是一个表示文件路径的字符串,或整合文件的 Python 文件描述器(file descriptor)。如果该参数是文件路径,那么closefd参数必须是True,否则将引发异常ValueError: Cannot use closefd=False with file name

Python 文件描述器可通过os模块的open函数创建,但请区别于 Python 内置函数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函数(不是 Python 内置函数open)创建了一个文件描述器,并使用该文件描述器打开了文件,由于closefd参数为False,因此当文件被关闭之后,你依然可以通过文件描述器再次打开文件。

需要指出的是,使用文件描述器是没有必要的,一般情况下,应直接调用 Python 函数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
今天天气不错
今天天气不错

为 Python open 函数指定文件打开模式

Pythonopen函数的mode参数可用于设置文件的打开模式,并影响接下来的文件操作,比如,当文件以只读模式打开时,你将无法对文件进行写入。mode参数是一个字符串,他可以是以下值之一,或他们的某种组合。


模式作用
r默认值,表示可读取文件中的内容
w清空文件中的内容,并可将新内容写入文件
a可将内容写入文件,默认追加至文件末尾
x创建新文件,并可将内容写入其中
t默认值,作为文本文件打开
b作为二进制文件打开
+额外允许读取或写入文件

一般情况下,rwax中的一个需要存在于 Pythonopen函数的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不能同时出现,如果希望 Pythonopen函数所打开的文件同时支持读取和写入操作,那么应在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

Python open 函数如何处理文件不存在的情况?

当你选择rwa中的某一个作为mode参数时, Python 的 open 函数将采用不同的方式来处理文件不存在的情况。

对于r模式,如果需要打开的文件不存在,那么 Python open 函数将抛出异常FileNotFoundError: [Errno …] No such file or directory: '…'。对于wa模式,如果需要打开的文件不存在,那么 Python open 函数将立刻创建该文件。

与以上提到的三种模式不同,x模式并不处理文件不存在的情况,相反的,如果被打开的文件已经存在,那么 Python 的 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'

无论是否写入新内容 Python open 函数都将在 w 模式下清空文件中的内容

如果选择w作为文件的打开模式,那么 Pythonopen函数将清空被打开文件中的内容,即便接下来你并没有使用该函数返回的文件对象,将新的内容写入文件。

在下面的示例中,虽然没有通过 Python 文件对象向文件写入数据,但文件中的内容将被清空。

w_clear.py
# 请将命令行跳转至脚本文件 w_clear.py 所在的目录,然后运行他
# 文件 data.txt 中的内容将被清空
open('data.txt', 'w')
data.txt
一些数据

打开二进制文件时不需要为 Python open 函数指定编码格式

对于b模式,你不需要为 Pythonopen函数指定文件的编码格式(即encoding参数),否则将引发异常ValueError: binary mode doesn't take an encoding argument

为 Python open 函数指定缓冲策略

通过 Pythonopen函数的buffering参数,可以为open函数返回的文件对象指定缓冲策略,在缓冲策略的作用下,Python 文件对象会从缓冲区读取数据或将数据写入缓冲区,而不是直接针对文件进行读取和写入,这样做的目的是为了减少存储设备的访问次数,提高代码的执行效率。

对于二进制文件,Pythonopen函数的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')

Python open 函数如何指定文本文件采用行缓冲策略?

对于文本文件,如果 Pythonopen函数的buffering参数为1,那么将采用行缓冲策略,无论open函数的newline参数指定了哪种换行₁方式,当通过文件对象写入\n\r\n\r时,都将使缓冲区中的数据被保存至文件。

这里需要说明的是,你必须明确的通过 Python 文件对象将\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')

为 Python open 函数指定文件的编码格式

当通过 Pythonopen函数打开文本文件时,你应该给出文本文件的编码,即open函数的encoding参数。当然,如果encoding参数被忽略或被设置为空值None,那么open函数将采用 Pythonlocale模块的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 的文件

Python open 函数支持编码格式的别名并且不区分名称的大小写

对于某种编码格式,Python 可能为其定义了别名,以方便开发人员书写代码,比如,utf8utf-8utf_8在运行结果上是相同的。此外,Pythonopen函数也不区分编码格式的名称的大小写,书写utf8Utf8UTF8在运行结果上是相同的。

你可以导入 Python 的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 的文件

解码或编码的字符应该与 Python open 函数的 encoding 参数对应的编码格式兼容

事实上,在调用 Pythonopen函数时,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)

为 Python open 函数指定编码和解码错误的处理方式

Pythonopen函数的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为十六进制数字)。比如,当 Pythonopen函数的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

为 Python open 函数指定换行₁的处理方式

不同的操作系统,可能会以不同的字符来表示文本文件中的换行₁,比如,UNIX/Linux/macOS 通常会将\n视为换行₁(较早版本的 macOS 将\r视为换行₁),Windows 通常会将\r\n视为换行₁。

在使用 Python 的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'

为 Python open 函数自定义文件描述器的创建方式

Pythonopen函数的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

Python open 函数所返回的文件对象的类型

如本节所述,Pythonopen函数的返回值是一个文件对象,该文件对象的类型由open函数的参数来决定。

当 Pythonopen函数尝试打开文本文件时,其返回的文件对象的类型为TextIOWrapper

当 Pythonopen函数尝试使用缓冲区打开二进制文件时,其返回的文件对象的类型可能是BufferedReader(只读),BufferedWriter(只写),BufferedRandom(读写)中的一种。

当 Pythonopen函数尝试打开二进制文件并禁用缓冲区时,其返回的文件对象的类型为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/file_system/file_handling/open·codebeatme/python·GitHub