【问题标题】:How to check if a particular file exists in a top level folder in s3, using lambda, boto3 and python 2.7如何使用 lambda、boto3 和 python 2.7 检查 s3 的顶级文件夹中是否存在特定文件
【发布时间】:2019-03-21 10:23:04
【问题描述】:

我猜这个问题有两个部分,但我会解释一下: 场景:

我有一个 lambda 函数,如果用户没有文件夹,它会在 S3 中创建一个文件夹,然后最终将填充 mp3 文件。对于我的测试用例,我必须处理文件是否存在。为此,我正在尝试使用它:

s3client = boto3.client('s3')
bucket_name = os.environ['BUCKET_NAME']
prefix = email + "/"
resp = s3client.list_objects(Bucket=bucket_name, Prefix=prefix, Delimiter="/")
print resp 
print resp.get(email + "/" + postId + ".mp3")

我总是得到 NoneType 因为它不存在,但出于测试目的,我已经创建了所有内容,我只想通过成功案例,所以它确实存在,但我没有正确“获取”信息。

打印“resp”变量得到的响应是:

{u'Name': 'listen-n-save-mp3', 'ResponseMetadata': {'HTTPStatusCode': 200, 'RetryAttempts': 0, 'HostId': 'QcxxxfYu1GunfZ2dXMUo=', 'RequestId': '16BCFFD288F16D74', 'HTTPHeaders': {'x-amz-bucket-region': 'us-east-1', 'x-amz-id-2': 'QRxZVUnWzcxxx22K5RoFKgxKfYu1GunfZ2dXMUo=', 'server': 'AmazonS3', 'transfer-encoding': 'chunked', 'x-amz-request-id': '16BCFFD288F16D74', 'date': 'Tue, 16 Oct 2018 19:23:06 GMT', 'content-type': 'application/xml'}}, u'Delimiter': u'/', u'MaxKeys': 1000, u'Prefix': 'philips%40exmaple.com/', u'Marker': u'', u'EncodingType': 'url', u'IsTruncated': False, u'Contents': [{u'LastModified': datetime.datetime(2018, 10, 16, 19, 22, 6, tzinfo=tzlocal()), u'ETag': '"xxxx"', u'StorageClass': 'STANDARD', u'Key': u'philips@exmaple.com/', u'Owner': {u'DisplayName': 'listennsave', u'ID': 'xxxx'}, u'Size': 0}, {u'LastModified': datetime.datetime(2018, 10, 16, 18, 57, 43, tzinfo=tzlocal()), u'ETag': '"xxxx"', u'StorageClass': 'STANDARD', u'Key': u'philips@exmaple.com/supImanId.mp3', u'Owner': {u'DisplayName': 'listennsave', u'ID': 'xxx'}, u'Size': 36942}]}

很遗憾,响应真的很长,并且自动格式化为一行,但文件夹中有一个名为 u'Key': u'philips@exmaple.com/supImanId.mp3' 的键,您可以在该行的末尾看到它。我的第一个问题是如何使用我的 get 方法正确访问该密钥?

我的第二个问题是,当我知道我正确获取了密钥并且它返回 NoneType (意味着它尚未创建)时,我如何将它用作允许函数继续的条件语句?

感谢您的宝贵时间。

================================================ ===================

编辑:这就是我现在拥有的

s3client = boto3.client('s3')
bucket_name = os.environ['BUCKET_NAME']
prefix = email + "/"
print bucket_name
resp = s3client.list_objects(Bucket=bucket_name, Prefix=prefix, Delimiter="/")

this_item =  [item for item in resp['Contents'] if item.get('Key')==email + "/" + postId + ".mp3" ]
try:
    this_item[0]['Key']
except IndexError:
    pass
continue

问题是,如果我什么都没有返回,我希望这个函数能正常工作。我尝试使用此语法,但收到有关循环的错误

Syntax error in module 'lambda_function': 'continue' not properly in loop (lambda_function.py, line 80)

所以我需要一个我假设的循环?我应该在哪里以及如何使用当前设置开始循环?看起来很简单,但我对 Python 很陌生,所以它会很有帮助!

【问题讨论】:

    标签: python python-2.7 amazon-s3 aws-lambda boto3


    【解决方案1】:

    来自list_objects() 的响应遵循一个定义的结构,该结构定义了一堆关于请求的元数据以及结果内容。您可以在boto3 documentation 中详细了解响应文件中的内容及其结构。

    响应对象只是一个字典。 Key 的值嵌套在 Contents 中,因此要在响应对象中访问 Key,您可以使用:

    k = resp['Contents']['Key']
    

    如果请求返回多个键,那么您也可以直接遍历 Contents 对象并创建一个包含所有返回键的列表,如下所示:

    all_keys = [k["Key"] for k in resp["Contents"]
    

    【讨论】:

    • 感谢您的回复,我考虑了问题并意识到即使我不懂 Python,它也很简单。在我的编辑中,我的答案与您的答案相似,但我需要正确处理 NoneType 。我想知道如何在我的场景中设置该循环。抱歉,如果我问了一个不好的问题,但我觉得我需要与某人讨论这个问题。无论如何我会检查你的答案。
    • 您的问题并不完全清楚。如果您只是想确定是否存在密钥,则应查看此答案:Check if a Key Exists in a S3 Bucket。您不需要使用list_objects() 并且可以直接测试密钥然后捕获密钥不存在的实例。另请注意,list_objects() 仅返回 1000 个项目。如果退回的数量超过此数量,则会遇到问题。
    猜你喜欢
    • 2016-05-04
    • 2021-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-23
    • 2018-11-17
    • 1970-01-01
    相关资源
    最近更新 更多