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

mar*_*tin 5 python amazon-s3 amazon-web-services boto3

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

s3 = boto3.resource('s3')

content = s3.Object(BUCKET_NAME, S3_KEY).get()['Body'].read()
Run Code Online (Sandbox Code Playgroud)

这将返回一个字符串类型。我需要获取的特定文件恰好是一组类似字典的对象,每行一个。所以它不是 JSON 格式。我不想将其作为字符串读取,而是将其作为文件对象流式传输并逐行读取;除了首先在本地下载文件之外,找不到其他方法来执行此操作

s3 = boto3.resource('s3')

bucket = s3.Bucket(BUCKET_NAME)

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

f = open('my-file')
Run Code Online (Sandbox Code Playgroud)

我要问的是是否可以对文件进行这种类型的控制,而不必先在本地下载它?

小智 6

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

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

如果没有 .splitlines() 整个文本块被返回并尝试迭代每一行导致每个字符被迭代。使用 .splitlines() 逐行迭代是可以实现的。

在我的示例中,我遍历每一行并将其编译成一个 dict。

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

for line in txt_file:
    arr = line.split()
    print(arr)
Run Code Online (Sandbox Code Playgroud)

  • 我不知道为什么这个答案得到了这么多票。这种方法实际上是首先将整个文件下载到本地内存,然后将其分割成行。@EnzoMolion 的答案要好得多。 (2认同)

Enz*_*ion 6

You also can take advantage of StreamingBody's iter_lines method:

for line in s3.Object(bucket, file).get()['Body'].iter_lines():
    decoded_line = line.decode('utf-b') # if decoding is needed
Run Code Online (Sandbox Code Playgroud)

That would consume less memory than reading the whole line at once and then split it


小智 0

这将完成以下工作:

bytes_to_read = 512

content = s3.Object(BUCKET_NAME, S3_KEY).get()['Body'].read(bytes_to_read)
Run Code Online (Sandbox Code Playgroud)

  • 仅当 OP 知道每行中有多少字节时,这才有用。该问题没有表明情况确实如此。事实上,线路长度似乎更有可能是未知的 (11认同)