即使在实施BufferedIOBase
类包装的IOBase
对象,它们的接口是一个流(一切从IOBase
继承),所以IOBase
对象的普通行为是封闭自己当他们超出范围。 BufferedIOBase
只是将close()
调用委托给基础流。
您不应将BufferedReader
视为流包装(尽管它是如何实现的),而是作为对现有流的类型转换。两条河流的状态完全结合在一起。但是,您可以使用detach()
取消绑定包装流,但这会使BufferedIOBase
对象无用。
此外,当模式为rb
时,io.open
已返回BufferedReader
,所以您是双缓冲。您应该改用io.FileIO
。
您有几种选择:
创建一个新的物流和新底层的文件描述符,并通过周围的文件名,而不是流。这是您最简单和最安全的选择。
根据需要创建原始文件描述符并根据它们创建流。这需要一些 注意多个流不同时使用相同的文件描述符。例如:
fd = os.open('test.txt', os.O_RDONLY)
file1 = FileIO(fd, 'r', closefd=False)
file2 = FileIO(fd, 'r', closefd=False)
file1.read(100)
assert file1.tell() == 100
file2.read(100)
assert file1.tell() == 200
detach()
底层流的BufferedIOBase
对象之前关闭其流。 (记住,倒转流!)
def test(streams):
for stream in streams:
b=TestReader(stream)
do_something(b)
wrappedstream = b.detach()
assert wrappedstream is stream
你甚至可以在你的析构函数实现这一点:
class TestReader(BufferedReader):
def __del__(self):
self.detach()
# self.raw will not be closed,
# rather left in the state it was in at detachment
或者只是禁用close()
代表团完全,如果你认为语义是错误的:
class TestReader(BufferedReader):
def close(self):
self.closed = True
我不知道你在做什么(可能你需要一个不同的des ign),但这是我将如何实现我看到的代码:
from io import FileIO, BufferedReader
import io
import os
class TestReader(BufferedReader):
pass
def test(streams):
for stream in streams:
b = TestReader(stream)
def test_reset(streams):
"""Will try to leave stream state unchanged"""
for stream in streams:
pos = stream.tell()
b = TestReader(stream)
do_something(b)
b.detach()
stream.seek(pos)
filenames = ['test1.txt', 'test2.txt']
# option 1: just make new streams
streams = [FileIO(name, 'r') for name in filenames]
test(streams)
streams = [io.open(name, 'rb') for name in filenames]
#etc
# option 2: use file descriptors
fds = [os.open(name, os.O_RDONLY) for name in filenames]
#closefd = False means "do not close fd on __del__ or __exit__"
#this is only an option when you pass a fd instead of a file name
streams = [FileIO(fd, 'r', closefd=False) for fd in fds]
test(streams)
streams = []
for fd in fds:
os.lseek(fd, 0, os.SEEK_SET)
streams.append(io.open(fd, 'rb', closefd=False))
# you can also .seek(0) on the BufferedReader objects
# instead of os.lseek on the fds
# option 3: detach
streams = [FileIO(name, 'r') for name in filenames]
test_reset(streams)
# streams[*] should still be in the same state as when you passed it in
实际上,在您的评论出现的位置,流仍处于打开状态。 – 2011-12-25 20:09:50
不,他们不是,尝试做流[0] .read() – simonzack 2011-12-25 20:12:01
嗯,你是对的,我在我的测试脚本中有一个错误。 – 2011-12-25 20:17:09