【发布时间】:2020-06-12 19:12:21
【问题描述】:
我以前做过 Lambda 函数,但不是在 Python 中。我知道在 Javascript 中 Lambda 支持异步处理函数,但如果我在 Python 中尝试会出错。
这是我要测试的代码:
async def handler(event, context):
print(str(event))
return {
'message' : 'OK'
}
这是我得到的错误:
An error occurred during JSON serialization of response: <coroutine object handler at 0x7f63a2d20308> is not JSON serializable
Traceback (most recent call last):
File "/var/lang/lib/python3.6/json/__init__.py", line 238, in dumps
**kw).encode(obj)
File "/var/lang/lib/python3.6/json/encoder.py", line 199, in encode
chunks = self.iterencode(o, _one_shot=True)
File "/var/lang/lib/python3.6/json/encoder.py", line 257, in iterencode
return _iterencode(o, 0)
File "/var/runtime/awslambda/bootstrap.py", line 149, in decimal_serializer
raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <coroutine object handler at 0x7f63a2d20308> is not JSON serializable
/var/runtime/awslambda/bootstrap.py:312: RuntimeWarning: coroutine 'handler' was never awaited
errortype, result, fatal = report_fault(invokeid, e)
2021 年编辑:
由于这个问题似乎越来越受到关注,我假设人们来到这里试图弄清楚如何让 async 像我一样使用 AWS Lambda。坏消息是,即使在一年多之后的现在,AWS 仍然不支持在基于 Python 的 Lambda 函数中使用异步处理程序。 (我不知道为什么,因为基于 NodeJS 的 Lambda 函数可以很好地处理它。)
好消息是,从 Python 3.7 开始,有一个简单的解决方法,形式为 asyncio.run:
import asyncio
def lambda_handler(event, context):
# Use asyncio.run to synchronously "await" an async function
result = asyncio.run(async_handler(event, context))
return {
'statusCode': 200,
'body': result
}
async def async_handler(event, context):
# Put your asynchronous code here
await asyncio.sleep(1)
return 'Success'
【问题讨论】:
-
我不知道。编程文档只说明了同步
def handler(event, context)选项。 -
asyncio.run不是正确的方法!您将在后续调用时遇到Event loop closed异常。请参阅下面我的答案中的详细信息。 -
@AntonBryzgalov 我不知道这是否是 Lambda 运行时的问题,因为您的答案已经写好了,但是当我使用
asyncio.get_event_loop()时,它抛出了一个错误,因为没有现有的事件循环要得到。因此,您必须手动创建事件循环并关闭它,这真的很难管理,这就是我使用asyncio.run的原因,因为它为您处理创建和关闭循环。我在每个受支持的 Python 运行时 3.7+ 上运行了几次,但从未收到Event loop closed异常。 -
@Abion47 是的,如果您不将任何资源(如数据库连接或 HTTP 客户端)附加到循环,这是可能的。或者,如果您在 Lambda 处理程序函数执行中附加所有资源(而不是在全局 Python 范围内)。但是建议在全局范围内定义连接,因为它允许您通过后续调用重用它们(而不是花时间重新建立连接)。
-
@AntonBryzgalov 那么当你的 lambda 不包含任何此类资源或连接时,如何确保存在循环?
标签: python amazon-web-services aws-lambda async-await python-3.6