【问题标题】:How to use asyncio to download files on s3 bucket如何使用 asyncio 下载 s3 存储桶上的文件
【发布时间】:2017-12-08 11:35:48
【问题描述】:

我正在使用以下代码将我的所有文件下载到 s3 存储桶中:

def main(bucket_name, destination_dir):
    bucket = boto3.resource('s3').Bucket(bucket_name)
    for obj in bucket.objects.all():
        if obj.key.endswith('/'):
            continue
        destination = '%s/%s' % (bucket_name, obj.key)
        if not os.path.exists(destination):
            os.makedirs(os.path.dirname(destination), exist_ok=True)
        bucket.download_file(obj.key, destination)

如果可能的话,我想知道如何使这个异步。

提前谢谢你。

【问题讨论】:

    标签: python-3.x amazon-s3 boto boto3


    【解决方案1】:

    Aiobotocore 使用 aiohttp 为 botocore 库提供异步支持。如果您愿意修改代码以改用botocore,那将是一个解决方案。

    【讨论】:

      【解决方案2】:

      开箱即用,boto3 不支持异步。在此打开了一个tracking issue,它提供了一些解决方法;它们可能适用于您的用例,也可能不适用于您的用例。

      【讨论】:

        【解决方案3】:

        您可以使用s3客户端的generate_presigned_url方法获取带有AWS凭证的URL(见docs),然后通过异步HTTP客户端发送下载文件的请求(例如aiohttp

        import boto3
        import asyncio
        from aiohttp import client
        
        bucket = 'some-bucket-name'
        
        s3_client = boto3.client('s3')
        s3_objs = s3_client.list_objects(Bucket=bucket)['Contents']
        
        async def download_s3_obj(key: str, aiohttp_session: client.ClientSession):
            request_url = s3_client.generate_presigned_url('get_object', {
                'Bucket': bucket,
                'Key': key
            })
        
            async with aiohttp_session.get(request_url) as response:
                file_path = 'some-local-folder-name/' + key.split('/')[-1]
        
                with open(file_path, 'wb') as file:
                    file.write(await response.read())
        
        async def get_tasks():
            session = client.ClientSession()
        
            return [download_s3_obj(f['Key'], session) for f in s3_objs], session
        
        loop = asyncio.get_event_loop()
        tasks, session = loop.run_until_complete(get_tasks())
        loop.run_until_complete(asyncio.gather(*tasks))
        
        loop.run_until_complete(session.close())
        

        【讨论】:

          猜你喜欢
          • 2018-12-31
          • 2019-05-30
          • 2013-04-29
          • 2018-01-04
          • 1970-01-01
          • 2015-05-20
          • 2021-07-18
          • 1970-01-01
          • 2019-02-16
          相关资源
          最近更新 更多