从Python中的AWS S3读取gzip文件的内容

时间:2016-12-15 09:46:26

标签: python amazon-web-services amazon-s3 boto3

我正在尝试从我在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')

给出错误 utf8'编解码器无法解码位置1中的字节0x8b:无效的起始字节。

我也试过

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

这会返回错误 IOError:不是gzip压缩文件

不确定如何解码此.gz文件。

编辑 - 找到解决方案。需要传递n并使用BytesIO

gzip = BytesIO(n)

6 个答案:

答案 0 :(得分:13)

这很旧,但是您不再需要其中间的BytesIO对象(至少在我的boto3==1.9.223python3.7上)

import boto3
import gzip

s3 = boto3.resource("s3")
obj = s3.Object("YOUR_BUCKET_NAME", "path/to/your_key.gz")
with gzip.GzipFile(fileobj=obj.get()["Body"]) as gzipfile:
    content = gzipfile.read()
print(content)

答案 1 :(得分:2)

@Amit,我正在尝试做同样的事情来测试解码文件,并让您的代码经过一些修改即可运行。我只需要删除函数def,返回值并重命名gzip变量,因为该名称正在使用中。

O(1)

答案 2 :(得分:2)

您可以使用AWS S3 SELECT对象内容来读取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 :(得分:1)

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

答案 4 :(得分:0)

就像我们对变量所做的那样,当我们使用io模块的字节IO操作时,数据可以作为字节保存在内存缓冲区中。

这是一个示例程序来证明这一点:

getvalue()

gzip = BytesIO(n) 函数将缓冲区中的值作为字符串。

因此,@Jean-FrançoisFabre答案是正确的,您应该使用

var requiredDiv = $("<span class='markrequired'>*</span>");

有关更多信息,请阅读以下文档:

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

答案 5 :(得分:0)

当前文件可以读取为

import pandas as pd
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='"')