io.BufferdReader真的支持readline吗



根据文档io.BufferedReader继承io.IOBase:io.IOBase->io.BufferedIOBase->io.BufferedReader。因此,它应该实现readlinereadinto,但事实并非如此,因为我得到了一个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.TextIOWrapperreadline方法就可以工作了。

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'

最新更新