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

用Python从AWS S3读取gzip文件的内容,python,amazon-web-services,amazon-s3,boto3,Python,Amazon Web Services,Amazon S3,Boto3,我试图从我在AWS中运行的Hadoop进程中读取一些日志。日志存储在S3文件夹中,并具有以下路径 bucketname=名称 key=y/z/stderr.gz 这里Y是集群id,z是文件夹名称。这两者在AWS中都充当文件夹(对象)。因此,完整路径类似于x/y/z/stderr.gz 现在我想解压这个.gz文件并读取文件的内容。我不想将此文件下载到我的系统,我想将内容保存在python变量中 这就是我到现在为止一直在尝试的 bucket_name = "name" key = "y/z/stde

我试图从我在AWS中运行的Hadoop进程中读取一些日志。日志存储在S3文件夹中,并具有以下路径

bucketname=名称 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()
这将返回一个错误:不是gzip文件

不知道如何解码这个.gz文件

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

gzip = BytesIO(n)

就像我们处理变量一样,当我们使用io模块的字节io操作时,数据可以作为字节保存在内存缓冲区中

下面是一个示例程序来演示这一点:

mport io

stream_str = io.BytesIO(b"JournalDev Python: \x00\x01")
print(stream_str.getvalue())
getvalue()
函数将缓冲区中的值作为字符串

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

gzip = BytesIO(n)
有关更多信息,请阅读以下文档:


@Amit,我正试图做同样的事情来测试解码一个文件,并通过一些修改让您的代码运行。我只需要删除函数def和return,并重命名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

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

您可以使用AWS S3选择对象内容来读取gzip内容

S3 Select是Amazon S3的一项功能,旨在仅从对象中提取所需的数据,这可以显著提高性能并降低需要在S3中访问数据的应用程序的成本

amazons3select处理以apacheparquet格式存储的对象、JSON数组以及用于CSV和JSON对象的BZIP2压缩

参考:

从io导入StringIO
进口boto3
作为pd进口熊猫
bucket='我的bucket'
前缀='我的前缀'
client=boto3.client('s3')
用于客户端中的对象。列出对象(Bucket=Bucket,Prefix=Prefix)['Contents']:

如果对象['Size']当前文件可以读取为

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='"') 

这是旧的,但是您不再需要中间的ByTeSo对象(至少在我的代码> BOT3==1.9223 < /代码>和<代码> Python 3.7< /代码>)

导入boto3
导入gzip
s3=两种资源(“s3”)
obj=s3.Object(“您的_BUCKET_NAME”、“path/to/YOUR_key.gz”)
使用gzip.gzip文件(fileobj=obj.get()[“Body”])作为gzip文件:
content=gzipfile.read()
打印(内容)

gzip=StringIO(obj)
如果您使用的是Python3,您需要
gzip=BytesIO(obj)
。这是二进制数据。当然你也需要
BytesIO(obj.get()['Body'].read())
@Jean-Françoisfare它起作用了。谢谢。@KshitijMarwah请帮我回答下面的问题。这太棒了。我喜欢这样的事实,它给你的数据在卡盘。您的解决方案有一个小问题,我注意到有时候S3选择拆分行,其中一半行位于一个负载的末尾,另一半行位于下一个负载的开头。这并不难修复,但需要注意的是,尽管它适用于使用GZIP或BZIP2压缩的对象,但这只适用于CSV和JSON对象,只有熊猫才适用于YPD:)
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='"')