如何使用 Python open 函数打开文件?以及编码,解码,换行,缓冲等问题
本节所讲述的是如何在 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 所在的目录,然后运行他
# 使用 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')
今天天气不错
今天天气不错
为 Python open 函数指定文件打开模式
Pythonopen
函数的mode
参数可用于设置文件的打开模式,并影响接下来的文件操作,比如,当文件以只读模式打开时,你将无法对文件进行写入。mode
参数是一个字符串,他可以是以下值之一,或他们的某种组合。
模式 作用 r 默认值,表示可读取文件中的内容 w 清空文件中的内容,并可将新内容写入文件 a 可将内容写入文件,默认追加至文件末尾 x 创建新文件,并可将内容写入其中 t 默认值,作为文本文件打开 b 作为二进制文件打开 + 额外允许读取或写入文件
一般情况下,r
,w
,a
,x
中的一个需要存在于 Pythonopen
函数的mode
参数中,否则异常ValueError: Must have exactly one of create/read/write/append mode and at most one plus
将被抛出,并且r
,w
,a
,x
不能同时出现,比如,rw
或ra
这样的模式是无效的,异常ValueError: must have exactly one of create/read/write/append mode
将被抛出。
由于r
,w
,a
,x
不能同时出现,如果希望 Pythonopen
函数所打开的文件同时支持读取和写入操作,那么应在mode
参数中增加+
,比如,r+
,w+
。
此外,一些模式组合是明显无效的,比如,rtb
是无效的,因为无法将一个文件同时作为文本文件和二进制文件打开。
Python 3.11 版本移除了U
模式。
# 请将命令行跳转至脚本文件 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 函数如何处理文件不存在的情况?
当你选择r
,w
和a
中的某一个作为mode
参数时, Python 的 open 函数将采用不同的方式来处理文件不存在的情况。
对于r
模式,如果需要打开的文件不存在,那么 Python open 函数将抛出异常FileNotFoundError: [Errno …] No such file or directory: '…'
。对于w
和a
模式,如果需要打开的文件不存在,那么 Python open 函数将立刻创建该文件。
与以上提到的三种模式不同,x
模式并不处理文件不存在的情况,相反的,如果被打开的文件已经存在,那么 Python 的 open 函数将抛出异常FileExistsError: [Errno …] File exists: '…'
。
在下面的示例中,使用a
模式打开文件no.md
,将导致该文件被自动创建。
# 请将命令行跳转至脚本文件 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 所在的目录,然后运行他
# 文件 data.txt 中的内容将被清空
open('data.txt', 'w')
一些数据
打开二进制文件时不需要为 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 所在的目录,然后运行他
# 设置缓冲区的大小为 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 所在的目录,然后运行他
# 启用行缓冲策略
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 所在的目录,然后运行他
# 使用编码格式 utf-8 打开文件 utf8.txt
file = open('utf8.txt', 'r', encoding='utf8')
print(file.read())
这是编码格式为 utf-8 的文件
这是编码格式为 utf-8 的文件
Python open 函数支持编码格式的别名并且不区分名称的大小写
对于某种编码格式,Python 可能为其定义了别名,以方便开发人员书写代码,比如,utf8
,utf-8
和utf_8
在运行结果上是相同的。此外,Pythonopen
函数也不区分编码格式的名称的大小写,书写utf8
,Utf8
或UTF8
在运行结果上是相同的。
你可以导入 Python 的encodings
模块,并通过表达式encodings.aliases.aliases
来获得所有编码格式的别名与他们对应的编码格式名称。表达式encodings.aliases.aliases
将返回一个形式为{alias:name}
的字典对象,其中alias
为编码格式的别名,name
为编码格式在 Python 中的名称。
# …
# 使用编码格式 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
的文件,可以正常的读取和写入文本,因为utf8
与ascii
兼容,只不过最终文件的编码格式可能是utf8
,如果文件被真实保存的话。
在下面的示例中,虽然我们使用编码格式ascii
打开了编码格式为utf8
的文件diff.txt
,但保存文件之后,diff.txt
的编码格式依然为utf8
。
# 请将命令行跳转至脚本文件 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
这里的字符将以编码格式 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 编码值在DC80
与DCFF
之间的字符出现了编码错误,那么出错的字符将被替换为代理码(比如,编码值为DC80
的字符会被替换为值为80
的代理码),这样在进行解码时,代理码便可再次被替换回原本的字符(比如,值为80
的代理码被替换回编码值为DC80
的字符)。
在下面的示例中,我们采用不同的错误处理方式读取文件error.txt
,该文件包含了汉字和英文字母,这将导致编码格式为ascii
的 Python 文件对象在读取文件时会出现解码错误。
# 请将命令行跳转至脚本文件 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')
今天 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 所在的目录,然后运行他
# 函数 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 所在的目录,然后运行他
# 尝试将 \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 文件对象的readline
和readlines
方法,不同的newline
参数会导致readline
和readlines
方法将不同的字符视为一行的结束。
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.txt
,line_rn.txt
,line_r.txt
,他们分别包含内容\n\n
,\r\n\r\n
,\r\r
。以不同的换行₁方式打开他们之后,Python 文件对象的readlines
方法将返回不同的结果。
# 请将命令行跳转至脚本文件 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 所在的目录,然后运行他
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)
的参数,其中file
和flags
的值将根据open
函数的其他参数来确定,返回的文件描述器将用于打开文件。
在下面的示例中,我们定义了函数myopener
作为opener
参数的值,该函数只会返回用于读取操作的文件描述器,因此,所有对文件的写入操作都将是无效的。
# 请将命令行跳转至脚本文件 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('写点东西')
我始终是只读的
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 所在的目录,然后运行他
# 读取文本文件
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