Подтвердить что ты не робот

Python распаковывает поток байтов?

Вот ситуация:

  • Я получаю gzipped xml документы от Amazon S3

    import boto
    from boto.s3.connection import S3Connection
    from boto.s3.key import Key
    conn = S3Connection('access Id', 'secret access key')
    b = conn.get_bucket('mydev.myorg')
    k = Key(b)
    k.key('documents/document.xml.gz')
    
  • Я читаю их в файле как

    import gzip
    f = open('/tmp/p', 'w')
    k.get_file(f)
    f.close()
    r = gzip.open('/tmp/p', 'rb')
    file_content = r.read()
    r.close()
    

Вопрос

Как я могу разархивировать потоки напрямую и прочитать содержимое?

Я не хочу создавать временные файлы, они не выглядят хорошо.

4b9b3361

Ответ 1

Да, вы можете использовать zlib module для распаковки байтовых потоков:

import zlib

def stream_gzip_decompress(stream):
    dec = zlib.decompressobj(32 + zlib.MAX_WBITS)  # offset 32 to skip the header
    for chunk in stream:
        rv = dec.decompress(chunk)
        if rv:
            yield rv

Смещение 32 сигналов к заголовку zlib, который ожидается в заголовке gzip, но пропущен.

Объект ключа S3 является итератором, поэтому вы можете:

for data in stream_gzip_decompress(k):
    # do something with the decompressed data

Ответ 2

Мне нужно было сделать то же самое, и вот как я это сделал:

import gzip
f = StringIO.StringIO()
k.get_file(f)
f.seek(0) #This is crucial
gzf = gzip.GzipFile(fileobj=f)
file_content = gzf.read()

Ответ 3

Вы можете попробовать PIPE и прочитать содержимое без скачивания файла

    import subprocess
    c = subprocess.Popen(['-c','zcat -c <gzip file name>'], shell=True, stdout=subprocess.PIPE,         stderr=subprocess.PIPE)
    for row in c.stdout:
      print row

Кроме того, "/dev/fd/" + str (c.stdout.fileno()) предоставит вам имя файла FIFO (Именованный канал), который может быть передан другой программе.

Ответ 4

Для Python3x и boto3 -

Итак, я использовал BytesIO для чтения сжатого файла в буферный объект, затем я использовал zip файл, чтобы открыть распакованный поток как несжатые данные, и я смог получить нулевое значение строки за строкой.

import io
import zipfile
import boto3
import sys

s3 = boto3.resource('s3', 'us-east-1')


def stream_zip_file():
    count = 0
    obj = s3.Object(
        bucket_name='MonkeyBusiness',
        key='/Daily/Business/Banana/{current-date}/banana.zip'
    )
    buffer = io.BytesIO(obj.get()["Body"].read())
    print (buffer)
    z = zipfile.ZipFile(buffer)
    foo2 = z.open(z.infolist()[0])
    print(sys.getsizeof(foo2))
    line_counter = 0
    for _ in foo2:
        line_counter += 1
    print (line_counter)
    z.close()


if __name__ == '__main__':
    stream_zip_file()