Skip to main content
 首页 » 编程设计

python之处理从损坏的 GZ (TAR) 中提取单个文件

2025年05月04日11TianFang

这是我在 Stack Overflow 上的第一篇文章,我有一个关于使用 GZ 压缩从 TAR 文件中提取单个文件的问题。我不是最擅长 Python 的,所以我可能做错了,任何帮助将不胜感激。


场景:

损坏的*.tar.gz 文件进来,GZ 中的第一个文件包含获取系统SN 的重要信息。这可用于识别机器,以便我们可以向其管理员发出文件已损坏的通知。

问题:

使用常规的 UNIX tar 二进制文件,我能够从存档中提取 README 文件,即使存档不完整并且在完全提取时会返回错误。但是,在 Python 中,我无法只提取一个文件,即使我只指定单个文件,它也总是返回异常。

当前的解决方法:

我正在使用“os.popen”来使用 UNIX tar 二进制文件,以便仅获取 README 文件。

所需的解决方案:

使用 Python tarfile 包仅提取单个文件。

示例错误:

UNIX(工作):

[root@athena tmp]# tar -xvzf bundle.tar.gz README 
README 
 
gzip: stdin: unexpected end of file 
tar: Unexpected EOF in archive 
tar: Error is not recoverable: exiting now 
[root@athena tmp]#  
[root@athena tmp]# ls 
bundle.tar.gz  README 

python :

>>> import tarfile 
>>> tar = tarfile.open("bundle.tar.gz") 
>>> data = tar.extractfile("README").read() 
Traceback (most recent call last): 
  File "<stdin>", line 1, in ? 
  File "/usr/lib64/python2.4/tarfile.py", line 1364, in extractfile 
    tarinfo = self.getmember(member) 
  File "/usr/lib64/python2.4/tarfile.py", line 1048, in getmember 
    tarinfo = self._getmember(name) 
  File "/usr/lib64/python2.4/tarfile.py", line 1762, in _getmember 
    members = self.getmembers() 
  File "/usr/lib64/python2.4/tarfile.py", line 1059, in getmembers 
    self._load()        # all members, we first have to 
  File "/usr/lib64/python2.4/tarfile.py", line 1778, in _load 
    tarinfo = self.next() 
  File "/usr/lib64/python2.4/tarfile.py", line 1588, in next 
    self.fileobj.seek(self.offset) 
  File "/usr/lib64/python2.4/gzip.py", line 377, in seek 
    self.read(1024) 
  File "/usr/lib64/python2.4/gzip.py", line 225, in read 
    self._read(readsize) 
  File "/usr/lib64/python2.4/gzip.py", line 273, in _read 
    self._read_eof() 
  File "/usr/lib64/python2.4/gzip.py", line 309, in _read_eof 
    raise IOError, "CRC check failed" 
IOError: CRC check failed 
>>> print data 
Traceback (most recent call last): 
  File "<stdin>", line 1, in ? 
NameError: name 'data' is not defined 

Python(处理异常):

>>> tar = tarfile.open("bundle.tar.gz") 
>>> try: 
...     data = tar.extractfile("README").read() 
... except: 
...     pass 
...  
>>> print(data) 
Traceback (most recent call last): 
  File "<stdin>", line 1, in ? 
NameError: name 'data' is not defined 

请您参考如下方法:

使用手动 Unix 方法,看起来 gzip 将文件解压缩到它中断的位置。

Python gzip(或 tar)模块一旦发现由于 CRC 检查失败导致存档损坏,就会立即退出。

只是一个想法,但您可以使用 gzip 预处理损坏的存档并重新压缩它们以更正 CRC。

gunzip < damaged.tar.gz | gzip > corrected.tar.gz 

这将为您提供一个 corrected.tar.gz,它现在将包含所有数据,直到存档被破坏的那一点。您现在应该能够使用 python tar/gzip 库而不会出现 CRC 异常。

请记住,此命令将对存档进行解压缩和 gzip 压缩,这会消耗存储 IO 和 CPU 时间,您不应该对所有存档都这样做。

为了提高效率,您应该只在收到 IOError: CRC check failed 异常时运行它。