Boto3逐行从S3键读取文件内容

时间:2017-11-29 17:38:06

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

使用boto3,您可以根据给定的存储桶名称和密钥从S3中的某个位置读取文件内容(这假定为初步import boto3

s3 = boto3.resource('s3')

content = s3.Object(BUCKET_NAME, S3_KEY).get()['Body'].read()

返回字符串类型。我需要获取的特定文件恰好是一个类似字典的对象的集合,每行一个。所以它不是JSON格式。我不想将其作为字符串读取,而是将其作为文件对象进行流式处理并逐行读取;除了首先在本地下载文件

之外,找不到办法做到这一点
s3 = boto3.resource('s3')

bucket = s3.Bucket(BUCKET_NAME)

filename = 'my-file'
bucket.download_file(S3_KEY, filename)

f = open('my-file')

我要问的是,是否可以对文件进行此类控制而无需先在本地下载?

5 个答案:

答案 0 :(得分:3)

我发现.splitlines()对我有用...

txt_file = s3.Object(bucket, file).get()['Body'].read().decode('utf-8').splitlines()

如果没有.splitlines(),则会返回整个文本,尝试迭代每一行会导致每个char都被迭代。使用.splitlines()可以实现逐行迭代。

在这里的示例中,我遍历每一行并将其编译成字典。

txt_file = s3.Object(bucket, file).get()['Body'].read().decode(
        'utf-8').splitlines()

for line in txt_file:
    arr = line.split()
    print(arr)

答案 1 :(得分:0)

这将完成工作:

bytes_to_read = 512

content = s3.Object(BUCKET_NAME, S3_KEY).get()['Body'].read(bytes_to_read)

答案 2 :(得分:0)

这对我有用:

json_object = s3.get_object(Bucket = bucket, Key = json_file_name)
json_file_reader = json_object['Body'].read()
content = json.loads(json_file_reader)

答案 3 :(得分:0)

以下commentkooshiwoosh到类似的问题提供了一个很好的答案:

from io import TextIOWrapper
from gzip import GzipFile
...

# get StreamingBody from botocore.response
response = s3.get_object(Bucket=bucket, Key=key)
# if gzipped
gzipped = GzipFile(None, 'rb', fileobj=response['Body'])
data = TextIOWrapper(gzipped)

for line in data:
    # process line

答案 4 :(得分:0)

到目前为止,您可以使用download_fileobj函数。以下是CSV文件的示例:

import boto3
import csv

bucket           = 'my_bucket' 
file_key         = 'my_key/file.csv'
output_file_path = 'output.csv'

s3 = boto3.resource('s3')
bucket = s3.Bucket(bucket)

#Dump binary in append mode
with open(output_file_path, 'ab') as file_object:
    bucket.download_fileobj(
        Key     = file_key, 
        Fileobj = file_object,
    )

#Read your file as usual
with open(output_file_path, 'r') as csvfile:
    lines = csv.reader(csvfile)
    for line in lines:
        doWhatEver(line[0])