这个用例就是基于某个文件对象创建多个生成器,而不会有任何相互篡改的读取状态。
最初我(我认为)有一个使用seek()
和tell()
的工作实现,其中每个生成器都由一个元生成器修饰,该生成器维护文件句柄位置。这在StringIO
之类的工作上运行良好,但由于预读缓冲区毁坏了offset,因此在实际文件上失败了。
使用readline()
或以其他方式模拟真实的文件对象是不可行的,因为这样做的原因是过大的文件首先提示生成器表达式。因此,丢失预读缓冲区并不是一个很好的选择(顺便说一下,为什么Python首先以这种方式实现?不应该将缓冲区当作缓存而不是实际暴露给用户?正确的封装应该首先阻止这个tell()
问题......)
然后我尝试使用copy.copy
,但结果如下:<closed file '<uninitialized file>', mode '<uninitialized file>' at 0x7f722ffda810>
。哪个似乎无法使用。
是否存在另一种复制方式?有没有办法初始化文件对象?或者我应该完全放弃这个用例,因为它在Python中是不可能的?
答案 0 :(得分:5)
您正在寻找itertools.tee
。
from itertools import tee
with open("somefile.txt", "r") as fh:
fh1, fh2, fh3 = tee(fh, 3)
调用tee
后,请勿再次使用父迭代器。但是,tee
返回的迭代器可以自由独立地使用。
对于文件对象(保留特定于文件的方法,如read
),您可以多次打开文件;每个文件对象在读取文件时都会保留自己的文件指针。
fh1, fh2, fh3 = [open("somefile.txt") for i in range(3)]
或者,如果您已有文件对象fh
:
fh1, fh2, fh3 = [open(fh.name) for i in range(3)]
这并不能保留已经很高级的文件指针,但它很容易上手:
for x in fh1, fh2, fh3:
x.seek(fh.tell())