tar.extractall() не распознает неожиданный EOF

Библиотека 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 декодирует файл, но не вызывает никаких исключений.

Как обнаружить неожиданный EOF с помощью библиотеки Python? Я хочу избежать модуля subprocess.

Параметр errorlevel не помогает. Я пробовал уровень ошибок = 1 и уровень ошибок = 2.


person guettli    schedule 18.05.2015    source источник
comment
Хорошо поймал! вам следует подумать об открытии отчета об ошибке и представить свое решение   -  person knitti    schedule 21.05.2015
comment
@knitti Я открыл отчет об ошибке: bugs.python.org/issue24259   -  person guettli    schedule 21.05.2015
comment
К сожалению, я не могу добавить награду к существующей...   -  person knitti    schedule 21.05.2015
comment
Какой тар вы используете? Моя не выдавала ошибку.   -  person Ethan Furman    schedule 28.05.2015
comment
Я использую tar (GNU tar) 1.27.1. В отчете об ошибке на python.org (см. выше) есть неработающий файл tar_what_is_cut.tar для тестирования.   -  person guettli    schedule 28.05.2015


Ответы (2)


Я написал работу вокруг. Он работает с моими файлами 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))
person guettli    schedule 18.05.2015

Это было исправлено в Python 3 — OSError поднимается независимо от настройки errorlevel.

person Ethan Furman    schedule 28.05.2015
comment
Извините, в моем случае установка уровня ошибки не работает. Это означает, что изменения Python3 здесь не помогут. - person guettli; 29.05.2015
comment
@guettli: ты пробовал с 3.4? Пожалуйста, добавьте примечание к bugs.python.org/issue24259, говоря об этом. - person Ethan Furman; 30.05.2015
comment
Я попытался извлечь все () загруженный файл tar_what_is_cut.tar с помощью Python 3.4.0. Выдает OSError - хорошо. Только 2.7 пострадали? - person guettli; 30.05.2015