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()
Вопрос
Как я могу разархивировать потоки напрямую и прочитать содержимое?
Я не хочу создавать временные файлы, они не выглядят хорошо.
Ответы
Ответ 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()