使用Boto3将S3对象打开为字符串

Gah*_*evy 126 python amazon-s3 boto boto3

我知道使用Boto 2可以打开一个S3对象作为字符串:

get_contents_as_string() http://boto.readthedocs.org/en/latest/ref/file.html?highlight=contents%20string#boto.file.key.Key.get_contents_as_string

boto3中是否有等效功能?

ksi*_*ndi 186

read将返回字节.至少对于Python 3,如果要返回一个字符串,则必须使用正确的编码进行解码:

import boto3

s3 = boto3.resource('s3')

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

  • @TzunghsingDavidWong 您不必导入包来调用现有对象上的方法,对吧?这可能只是在实验时才需要吗? (2认同)
  • obj = s3.Object(bucket,key) ** Bucket 中 key 的值是什么?关键是文件名???*** 如果我错了请纠正我... (2认同)
  • @Amaresh 是的,bucket = 存储桶名称,key = 文件名 (2认同)

Evg*_*kov 78

由于.get()在AWS Lambda 中使用Python 2.7,我在从S3读取/解析对象时遇到问题.

我在示例中添加了json以显示它变得可解析:)

import boto3
import json

s3 = boto3.client('s3')

obj = s3.get_object(Bucket=bucket, Key=key)
j = json.loads(obj['Body'].read())
Run Code Online (Sandbox Code Playgroud)

注意(对于python 2.7):我的对象都是ascii,所以我不需要 .decode('utf-8')

注意(对于python 3.6+):我们移动到python 3.6并发现read()现在返回bytes所以如果你想从中获取一个字符串,你必须使用:

j = json.loads(obj['Body'].read().decode('utf-8'))

  • 为我工作!AWS Boto3文档很乱 (12认同)

Gah*_*evy 70

这不在boto3文档中.这对我有用:

object.get()["Body"].read()
Run Code Online (Sandbox Code Playgroud)

object是一个s3对象:http://boto3.readthedocs.org/en/latest/reference/services/s3.html#object

  • 截至2016年,boto3得到了可怕的文档. (22认同)
  • http://boto3.readthedocs.io/en/latest/reference/services/s3.html#S3.Object.get告诉我们返回值是一个dict,其中一个StreamingBody类型的键"Body"正在搜索阅读文档将您带到http://botocore.readthedocs.io/en/latest/reference/response.html,它将告诉您使用read(). (3认同)
  • 看来,现在“得到至少1个参数,得到0”。删除“ get()”并直接访问“ Body”对象属性 (3认同)

Gat*_*Lee 6

Python3 + Using boto3 API approach.

By using S3.Client.download_fileobj API and Python file-like object, S3 Object content can be retrieved to memory.

Since the retrieved content is bytes, in order to convert to str, it need to be decoded.

import io
import boto3

client = boto3.client('s3')
bytes_buffer = io.BytesIO()
client.download_fileobj(Bucket=bucket_name, Key=object_key, Fileobj=bytes_buffer)
byte_value = bytes_buffer.getvalue()
str_value = byte_value.decode() #python3, default decoding is utf-8
Run Code Online (Sandbox Code Playgroud)

  • 这比 object.get()["Body"].read() 方法快得多。 (2认同)
  • 这应该是答案。这比任何其他方法(@Jakobovski)都要快,因为它使用多部分下载。基本上,它将文件不同部分的下载分布在多个进程上,然后将结果合并在一起 (2认同)

Ces*_*aro 5

最快的方法

如此处文档所述,download_fileobj使用并行化:

这是一种托管传输,如有必要,它将在多个线程中执行分段下载。

引用aws文档

您可以通过在 GetObjectRequest 中指定部件号来从 S3 检索对象的部件。TransferManager 使用此逻辑异步下载对象的所有部分并将它们写入单独的临时文件。然后,临时文件将合并到用户提供的目标文件中。


可以利用这一点将数据保留在内存中而不是将其写入文件中。

所展示的方法可以做到这一点,这就是为什么它是所列出的方法中最快的@Gatsby Lee原因。无论如何,使用参数可以进一步改进:Config

import io
import boto3

client = boto3.client('s3')
buffer = io.BytesIO()

# This is just an example, parameters should be fine tuned according to:
# 1. The size of the object that is being read (bigger the file, bigger the chunks)
# 2. The number of threads available on the machine that runs this code

config = TransferConfig(
    multipart_threshold=1024 * 25,   # Concurrent read only if object size > 25MB
    max_concurrency=10,              # Up to 10 concurrent readers
    multipart_chunksize=1024 * 25,   # 25MB chunks per reader
    use_threads=True                 # Must be True to enable multiple readers
)

# This method writes the data into the buffer
client.download_fileobj( 
    Bucket=bucket_name, 
    Key=object_key, 
    Fileobj=buffer,
    Config=config
)

str_value = buffer.getvalue().decode()

Run Code Online (Sandbox Code Playgroud)

对于大于 1GB 的对象,就速度而言已经是值得的。