Как распаковать.tar.bz2 в памяти с питоном

Как распаковать файл *.bz2 в память с помощью python? Файл bz2 происходит из файла csv.

Я использую код ниже, чтобы распаковать его в памяти, он работает, но он приносит некоторые грязные данные, такие как имя файла csv и имя автора, есть ли другой лучший способ справиться с этим?

#!/usr/bin/python
# -*- coding: utf-8 -*-
import StringIO
import bz2


with open("/app/tmp/res_test.tar.bz2", "rb") as f:
    content = f.read()

    compressedFile = StringIO.StringIO(content)
    decompressedFile = bz2.decompress(compressedFile.buf)
    compressedFile.seek(0)

    with open("/app/tmp/decompress_test", 'w') as outfile:
        outfile.write(decompressedFile)

Я нашел этот вопрос, это в gzip, однако мои данные в формате bz2, я пытаюсь сделать, как указано в нем, но кажется, что bz2 не может обработать это таким образом.

Редактировать:

Независимо от ответа @metatoaster или приведенного выше кода, оба они внесут более грязные данные в окончательный распакованный файл. Например: мои исходные данные прикреплены ниже и в формате csv с именем res_test.csv:

Затем я перехожу в каталог, в котором находится файл, и сжимаю его tar -cjf res_test.tar.bz2 res_test.csv и получить сжатый файл res_test.tar.bz2, этот файл может имитировать данные bz2, которые я получу из Интернета, и я хочу распаковать их в памяти без предварительного кэширования на диск, но я получаю данные ниже и содержит слишком много грязные данные:

Данные все еще там, но погружены в шум, возможно ли распаковывать их в чистые данные, точно так же, как исходные данные, вместо распаковки и извлекать реальные данные из слишком большого количества шума?

1 ответ

Решение

Для общей декомпрессии bz2, BZ2File класс может быть использован.

from bz2 import BZ2File
with BZ2File("/app/tmp/res_test.tar.bz2") as f:
    content = f.read()

content должен содержать распакованное содержимое файла.

Однако, учитывая, что это tar файл (архивный файл, который обычно извлекается на диск как каталог файлов), tarfile модуль может быть использован вместо него, и он имеет расширенные флаги режима для обработки bz2. Предполагая, что целевой файл содержит res_test.csv можно использовать следующее

tf = tarfile.open('/app/tmp/res_test.tar.bz2', 'r:bz2')
csvfile = tf.extractfile('res_test.csv').read()

r:bz2 flag открывает архив tar таким образом, что позволяет искать в обратном направлении, что важно в качестве альтернативного метода r|bz2 делает нецелесообразным вызывать извлечение файлов из членов, которые он возвращает extractfile, Вторая строка просто вызывает extractfile вернуть содержимое 'res_test.csv' из архива в виде строки.

Прозрачный открытый режим ('r:*'), как правило, рекомендуется, однако, если входной tar-файл сжат с использованием gzip, сбоев не возникнет.

Естественно, что tarfile модуль имеет более низкий уровень open метод, который может использоваться на объектах произвольного потока. Если файл уже был открыт с помощью BZ2File уже это тоже можно использовать

with BZ2File("/app/tmp/res_test.tar.bz2") as f:
    tf = tarfile.open(fileobj=f, mode='r:')
    csvfile = tf.extractfile('res_test.csv').read()
Другие вопросы по тегам