【问题标题】:How to iterate over files in an S3 bucket?如何遍历 S3 存储桶中的文件?
【发布时间】:2021-03-24 21:25:15
【问题描述】:

我有大量文件 (>1,000) 存储在 S3 存储桶中,我想迭代它们(例如在 for 循环中)以使用 boto3 从它们中提取数据。

但是,我注意到按照http://boto3.readthedocs.io/en/latest/reference/services/s3.html#S3.Client.list_objectsClient 类的list_objects() 方法最多只能列出1000 个对象:

In [1]: import boto3

In [2]: client = boto3.client('s3')

In [11]: apks = client.list_objects(Bucket='iper-apks')

In [16]: type(apks['Contents'])
Out[16]: list

In [17]: len(apks['Contents'])
Out[17]: 1000

但是,我想列出所有对象,即使有超过 1,000 个。我怎样才能做到这一点?

【问题讨论】:

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


    【解决方案1】:

    正如 kurt-peek 所说,boto3 有一个 Paginator 类,它允许您对 s3 对象的页面进行迭代,并且可以轻松地用于提供对页面内项目的迭代:

    import boto3
    
    
    def iterate_bucket_items(bucket):
        """
        Generator that iterates over all objects in a given s3 bucket
    
        See http://boto3.readthedocs.io/en/latest/reference/services/s3.html#S3.Client.list_objects_v2 
        for return data format
        :param bucket: name of s3 bucket
        :return: dict of metadata for an object
        """
    
    
        client = boto3.client('s3')
        paginator = client.get_paginator('list_objects_v2')
        page_iterator = paginator.paginate(Bucket=bucket)
    
        for page in page_iterator:
            if page['KeyCount'] > 0:
                for item in page['Contents']:
                    yield item
    
    
    for i in iterate_bucket_items(bucket='my_bucket'):
        print i
    

    这将输出如下内容:

    {u'ETag': '"a8a9ee11bd4766273ab4b54a0e97c589"',
     u'Key': '2017-06-01-10-17-57-EBDC490AD194E7BF',
     u'LastModified': datetime.datetime(2017, 6, 1, 10, 17, 58, tzinfo=tzutc()),
     u'Size': 242,
     u'StorageClass': 'STANDARD'}
    {u'ETag': '"03be0b66e34cbc4c037729691cd5efab"',
     u'Key': '2017-06-01-10-28-58-732EB022229AACF7',
     u'LastModified': datetime.datetime(2017, 6, 1, 10, 28, 59, tzinfo=tzutc()),
     u'Size': 238,
     u'StorageClass': 'STANDARD'}
    ...
    

    请注意,建议使用list_objects_v2 而不是list_objectshttps://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGET.html

    您还可以通过直接调用list_objects_v2() 并将响应中的NextContinuationToken 值作为ContinuationToken 传递而在响应中isTruncated 为true 时在较低级别执行此操作。

    【讨论】:

    • 太棒了!!谢谢
    【解决方案2】:

    我发现boto3 有一个Paginator 类来处理截断的结果。以下对我有用:

    paginator = client.get_paginator('list_objects')
    page_iterator = paginator.paginate(Bucket='iper-apks')
    

    之后我可以在for 循环中使用page_iterator 生成器。

    【讨论】:

    【解决方案3】:
    import com.amazonaws.regions.Regions
    import com.amazonaws.services.s3.AmazonS3ClientBuilder
    import com.amazonaws.services.s3.model.ListObjectsRequest
    import java.util._
    
    import scala.collection.JavaConverters._
    
    val s3client = AmazonS3ClientBuilder.standard().withRegion(Regions.US_EAST_1).build()
    val listObjectsRequest = new ListObjectsRequest().withBucketName("<enter_bucket_name>").withPrefix("<enter_path>").withDelimiter("/")
    val bucketListing = s3client.listObjects(listObjectsRequest).getCommonPrefixes.asScala
    
    println("")
    
    for (file <- bucketListing) {
        println(file)
    }
    
    println("")
    

    【讨论】:

    • 感谢您提供此代码 sn-p,它可能会提供一些有限的即时帮助。 proper explanation 将通过展示为什么这是解决问题的好方法,并使其对有其他类似问题的未来读者更有用,从而大大提高其长期价值。请编辑您的答案以添加一些解释,包括您所做的假设。
    猜你喜欢
    • 2012-03-15
    • 2020-07-07
    • 2016-10-20
    • 1970-01-01
    • 2020-08-05
    • 1970-01-01
    • 1970-01-01
    • 2021-03-16
    • 2019-07-10
    相关资源
    最近更新 更多