Как загрузить и извлечь файл tar с помощью Python

Извиняюсь за очень простой вопрос, но здесь я совсем запутался. Я не могу понять, как загрузить и извлечь tar-файл .xz с помощью Python. См. приведенный ниже пример кода, где я пробую несколько подходов как для загрузки, так и для извлечения из двух разных tar (просто чтобы убедиться, что я не тестирую действительно искаженный tar) — все они терпят неудачу:

Информация о системе: Mac OS 10.15.7, Python 3.9.9

Код:

#!/usr/bin/env python3

import requests
import tarfile
import subprocess

from functools import partial
from shutil import copyfileobj

example_url_1 = 'https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2022-04-07/2022-04-04-raspios-bullseye-armhf-lite.img.xz'
example_url_2 = 'https://cdimage.ubuntu.com/releases/22.04/release/ubuntu-22.04-preinstalled-server-arm64+raspi.img.xz'

def _try_extracting(filename: str):
    try:
        with tarfile.open(filename, mode='r:xz') as tf:
            tf.extractall(filename[:-3])
        print(f'Extracting {filename} succeeded')
    except Exception as e:
        print(f'Extracting {filename} failed: ', e)
        print('Falling back to extracting via command-line `tar` tool')
        p = subprocess.run(['tar', 'xf', filename], capture_output=True)
        print(p.stdout)
        print(p.stderr)
        print()
        # https://askubuntu.com/a/843803
        print('Also attempting use of command-line `ar` tool')
        p = subprocess.run(['ar', '-x', filename], capture_output=True)
        print(p.stdout)
        print(p.stderr)
        print()
        print('=========')

def _download_and_extract_in_various_ways(url, prefix):
    print('=========================================\n=========================================')
    print(f'Operating on {url}')
    print('Downloading xz via copyfileobj from requests')
    copyfileobj_download_request = requests.get(url, stream=True)
    content_length = int(copyfileobj_download_request.headers.get('content-length'))
    # https://stackoverflow.com/a/63831344/1040915
    copyfileobj_download_request.raw.read = partial(copyfileobj_download_request.raw.read, decode_content=True)
    # Here I would insert `tqdm.wrapattr(copyfileobj_download_request.raw, "read", total=content_length) as tq:`
    with open(prefix + '_tar_downloaded_with_copyfileobj.xz', 'wb') as f:
        copyfileobj(copyfileobj_download_request.raw, f) # This would be `copyfileobj(tq, f)` if fully wrapped
    _try_extracting(prefix + '_tar_downloaded_with_copyfileobj.xz')

    print('Downloading xz via bare request')
    standard_download_request = requests.get(url)
    with open(prefix + '_tar_downloaded_with_requests.xz', 'wb') as f:
        f.write(standard_download_request.content)
    _try_extracting(prefix + '_tar_downloaded_with_requests.xz')

    subprocess.run(['wget', '-O', prefix + '_tar_downloaded_with_wget.xz', url], capture_output=True)
    _try_extracting(prefix + '_tar_downloaded_with_wget.xz')

    subprocess.run(['curl', '-o', prefix + '_tar_downloaded_with_curl.xz', url], capture_output=True)
    _try_extracting(prefix + '_tar_downloaded_with_curl.xz')

def main():
    _download_and_extract_in_various_ways(example_url_1, 'raspbian')
    _download_and_extract_in_various_ways(example_url_2, 'ubuntu')


if __name__ == '__main__':
    main()

Выход:

=========================================
=========================================
Operating on https://downloads.raspberrypi.org/raspios_lite_armhf/images/raspios_lite_armhf-2022-04-07/2022-04-04-raspios-bullseye-armhf-lite.img.xz
Downloading xz via copyfileobj from requests
Extracting raspbian_tar_downloaded_with_copyfileobj.xz failed:  bad checksum
Falling back to extracting via command-line `tar` tool
b''
b'tar: Error opening archive: Unrecognized archive format\n'

Also attempting use of command-line `ar` tool
b''
b'ar: raspbian_tar_downloaded_with_copyfileobj.xz: Inappropriate file type or format\n'

=========
Downloading xz via bare request
Extracting raspbian_tar_downloaded_with_requests.xz failed:  bad checksum
Falling back to extracting via command-line `tar` tool
b''
b'tar: Error opening archive: Unrecognized archive format\n'

Also attempting use of command-line `ar` tool
b''
b'ar: raspbian_tar_downloaded_with_requests.xz: Inappropriate file type or format\n'

=========
Extracting raspbian_tar_downloaded_with_wget.xz failed:  bad checksum
Falling back to extracting via command-line `tar` tool
b''
b'tar: Error opening archive: Unrecognized archive format\n'

Also attempting use of command-line `ar` tool
b''
b'ar: raspbian_tar_downloaded_with_wget.xz: Inappropriate file type or format\n'

=========
Extracting raspbian_tar_downloaded_with_curl.xz failed:  bad checksum
Falling back to extracting via command-line `tar` tool
b''
b'tar: Error opening archive: Unrecognized archive format\n'

Also attempting use of command-line `ar` tool
b''
b'ar: raspbian_tar_downloaded_with_curl.xz: Inappropriate file type or format\n'

=========
=========================================
=========================================
Operating on https://cdimage.ubuntu.com/releases/22.04/release/ubuntu-22.04-preinstalled-server-arm64+raspi.img.xz
Downloading xz via copyfileobj from requests
Extracting ubuntu_tar_downloaded_with_copyfileobj.xz failed:  bad checksum
Falling back to extracting via command-line `tar` tool
b''
b'tar: Error opening archive: Unrecognized archive format\n'

Also attempting use of command-line `ar` tool
b''
b'ar: ubuntu_tar_downloaded_with_copyfileobj.xz: Inappropriate file type or format\n'

=========
Downloading xz via bare request
Extracting ubuntu_tar_downloaded_with_requests.xz failed:  bad checksum
Falling back to extracting via command-line `tar` tool
b''
b'tar: Error opening archive: Unrecognized archive format\n'

Also attempting use of command-line `ar` tool
b''
b'ar: ubuntu_tar_downloaded_with_requests.xz: Inappropriate file type or format\n'

=========
Extracting ubuntu_tar_downloaded_with_wget.xz failed:  bad checksum
Falling back to extracting via command-line `tar` tool
b''
b'tar: Error opening archive: Unrecognized archive format\n'

Also attempting use of command-line `ar` tool
b''
b'ar: ubuntu_tar_downloaded_with_wget.xz: Inappropriate file type or format\n'

=========
Extracting ubuntu_tar_downloaded_with_curl.xz failed:  bad checksum
Falling back to extracting via command-line `tar` tool
b''
b'tar: Error opening archive: Unrecognized archive format\n'

Also attempting use of command-line `ar` tool
b''
b'ar: ubuntu_tar_downloaded_with_curl.xz: Inappropriate file type or format\n'

=========

Если я загружаю эти файлы, напрямую посещая эти URL-адреса в своем браузере, полученный загруженный файл Все еще не может быть извлечен с помощью tar xf <file>.

Интересно, что все 8 файлов, загруженных с помощью скрипта ([copyfileobj,requests,wget,curl] X [raspbian,ubuntu]), можно извлечь без ошибок, «открыв» их в Mac OS Finder.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
39
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это файлы .xz и файлы нет tar.xz. Так что модуль Tarfile работать не будет. Вместо этого используйте Изма:

import lzma
with lzma.open(filename) as fin:
    file_content = fin.read()
fout = open(filename[:-3], 'wb')
fout.write(file_content)
fout.close()

@blankettripod, я думаю, что полученные файлы - это файлы IMG, эквивалент файлов ISO для Mac.

bfris 11.05.2022 21:49

@blankettripod весь смысл ответа в том, что файлы .xz представляют собой сжатый tar-архив нет, но просто «обычные» сжатые файлы, т.е. они не имеют ничего общего с tar-архивом, поэтому tarfiles не может их обработать.

BlackBeans 11.05.2022 21:54

D'oh, ну теперь я чувствую себя глупо! Благодарю вас!

scubbo 12.05.2022 05:05

Другие вопросы по теме