首页 > 解决方案 > io.BufferedReader 是否真的支持 readline?

问题描述

根据文档 io.BufferedReader继承io.IOBaseio.IOBase-> io.BufferedIOBase-> io.BufferedReader。因此,它应该实现readlineand readinto,但似乎并非如此,因为我得到了AttributeError. 一个最小的例子:

数据样本:

$ printf 'foo bar\nspam ham\n' | 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.TextIOWrapper退出io.BufferedReader包装字节流,并且该readline方法将起作用。

import gzip
import io

with io.TextIOWrapper(io.BufferedReader(gzip.open('compressed_file.gz'))) as buffer:
    buffer.readline()

似乎_io.TextIOWrapper返回的实例io.BufferedReaderio.TextIOWrapper实例不同,尽管后者是直接从_io.

标签: pythoniopython-3.6

解决方案


是的,您确实缺少一个关键细节:BufferedReader环绕现有RawIOBase对象:

io.BufferedReader 类(原始,buffer_size=DEFAULT_BUFFER_SIZE)

提供对可读、顺序RawIOBase对象的更高级别访问的缓冲区。

而且因为您已经以文本模式打开了 gzip 文件,所以它不是一个RawIOBase实例:

>>> f = gzip.open('compressed_file.gz', 'rt')
>>> isinstance(f, io.RawIOBase)
False

换句话说,这是一个用户错误。

如果你包装一个BufferedReader二进制文件,你会发现该readline方法工作得很好:

>>> io.BufferedReader(io.BytesIO(b'foo\nbar')).readline()
b'foo\n'

推荐阅读