36

状況は次のとおりです。

  • Amazon S3 から gzip された xml ドキュメントを取得します

      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()
    

質問

ストリームを直接 unzip してコンテンツを読むにはどうすればよいですか?

一時ファイルを作成したくありません。見栄えがよくありません。

4

4 に答える 4

39

はい、zlibモジュールを使用してバイト ストリームを解凍できます。

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
于 2012-09-24T20:00:08.017 に答える
10

私は同じことをしなければなりませんでした、そしてこれは私がそれをした方法です:

import gzip
f = StringIO.StringIO()
k.get_file(f)
f.seek(0) #This is crucial
gzf = gzip.GzipFile(fileobj=f)
file_content = gzf.read()
于 2012-10-18T14:41:14.833 に答える
6

Python3x および boto3 の場合

そこで、BytesIO を使用して圧縮ファイルをバッファ オブジェクトに読み込み、次に zipfile を使用して圧縮解除されたストリームを非圧縮データとして開き、データを 1 行ずつ取得することができました。

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()
于 2017-09-26T21:04:30.363 に答える
0

ファイルをダウンロードせずに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 ファイル名 (名前付きパイプ) を提供します。

于 2012-09-24T21:01:34.877 に答える