我正在将备份脚本从Shell转换为Python。我的旧脚本的功能之一是通过执行以下操作来检查创建的tarfile的完整性:gzip -t。
在Python中这似乎有些棘手。
似乎唯一的方法是读取tarfile中每个压缩的TarInfo对象。
有没有一种方法可以检查tarfile的完整性,而无需将其提取到磁盘或保留在内存中(完整)?
Freenode上#python上的好人建议我应该逐块读取每个TarInfo对象,丢弃读取的每个块。
我必须承认,我刚刚开始使用Python,所以我不知道该怎么做。
想象一下,我有一个30GB的tarfile,其中包含的文件范围从1kb到10GB …
这是我开始写的解决方案:
try: tardude = tarfile.open("zero.tar.gz") except: print "There was an error opening tarfile. The file might be corrupt or missing." for member_info in tardude.getmembers(): try: check = tardude.extractfile(member_info.name) except: print "File: %r is corrupt." % member_info.name tardude.close()
这段代码还远远没有完成。我不敢在庞大的30GB的tar存档上运行此命令,因为在某一时刻,检查对象将是10 + GB(如果我在tar存档中有如此大的文件)
奖励:我尝试手动破坏zero.tar.gz(十六进制编辑器-编辑几个字节的中间文件)。第一个除外不捕获IOError …这是输出:
Traceback (most recent call last): File "./test.py", line 31, in <module> for member_info in tardude.getmembers(): File "/usr/lib/python2.7/tarfile.py", line 1805, in getmembers self._load() # all members, we first have to File "/usr/lib/python2.7/tarfile.py", line 2380, in _load tarinfo = self.next() File "/usr/lib/python2.7/tarfile.py", line 2315, in next self.fileobj.seek(self.offset) File "/usr/lib/python2.7/gzip.py", line 429, in seek self.read(1024) File "/usr/lib/python2.7/gzip.py", line 256, in read self._read(readsize) File "/usr/lib/python2.7/gzip.py", line 320, in _read self._read_eof() File "/usr/lib/python2.7/gzip.py", line 342, in _read_eof hex(self.crc))) IOError: CRC check failed 0xe5384b87 != 0xdfe91e1L
只是对Aya的回答进行了小幅改进,使事情变得更加惯用(尽管我正在删除一些错误检查以使机制更明显):
BLOCK_SIZE = 1024 with tarfile.open("zero.tar.gz") as tardude: for member in tardude.getmembers(): with tardude.extractfile(member.name) as target: for chunk in iter(lambda: target.read(BLOCK_SIZE), b''): pass
这实际上只是删除了while 1:(有时被认为是轻微的代码异味)和if not data:检查。另请注意,使用with限制将其限制为Python 2.7+
while 1:
if not data:
with