web-dev-qa-db-ja.com

PythonでAWS S3からgzipファイルの内容を読み取る

AWSで実行しているHadoopプロセスからいくつかのログを読み取ろうとしています。ログはS3フォルダーに保存され、次のパスがあります。

bucketname = name key = y/z/stderr.gzこ​​こで、YはクラスターID、zはフォルダー名です。これらは両方とも、AWSのフォルダー(オブジェクト)として機能します。したがって、フルパスはx/y/z/stderr.gzのようになります。

次に、この.gzファイルを解凍し、ファイルの内容を読み取ります。 python変数でコンテンツを保存したいシステムにこのファイルをダウンロードしたくない。

これは私が今まで試したものです。

bucket_name = "name"
key = "y/z/stderr.gz"
obj = s3.Object(bucket_name,key)
n = obj.get()['Body'].read()

これは私に読めないフォーマットを与えています。私も試しました

n = obj.get()['Body'].read().decode('utf-8')

エラーが発生しますtf8 'コーデックは位置1のバイト0x8bをデコードできません:無効な開始バイト

私も試しました

gzip = StringIO(obj)
gzipfile = gzip.GzipFile(fileobj=gzip)
content = gzipfile.read()

これはエラーを返しますIOError:gzipされていないファイル

この.gzファイルのデコード方法がわかりません。

編集-ソリューションを見つけました。 nを渡してBytesIOを使用する必要がありました

gzip = BytesIO(n)
18
Kshitij Marwah

@Amit、私はファイルのデコードをテストするために同じことをしようとしていました、そしてあなたのコードにいくつかの修正を加えて実行させました。その名前が使用されているため、関数defと戻り値を削除し、gzip変数の名前を変更する必要がありました。

import json
import boto3
from io import BytesIO
import gzip

try:
     s3 = boto3.resource('s3')
     key='YOUR_FILE_NAME.gz'
     obj = s3.Object('YOUR_BUCKET_NAME',key)
     n = obj.get()['Body'].read()
     gzipfile = BytesIO(n)
     gzipfile = gzip.GzipFile(fileobj=gzipfile)
     content = gzipfile.read()
     print(content)
except Exception as e:
    print(e)
    raise e
7
Levi

AWS S3SELECT Object Contentを使用してgzipコンテンツを読み取ることができます

S3 Selectは、オブジェクトから必要なデータのみを引き出すように設計されたAmazon S3機能です。これにより、S3のデータにアクセスする必要があるアプリケーションのパフォーマンスを劇的に改善し、コストを削減できます。

Amazon S3 Selectは、Apache Parquet形式で保存されたオブジェクト、JSON配列、およびCSVおよびJSONオブジェクトのBZIP2圧縮で動作します。

参照: https://docs.aws.Amazon.com/AmazonS3/latest/dev/selecting-content-from-objects.html

from io import StringIO
import boto3
import pandas as pd

bucket = 'my-bucket'
prefix = 'my-prefix'

client = boto3.client('s3')

for object in client.list_objects_v2(Bucket=bucket, Prefix=prefix)['Contents']:
    if object['Size'] <= 0:
        continue

    print(object['Key'])
    r = client.select_object_content(
            Bucket=bucket,
            Key=object['Key'],
            ExpressionType='SQL',
            Expression="select * from s3object",
            InputSerialization = {'CompressionType': 'GZIP', 'JSON': {'Type': 'DOCUMENT'}},
            OutputSerialization = {'CSV': {'QuoteFields': 'ASNEEDED', 'RecordDelimiter': '\n', 'FieldDelimiter': ',', 'QuoteCharacter': '"', 'QuoteEscapeCharacter': '"'}},
        )

    for event in r['Payload']:
        if 'Records' in event:
            records = event['Records']['Payload'].decode('utf-8')
            payloads = (''.join(r for r in records))
            try:
                select_df = pd.read_csv(StringIO(payloads), error_bad_lines=False)
                for row in select_df.iterrows():
                    print(row)
            except Exception as e:
                print(e)
3
rahulb

Pythonでaws s3からBz2拡張ファイルを読み取る

import json
import boto3
from io import BytesIO
import bz2
try:
    s3 = boto3.resource('s3')
    key='key_name.bz2'
    obj = s3.Object('bucket_name',key)
    nn = obj.get()['Body'].read()
    gzipfile = BytesIO(nn)
    content = bz2.decompress(gzipfile.read())
    content = content.split('\n')
    print len(content)

except Exception as e:
    print(e)
1
amardip kumar

現在、ファイルは次のように読み取ることができます

role = 'role name'
bucket = 'bucket name'
data_key = 'data key'
data_location = 's3://{}/{}'.format(bucket, data_key)
data = pd.read_csv(data_location,compression='gzip', header=0, sep=',', quotechar='"')
0

変数で行うのと同じように、ioモジュールのByte IO操作を使用すると、データをメモリ内のバッファーにバイトとして保持できます。

これを実証するサンプルプログラムを次に示します。

_mport io

stream_str = io.BytesIO(b"JournalDev Python: \x00\x01")
print(stream_str.getvalue())
_

getvalue()関数は、バッファから値を文字列として受け取ります。

したがって、@Jean-FrançoisFabreの答えは正しいので、

_gzip = BytesIO(n)
_

詳細については、次のドキュメントを参照してください。

https://docs.python.org/3/library/io.html

0
Reza Mousavi