Невозможно сделать запросы aiohttp на AWS Lambda из-за «TypeError: Требуется будущее или сопрограмма» - PullRequest
0 голосов
/ 06 июня 2019

Я хочу, чтобы асинхронный API получал запросы на моей лямбда-aws (время выполнения - python 3.6). Первоначально я пытался использовать grequests, но я не знаю, как скомпилировать это в совместимый с linux комплект для импорта в AWS lambda (я встречал «Gevent требуется для ошибки grequests»). Вместо этого сейчас я использую aysncio / aiohttp. На моем локальном компьютере он работает совершенно нормально, но когда я переношу его в AWS lambda (вручную развернуть, заархивировав пакеты и папку src в .zip, а затем загрузив), я столкнусь с

TypeError: A Future or coroutine is required

/var/runtime/awslambda/bootstrap.py:290: RuntimeWarning: coroutine 'main' was never awaited

Вот соответствующие части моего кода:

import os
import boto3
import json
import base64
from datetime import datetime
import logging
import asyncio
import aiohttp

async def fetch(session, headers, url):
    async with session.get(url, headers=headers ) as response:
        logging.info(response.status)
        return await response.text()


async def main(urls, headers):
    tasks = []
    connector = aiohttp.TCPConnector(limit=13)
    async with aiohttp.ClientSession(connector=connector) as session:
        for url in urls:
            task = asyncio.ensure_future(fetch(session, headers, url))
            tasks.append(task)
        responses = await asyncio.gather(*tasks)
    return responses

# Invoked method
def lambda_handler(event, context):
    my_urls = []
    for record in event['Records']:
        decoded = base64.b64decode(record['kinesis']['data'])
        try:
            url_record = json.loads(decoded)
            url = url_record['url']
            patient_urls.append(url)
        except (json.JSONDecodeError, KeyError):
            error = "Could not read url from record: {}".format(decoded)
            logging.error(error)
            continue
    token = get_token() # method not included as not relevant to error
    if token is not None:
        headers = {"Authorization": "Bearer {}".format(token)}
        loop = asyncio.get_event_loop()
        results = loop.run_until_complete(main(my_urls, headers))
        print("we did it:",len(results))

    else:
        timestamp = str(datetime.now())
        error = timestamp + "Token error"
        logging.error(error)

Я не понимаю, почему эта ошибка возникает, поскольку она прекрасно работает на моей локальной машине, и я практически скопировал код. Вот местный код для справки:

async def fetch(session, headers, url):
    async with session.get(url, headers=headers ) as response:
        return await response.text()


async def main(urls, headers):
    tasks = []
    connector = aiohttp.TCPConnector(limit=13)
    async with aiohttp.ClientSession(connector=connector) as session:
        for url in urls:
            task = asyncio.ensure_future(fetch(session, headers, url))
            tasks.append(task)
        responses = await asyncio.gather(*tasks)
    return responses
start = time.time()
token = get_token()
headers = {"Authorization": "Bearer {}".format(token)}
patient_urls = get_urls()
loop = asyncio.get_event_loop()
a = loop.run_until_complete(main(patient_urls, headers))
print("we did it!",len(a))
end = time.time()
print("it took {} seconds".format(end-start))
...