Как использовать Asyncio для загрузки файлов на S3 Bucket
Я использую следующий код для загрузки всех моих файлов в корзину 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)
Я хотел бы знать, как сделать это асинхронным, если это возможно.
Спасибо заранее.
3 ответа
Вы можете использовать
generate_presigned_url
метод клиента s3 для получения URL-адреса с учетными данными AWS (см. документы ), а затем отправить запрос на загрузку файла через асинхронный 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())
Aiobotocore обеспечивает поддержку asyncio для библиотеки botocore с использованием aiohttp. Если вы хотите изменить свой код, чтобы использовать вместо него botocore, это было бы решением.
Из коробки boto3 не поддерживает asyncio. Существует проблема отслеживания, которая предлагает некоторые обходные пути; они могут или не могут работать для вашего случая использования.