Как я могу прочитать из поврежденного файла tar.bz2 в Python?
У меня есть программа, которая сохраняет свой вывод в файл tar.bz2, как он работает. У меня есть скрипт Python, который обрабатывает эти данные.
Я хотел бы иметь возможность работать с выводом, если первая программа будет прервана, или просто запустить скрипт Python для него, пока процесс продолжается.
Конечно, последний блок bzip2 еще не закончен, поэтому его невозможно прочитать - он фактически поврежден, хотя на самом деле он просто обрезан. GNU tar на самом деле с радостью извлечет все, что может, из файла до этого момента - как и будет bzcat
, в этом отношении. А также bzip2recover
может создавать восстановленные блоки, хотя это действительно менее полезно в этом случае, чем bzcat
,
Но я пытаюсь использовать стандартный модуль tarfile для Python. Это не с
File "/usr/lib64/python2.7/tarfile.py", line 2110, in extractfile
tarinfo = self.getmember(member)
File "/usr/lib64/python2.7/tarfile.py", line 1792, in getmember
tarinfo = self._getmember(name)
File "/usr/lib64/python2.7/tarfile.py", line 2361, in _getmember
members = self.getmembers()
File "/usr/lib64/python2.7/tarfile.py", line 1803, in getmembers
self._load() # all members, we first have to
File "/usr/lib64/python2.7/tarfile.py", line 2384, in _load
tarinfo = self.next()
File "/usr/lib64/python2.7/tarfile.py", line 2319, in next
self.fileobj.seek(self.offset)
EOFError: compressed file ended before the logical end-of-stream was detected
когда я пытаюсь использовать TarFile.extractfile
на файл, который я знаю, в начале. (tar -xf tarfile.tar.bz2 filename
будет извлекать это просто отлично.)
Есть ли что-нибудь умное, что я могу сделать, чтобы игнорировать неверный конец файла и работать с тем, что у меня есть?
Набор данных может быть довольно большим и очень-очень сжимаемым, поэтому держать его без сжатия нежелательно.
(Я нашел существующий вопрос архива Untar в Python с ошибками, но в этом случае пользователь пытается os.system
файл tar.)
1 ответ
Кажется, есть 2 возможности. Во-первых, и, скорее всего:
Если ignore_zeros имеет значение False, обрабатывать пустой блок как конец архива. Если это Истина, пропустите пустые (и недействительные) блоки и попытайтесь получить как можно больше членов. Это полезно только для чтения сцепленных или поврежденных архивов.
Во-вторых:
Для специальных целей существует второй формат режима: 'filemode|[сжатие]'. tarfile.open() вернет объект TarFile, который обрабатывает его данные в виде потока блоков. Случайный поиск по файлу не производится. Если задано, fileobj может быть любым объектом, который имеет метод read() или write() (в зависимости от режима). bufsize определяет размер блока и по умолчанию составляет 20 * 512 байт. Используйте этот вариант в сочетании, например, с sys.stdin, объектом файла сокета или ленточным устройством. Тем не менее, такой объект TarFile ограничен тем, что он не позволяет получить случайный доступ
Похоже, что доступ к файлу в виде потока может быть полезен, когда файл не завершен.