Как распаковать файлы lzma2 (.xz) и zstd (.zst) в папку с помощью Python 3?

Я давно работаю с .bz2 файлы. Распаковать / распаковать .bz2 файлы в определенную папку, я использовал следующую функцию:

destination_folder = 'unpacked/'
def decompress_bz2_to_folder(input_file):
    unpackedfile = bz2.BZ2File(input_file)
    data = unpackedfile.read()
    open(destination_folder, 'wb').write(data)

Недавно я получил список файлов с .xz (не .tar.xz) а также .zst расширения. Мои плохие исследовательские навыки говорили мне, что первый lzma2 сжатие и последнее Zstandard,

Однако я не смог найти простой способ распаковать содержимое этих архивов в папку (как я это делал с .bz2 файлы).

Как я могу:

  1. Распакуйте содержимое .xz (lzma2) файл в папку с помощью Python 3?
  2. Распакуйте содержимое .zst (Zstandard) файл в папку с помощью Python 3?

Важное примечание: я распаковываю очень большие файлы, поэтому было бы неплохо, если бы решение учитывало возможные ошибки памяти.

1 ответ

Решение

Данные LZMA могут быть распакованы с использованием lzma модуль, просто откройте файл с этим модулем, затем используйте shutil.copyfileobj() для эффективного копирования распакованных данных в выходной файл без проблем с памятью:

import lzma
import pathlib
import shutil

def decompress_lzma_to_folder(input_file):
    input_file = pathlib.Path(input_file)
    with lzma.open(input_file) as compressed:
        output_path = pathlib.Path(destination_dir) / input_file.stem
        with open(output_path, 'wb') as destination:
            shutil.copyfileobj(compressed, destination)

Стандартная библиотека Python пока не поддерживает сжатие Zstandard, вы можете использовать либо zstandard (от IndyGreg из Mozilla и проекта Mercurial) или zstd; последнее, возможно, слишком базовое для ваших нужд, в то время как zstandard предлагает потоковый API, специально предназначенный для чтения файлов.

Я использую zstandard библиотека здесь, чтобы извлечь выгоду из API копирования, который она реализует, который позволяет распаковывать и копировать одновременно, как shutil.copyfileobj() работает:

import zstandard
import pathlib
import shutil

def decompress_zstandard_to_folder(input_file):
    input_file = pathlib.Path(input_file)
    with open(input_file, 'rb') as compressed:
        decomp = zstandard.ZstdDecompressor()
        output_path = pathlib.Path(destination_dir) / input_file.stem
        with open(output_path, 'wb') as destination:
            decomp.copy_stream(compressed, destination)
Другие вопросы по тегам