python-2.7 - 如何使用 boto3 get_object (Python 2.7) 从 S3 获取多个对象

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

我在 S3 中保存了成百上千个对象。我的要求需要我加载这些对象的一个​​子集(5 到 ~3000 之间的任何地方)并读取每个对象的二进制内容。通过阅读 boto3/AWS CLI 文档,似乎不可能在一个请求中获取多个对象,因此目前我已将此实现为一个循环,该循环构建每个对象的键,对对象的请求然后读取对象的主体:

for column_key in outstanding_column_keys:
  try:
     s3_object_key = "%s%s-%s" % (path_prefix, key, column_key)
     data_object = self.s3_client.get_object(Bucket=bucket_key, Key=s3_object_key)
     metadata_dict = data_object["Metadata"]
     metadata_dict["key"] = column_key
     metadata_dict["version"] = float(metadata_dict["version"])
     metadata_dict["data"] = data_object["Body"].read()
     records.append(Record(metadata_dict))
   except Exception as exc:
     logger.info(exc)
if len(records) < len(column_keys):
  raise Exception("Some objects are missing!")

我的问题是,当我尝试获取多个对象(例如 5 个对象)时,我返回 3 个对象,并且在我检查所有对象是否已加载时,有些对象尚未处理。我正在自定义异常中处理它。我想出了一个解决方案来将上面的代码片段包装在一个 while 循环中,因为我知道我需要的优秀键:
while (len(outstanding_column_keys) > 0) and (load_attempts < 10):
 for column_key in outstanding_column_keys:
  try:
     s3_object_key = "%s%s-%s" % (path_prefix, key, column_key)
     data_object = self.s3_client.get_object(Bucket=bucket_key, Key=s3_object_key)
     metadata_dict = data_object["Metadata"]
     metadata_dict["key"] = column_key
     metadata_dict["version"] = float(metadata_dict["version"])
     metadata_dict["data"] = data_object["Body"].read()
     records.append(Record(metadata_dict))
   except Exception as exc:
     logger.info(exc)
if len(records) < len(column_keys):
  raise Exception("Some objects are missing!")

但是我怀疑 S3 实际上仍在处理未完成的响应,而 while 循环会不必要地对 S3 已经在返回过程中的对象发出额外的请求。

我做了一个单独的调查来验证 get_object请求是同步的,似乎它们是:
import boto3
import time
import os

s3_client = boto3.client('s3', aws_access_key_id=os.environ["S3_AWS_ACCESS_KEY_ID"], aws_secret_access_key=os.environ["S3_AWS_SECRET_ACCESS_KEY"])

print "Saving 3000 objects to S3..."
start = time.time()
for x in xrange(3000):
  key = "greeting_{}".format(x)
  s3_client.put_object(Body="HelloWorld!", Bucket='bucket_name', Key=key)
end = time.time()
print "Done saving 3000 objects to S3 in %s" % (end - start)

print "Sleeping for 20 seconds before trying to load the saved objects..."
time.sleep(20)

print "Loading the saved objects..."
arr = []
start_load = time.time()
for x in xrange(3000):
  key = "greeting_{}".format(x)
   try:
     obj = s3_client.get_object(Bucket='bucket_name', Key=key)
     arr.append(obj)
   except Exception as exc:
     print exc
end_load= time.time()
print "Done loading the saved objects. Found %s objects. Time taken - %s" % (len(arr), end_load - start_load)

我的问题和我需要确认的是:
  • 是否get_object请求确实是同步的?如果是,那么我希望当我首先检查加载的对象时
    代码片段然后所有这些都应该被返回。
  • 如果get_object请求是异步的,那么我如何以一种避免向 S3 发出额外请求的方式处理响应
    仍在返回过程中的对象?
  • 进一步澄清/反驳我对 S3 的任何假设也将不胜感激。

  • 谢谢!

    最佳答案

    与 Javascript 不同,Python 以同步方式处理请求,除非您进行某种多线程处理(您在上面的代码段中没有这样做)。在您的 for 循环中,您向 s3_client.get_object 发出请求。 ,并且该调用会阻塞,直到返回数据。自 records数组比它应该的小,这一定意味着正在抛出一些异常,并且应该在except块中捕获它:

    except Exception as exc:
        logger.info(exc)
    

    如果这没有打印任何内容,可能是因为日志记录被配置为忽略 INFO 级别的消息。如果您没有看到任何错误,您可以尝试使用 logger.error 打印.

    关于python-2.7 - 如何使用 boto3 get_object (Python 2.7) 从 S3 获取多个对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47692010/

    相关文章:

    amazon-web-services - 如何通过 Haproxy 与 Neptune 连接?

    amazon-web-services - 未调用 AWS API Gateway 自定义授权方

    amazon-web-services - Amazon Elastic Map Reduce - 让服务器保持事件状态?

    ios - AWSS3 区域/plist 配置问题 'The service configuration is ` nil`

    node.js - 如何确定对象是否存在 AWS S3 Node.JS sdk

    python - 使用 Python 读取输入声音信号

    python - 使用 usecols 时 pandas.read_excel 错误

    java - 将AWS S3配置为图像服务器

    google-app-engine - Google App Engine 上的 SSL 证书

    python-2.7 - 处理由 Python 代码产生的 C++ 子进程引起的段错误