注意
python 中,一个需要特别注意的点。
gzip.open()
默认的 mode 参数是rb
,即使设置r
,无论是否有额外的b
,都会以rb
的模式读入。如果需要是文本格式,则必须使用rt
指定它。而,与
gzip.open()
行为相反,open()
中r
表示rt
,而不是rb
。
具体解释
具体解释这里我没有去验证,只是转载和记录下参考文章中的解释。
1、提问
我正在考虑使用
gzip.open()
,我对mode
参数有点困惑:The mode argument can be any of
'r', 'rb', 'a', 'ab', 'w', 'wb', 'x' or 'xb'
forbinary mode
, or'rt', 'at', 'wt', or 'xt'
fortext mode
. The default is 'rb'.
- 那么
w
和wb
之间有什么区别呢?- 文档声明它们都是二进制模式。
- 那么这是否意味着
w
和wb
之间没有区别呢?
2、回答
我只是想展示一些代码,因为它很有趣。
让我们看看 python 库中的 gzip.py 源代码,看看会发生什么,可以在这里找到 gzip.open()
,我在下面报告:
def open(filename, mode="rb", compresslevel=9,
encoding=None, errors=None, newline=None):
"""Open a gzip-compressed file in binary or text mode.
The filename argument can be an actual filename (a str or bytes object), or
an existing file object to read from or write to.
The mode argument can be "r", "rb", "w", "wb", "x", "xb", "a" or "ab" for
binary mode, or "rt", "wt", "xt" or "at" for text mode. The default mode is
"rb", and the default compresslevel is 9.
For binary mode, this function is equivalent to the GzipFile constructor:
GzipFile(filename, mode, compresslevel). In this case, the encoding, errors
and newline arguments must not be provided.
For text mode, a GzipFile object is created, and wrapped in an
io.TextIOWrapper instance with the specified encoding, error handling
behavior, and line ending(s).
"""
if "t" in mode:
if "b" in mode:
raise ValueError("Invalid mode: %r" % (mode,))
else:
if encoding is not None:
raise ValueError("Argument 'encoding' not supported in binary mode")
if errors is not None:
raise ValueError("Argument 'errors' not supported in binary mode")
if newline is not None:
raise ValueError("Argument 'newline' not supported in binary mode")
gz_mode = mode.replace("t", "")
if isinstance(filename, (str, bytes, os.PathLike)):
binary_file = GzipFile(filename, gz_mode, compresslevel)
elif hasattr(filename, "read") or hasattr(filename, "write"):
binary_file = GzipFile(None, gz_mode, compresslevel, filename)
else:
raise TypeError("filename must be a str or bytes object, or a file")
if "t" in mode:
return io.TextIOWrapper(binary_file, encoding, errors, newline)
else:
return binary_file
在函数注释中,我们注意到的几件事:
- 以二进制或文本模式打开 gzip 压缩文件。
- filename 参数可以是实际的文件名(str 或 bytes 对象),也可以是要读取或写入的现有文件对象。
- 模式参数可以是
“r”、“rb”、“w”、“wb”、“x”、“xb”、“a”或“ab”
用于二进制模式
,或“rt”、“wt”、“ xt" 或 "at"
用于文本模式
。 - 默认模式为“rb”,默认压缩级别为 9。
- 对于二进制模式,此函数等效于 GzipFile 构造函数:GzipFile(filename, mode, compresslevel)。在这种情况下,不提供编码、错误和换行参数。
- 对于文本模式,会创建一个 GzipFile 对象,并将其包装在具有指定编码、错误处理行为和行尾的 io.TextIOWrapper() 实例中。
在构造函数中,以下行很重要:
if mode and ('t' in mode or 'U' in mode):
raise ValueError("Invalid mode: {!r}".format(mode))
if mode and 'b' not in mode:
mode += 'b'
if fileobj is None:
fileobj = self.myfileobj = builtins.open(filename, mode or 'rb')
if filename is None:
filename = getattr(fileobj, 'name', '')
if not isinstance(filename, (str, bytes)):
filename = ''
else:
filename = os.fspath(filename)
if mode is None:
mode = getattr(fileobj, 'mode', 'rb')
可以清楚地看到,如果模式中不存在 b
,则将添加。
所以 r 和 rb
、w 和 wb
这两种模式之间没有区别。
参考链接
- Python 3:gzip.open()和模式:https://www.cnpython.com/qa/83479