aiobotocore-aiohttp — Получить содержимое файла S3 и передать его в ответ

#python #amazon-s3 #aiohttp #botocore

#python #amazon-s3 #aiohttp #botocore

Вопрос:

Я хочу получить содержимое загруженного файла на S3 с помощью botocore и службы aiohttp. Поскольку файлы могут иметь огромный размер:

  • Я не хочу сохранять все содержимое файла в памяти,
  • Я хочу иметь возможность обрабатывать другие запросы при загрузке файлов с S3 (aiobotocore, aiohttp),
  • Я хочу иметь возможность вносить изменения в файлы, которые я загружаю, поэтому я хочу обработать это построчно и передать ответ клиенту

На данный момент у меня есть следующий код в моем обработчике aiohttp:

 import asyncio                                  
import aiobotocore                              

from aiohttp import web                         

@asyncio.coroutine                              
def handle_get_file(loop):                      

    session = aiobotocore.get_session(loop=loop)

    client = session.create_client(             
        service_name="s3",                      
        region_name="",                         
        aws_secret_access_key="",               
        aws_access_key_id="",                   
        endpoint_url="http://s3:5000"           
    )                                           

    response = yield from client.get_object(    
        Bucket="mybucket",                      
        Key="key",                              
    )                                           
  

Каждый раз, когда я читаю одну строку из данного файла, я хочу отправить ответ. На самом деле, get_object() возвращает dict с телом (объект ClientResponseContentProxy) внутри. Используя метод read(), как я могу получить фрагмент ожидаемого ответа и передать его клиенту?

Когда я делаю :

 for content in response['Body'].read(10):
    print("----")                        
    print(content)          
  

Код внутри цикла никогда не выполняется.

Но когда я делаю :

 result = yield from response['Body'].read(10)
  

В результате я получаю содержимое файла. Я немного запутался в том, как использовать read () здесь.

Спасибо

Ответ №1:

это потому, что aiobotocore api отличается от botocore api, здесь read() возвращается FlowControlStreamReader.read генератор, для которого вам нужно вывести из

это выглядит примерно так (взято из https://github.com/aio-libs/aiobotocore/pull/19 )

 resp = yield from s3.get_object(Bucket='mybucket', Key='k')
stream = resp['Body']
try:
    chunk = yield from stream.read(10)
    while len(chunk) > 0:
      ...
      chunk = yield from stream.read(10)
finally:
  stream.close()
  

и на самом деле в вашем случае вы даже можете использовать readline()

https://github.com/KeepSafe/aiohttp/blob/c39355bef6c08ded5c80e4b1887e9b922bdda6ef/aiohttp/streams.py#L587

Комментарии:

1. Спасибо, это то, что мне было нужно.