26

我一直使用的方式是将Collection转换为List并查询长度:

s3 = boto3.resource('s3')
bucket = s3.Bucket('my_bucket')
size = len(list(bucket.objects.all()))

但是,这会强制解析整个集合,并首先排除使用集合的好处。有一个更好的方法吗?

4

3 回答 3

38

如果不列出所有对象,就无法获取存储桶中的键数,这是 AWS S3 的限制(请参阅https://forums.aws.amazon.com/thread.jspa?messageID=164220)。

获取对象摘要 (HEAD) 不会获得实际数据,因此应该是一个相对便宜的操作,如果您只是丢弃列表,那么您可以这样做:

size = sum(1 for _ in bucket.objects.all())

这将为您提供对象的数量而无需构建列表。

于 2015-09-05T03:19:26.693 回答
4

借用一个类似的问题,从存储桶 + 前缀中检索对象键的完整列表的一种方法是使用递归与list_objects_v2方法。

此方法将递归检索对象键列表,一次检索 1000 个键。

每个请求都list_objects_v2使用该StartAfter参数在上一个请求的最后一个键之后继续列出键。

import boto3

if __name__ == '__main__':

    client = boto3.client('s3',
        aws_access_key_id     = 'access_key',
        aws_secret_access_key = 'secret_key'
    )

    def get_all_object_keys(bucket, prefix, start_after = '', keys = []):
        response = client.list_objects_v2(
            Bucket     = bucket,
            Prefix     = prefix,
            StartAfter = start_after
        )

        if 'Contents' not in response:
            return keys

        key_list = response['Contents']
        last_key = key_list[-1]['Key']

        keys.extend(key_list)

        return get_all_object_keys(bucket, prefix, last_key, keys)

    object_keys = get_all_object_keys('your_bucket', 'prefix/to/files')

    print(len(object_keys))
于 2017-03-08T18:40:44.047 回答
1

对于我的用例,我只需要知道文件夹是否为空。

s3 = boto3.client('s3')
response = s3.list_objects(
        Bucket='your-bucket',
        Prefix='path/to/your/folder/',
)
print(len(response['Contents']))

这足以知道文件夹是否为空。请注意,如果在 S3 控制台中手动创建文件夹,它本身可以算作资源。在这种情况下,如果上面显示的长度大于 1,则 S3“文件夹”为空。

于 2018-05-21T21:11:19.700 回答