sim*_*ack 1 python bufferedreader
我有一个扩展BufferedReader的类,并且文件流列表b.close()被除最后一个流之外的所有文件调用,我想保持流打开。我该怎么做?
谢谢
类TestReader(BufferedReader):
通过
清晰度测试(流):
用于流中的流:
b = TestReader(流)
do_something(b)
#除了stream [-1]以外的所有流都关闭了,如何防止这种情况发生?
stream = [open('test1.txt','rb'),open('test2.txt','rb')]
测试(流)
stream.do_something_else()
即使在实现BufferedIOBase类中包装IOBase对象,它们的接口也是一个流(一切都从继承IOBase),所以IOBase对象的常规行为是在超出范围时关闭自身。BufferedIOBase只是将close()调用委托给基础流。
您不应将a BufferedReader视为流包装器(尽管这是如何实现的),而应将其视为现有流的类型转换。 两个流的状态完全绑定在一起。但是,您可以将打包的流与解除绑定detach(),但这会使BufferedIOBase对象无用。
此外,当mode 为时,已经io.open返回一个,因此您要进行双缓冲。您应该改用。BufferedReaderrbio.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
Run Code Online (Sandbox Code Playgroud)detach()BufferedIOBase对象关闭其流之前的基础流。(请记住倒带!)
def test(streams):
for stream in streams:
b=TestReader(stream)
do_something(b)
wrappedstream = b.detach()
assert wrappedstream is stream
Run Code Online (Sandbox Code Playgroud)
您甚至可以在析构函数中实现此目的:
class TestReader(BufferedReader):
def __del__(self):
self.detach()
# self.raw will not be closed,
# rather left in the state it was in at detachment
Run Code Online (Sandbox Code Playgroud)
或者,close()如果您认为语义错误,则完全禁用委派:
class TestReader(BufferedReader):
def close(self):
self.closed = True
Run Code Online (Sandbox Code Playgroud)我对自己的工作没有全面了解(可能需要其他设计),但是这就是我实现所看到的代码的方式:
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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
636 次 |
| 最近记录: |