根据文档io.BufferedReader
继承io.IOBase
:io.IOBase
->io.BufferedIOBase
->io.BufferedReader
。因此,它应该实现readline
和readinto
,但事实并非如此,因为我得到了一个AttributeError
。一个最小的例子:
数据样本:
$ printf 'foo barnspam hamn' | gzip -c > compressed_file.gz
测试代码:
import gzip
import io
with io.BufferedReader(gzip.open('compressed_file.gz', 'rt')) as buffer:
buffer.readline()
例外:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-2-215a0d9b4feb> in <module>()
3
4 with io.BufferedReader(gzip.open('compressed_file.gz', 'rt')) as buffer:
----> 5 buffer.readline()
AttributeError: '_io.TextIOWrapper' object has no attribute 'readinto'
我是不是错过了什么?
更新
有趣的是,您可以手动从包装字节流的io.BufferedReader
中获得io.TextIOWrapper
,readline
方法就可以工作了。
import gzip
import io
with io.TextIOWrapper(io.BufferedReader(gzip.open('compressed_file.gz'))) as buffer:
buffer.readline()
io.BufferedReader
返回的_io.TextIOWrapper
实例似乎与io.TextIOWrapper
实例不同,尽管后者是直接从_io
导入的。
是的,您确实缺少一个关键的细节:BufferedReader
包装了一个现有的RawIOBase
对象:
类io.BufferedReader(原始,buffer_size=DEFAULT_buffer_size(
一种提供对可读的、顺序的
RawIOBase
对象进行更高级别访问的缓冲区。
因为您已经在text模式下打开了gzip文件,所以它不是RawIOBase
实例:
>>> f = gzip.open('compressed_file.gz', 'rt')
>>> isinstance(f, io.RawIOBase)
False
换句话说,这是一个用户错误。
如果您将BufferedReader
封装在二进制文件中,您将看到readline
方法工作得很好:
>>> io.BufferedReader(io.BytesIO(b'foonbar')).readline()
b'foon'