Python 在打开的文件上查找的优雅方式

Python 在打开的文件上查找的优雅方式,python,io,Python,Io,我不止一次遇到过这个问题,当您在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(

我不止一次遇到过这个问题,当您在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。这可能吗

如前所述,这是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))

这就是您要找的吗?

为什么要多次读取第一个字节?为什么仍然使用过时的Python 2?文件头检测主要是@KlausD,上面只是一个示例,因为一个文件可以检查多种头类型。IE MZ,%PDF,{\RTF,PK,etcStill没有任何意义。除了少数情况下的并发访问外,这应该读取相同的数据四次。假设我必须使用
.seek
,有没有一种优雅的方法来执行此操作?此外,即使您需要不同的长度(例如,如果您需要一个变量作为标题的开头,另一个变量作为整个标题),那么读取所有数据并存储其索引将更有意义。我认为添加一个默认值为0的参数
seek
将更有意义,而不是始终为0,但这似乎是所需要的。
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))