即使在實施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