【问题标题】:tar.extractall() does not recognize unexpected EOFtar.extractall() 无法识别意外的 EOF
【发布时间】:2023-10-11 21:33:01
【问题描述】:

Python tarfile 库未检测到损坏的 tar。

user@host$ wc -c good.tar
143360 good.tar

user@host$ head -c 130000 good.tar > cut.tar

user@host$ tar -tf cut.tar 
...
tar: Unexpected EOF in archive
tar: Error is not recoverable: exiting now

非常好,命令行工具识别出意外的 EOF。

user@host$ python
Python 2.7.6 (default, Mar 22 2014, 22:59:56) 
>>> import tarfile
>>> tar=tarfile.open('cut.tar')
>>> tar.extractall()

不好。 Python 库对文件进行解码,但不会引发异常。

如何使用 Python 库检测意外的 EOF?我想避免使用subprocess 模块。

参数errorlevel 没有帮助。我尝试了 errorlevel=1 和 errorlevel=2。

【问题讨论】:

  • 不错的收获!您应该考虑打开错误报告并提交您的解决方案
  • @knitti 我打开了一个错误报告:bugs.python.org/issue24259
  • 遗憾的是,我无法为现有的奖励添加一些赏金......
  • 您使用的是哪种焦油?我的没有引发错误。
  • 我使用 tar (GNU tar) 1.27.1。 python.org 上的错误报告(见上文)有一个损坏的 tar_which_is_cut.tar 用于测试。

标签: python tar eof


【解决方案1】:

我写了一个解决方法。它适用于我的 tar 文件。我猜它不支持所有可以存储在 tar 文件中的对象类型。

# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, unicode_literals, print_function
import os
import tarfile

class TarfileWhichRaisesOnEOF(tarfile.TarFile):
    def extractall(self, path=".", members=None):
        super(TarfileWhichRaisesOnEOF, self).extractall(path, members)
        if members is None:
            members = self

        for tarinfo in members:
            if not tarinfo.isfile():
                continue
            file=os.path.join(path, tarinfo.name)
            size_real=os.path.getsize(file)
            if size_real!=tarinfo.size:
                raise tarfile.ExtractError('Extracting %s: Size does not match. According to tarinfo %s and on disk %s' % (
                    tarinfo, tarinfo.size, size_real))

【讨论】:

    【解决方案2】:

    这已在 Python 3 中得到修复——无论errorlevel 设置如何,都会引发OSError

    【讨论】:

    • 对不起,在我的情况下设置错误级别不起作用。这意味着 Python3 的更改在这里无济于事。
    • @guettli:你试过 3.4 吗?请在bugs.python.org/issue24259 中添加备注。
    • 我尝试使用 Python 3.4.0 提取所有()上传的 tar_which_is_cut.tar。它引发了一个 OSError - 很好。只有 2.7 受到影响?