在打开的文件上进行 .seek 的优雅方式

Elegant way to .seek on an open file

我不止一次遇到过这个问题,当你在 python 中打开一个文件时使用 with open 以小字节读取它,一旦你读取了字节,如果在下一行你读了更多的字节,它从你上次调用中断的地方开始。例如:

def read_it(filename):
    with open(filename, "rb") as f:
        print f.read(4)
        print f.read(4)
        print f.read(4)
        print f.read(4)


read_it("test.rtf")
#<= {\rt
#<= f1\a
#<= nsi\
#<= ansi

这个问题的解决方法是在每次读取后添加.seek(0)从头开始:

def read_it(filename):
    with open(filename, "rb") as f:
        print f.read(4)
        f.seek(0)
        print f.read(4)
        f.seek(0)
        print f.read(4)
        f.seek(0)
        print f.read(4)


read_it("test.rtf")
#<= {\rt
#<= {\rt
#<= {\rt
#<= {\rt

但是,如您所见,多次调用 .seek 非常难看。我正在寻找一种更优雅的方式来在每次读取后返回 0。这可能吗?

如前所述,这是 python2,python3 中也有同样的问题:

Python 3.8.8 (tags/v3.8.8:024d805, Feb 19 2021, 13:18:16) [MSC v.1928 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> with open("test.rtf", "rb") as f:
...     print(f.read(4))
...     print(f.read(4))
...     print(f.read(4))
...
b'{\rt'
b'f1\a'
b'nsi\'
>>>

我很快想到了这个:

class Rewinder:

    def __init__(self, fname):
        self.fname = fname
        self.fd = None
    
    def __enter__(self):
        self.fd = open(self.fname)
        return self

    def __exit__(self, exc_type, exc_val, traceback):
        self.fd.close()
        self.fd = None

    def read(self, size=-1):
        try:
            return self.fd.read(size)
        finally:
            self.fd.seek(0)
        

with Rewinder('test.txt') as f:
    print(f.read(4))
    print(f.read(4))
    print(f.read(4))

这是您要找的吗?