Python 使用 boto 调用 lambda 函数如何异步执行此操作?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/39456309/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using boto to invoke lambda functions how do I do so asynchronously?
提问by sometimesiwritecode
SO I'm using boto to invoke my lambda functions and test my backend. I want to invoke them asynchronously. I have noted that "invoke_async" is deprecated and should not be used. Instead you should use "invoke" with an InvocationType of "Event" to do the function asynchronously.
所以我使用 boto 来调用我的 lambda 函数并测试我的后端。我想异步调用它们。我注意到“invoke_async”已被弃用,不应使用。相反,您应该使用具有“事件”的 InvocationType 的“invoke”来异步执行该功能。
I can't seem to figure out how to get the responses from the functions when they return though. I have tried the following:
我似乎无法弄清楚如何在函数返回时从函数中获取响应。我尝试了以下方法:
payload3=b"""{
"latitude": 39.5732160891,
"longitude": -119.672918997,
"radius": 100
}"""
client = boto3.client('lambda')
for x in range (0, 5):
response = client.invoke(
FunctionName="loadSpotsAroundPoint",
InvocationType='Event',
Payload=payload3
)
time.sleep(15)
print(json.loads(response['Payload'].read()))
print("\n")
Even though I tell the code to sleep for 15 seconds, the response variable is still empty when I try and print it. If I change the invokation InvokationType to "RequestResponse" it all works fine and response variable prints, but this is synchronous. Am I missing something easy? How do i execute some code, for example print out the result, when the async invokation returns??
即使我告诉代码休眠 15 秒,当我尝试打印它时,响应变量仍然是空的。如果我将 invokation InvokationType 更改为“RequestResponse”,则一切正常,并且会打印响应变量,但这是同步的。我错过了一些简单的东西吗?当异步调用返回时,我如何执行一些代码,例如打印出结果?
Thanks.
谢谢。
采纳答案by Leon
An asynchronously executed AWS Lambda function doesn't return the result of execution. If an asynchronous invocation request is successful (i.e. there were no errors due to permissions, etc), AWS Lambda immediately returns the HTTP status code 202 ACCEPTEDand bears no further responsibility for communicating any information about the outcome of this asynchronous invocation.
异步执行的 AWS Lambda 函数不会返回执行结果。如果异步调用请求成功(即没有由于权限等导致的错误),AWS Lambda 会立即返回 HTTP 状态代码202 ACCEPTED,并且不再负责传达有关此异步调用结果的任何信息。
From the documentation of AWS Lambda Invoke action:
从AWS Lambda Invoke action的文档中:
Response Syntax
HTTP/1.1 StatusCode X-Amz-Function-Error: FunctionError X-Amz-Log-Result: LogResult Payload
Response Elements
If the action is successful, the service sends back the following HTTP response.
StatusCode
The HTTP status code will be in the 200 range for successful request. For the
RequestResponse
invocation type this status code will be 200. For theEvent
invocation type this status code will be 202. For theDryRun
invocation type the status code will be 204.[...]
The response returns the following as the HTTP body.
Payload
It is the JSON representation of the object returned by the Lambda function. This is present only if the invocation type is
RequestResponse
.
响应语法
HTTP/1.1 StatusCode X-Amz-Function-Error: FunctionError X-Amz-Log-Result: LogResult Payload
响应元素
如果操作成功,服务会发回以下 HTTP 响应。
状态码
成功请求的 HTTP 状态代码将在 200 范围内。对于
RequestResponse
调用类型,此状态代码将为 200。 对于Event
调用类型,此状态代码将为 202。对于DryRun
调用类型,状态代码将为 204。[...]
响应将以下内容作为 HTTP 正文返回。
有效载荷
它是 Lambda 函数返回的对象的 JSON 表示。仅当调用类型为 时才存在
RequestResponse
。
回答by Julien
There is a difference between an 'async AWS lambda invocation'and 'async python code'. When you set the InvocationType
to 'Event'
, by definition, it does not ever send back a response.
'async AWS lambda invocation'和'async python code'之间存在差异。当您将 设置为InvocationType
时'Event'
,根据定义,它永远不会发回响应。
In your example, invoke()
immediately returns None
, and does not implicitly start up anything in the background to change that value at a later time (thank goodness!). So, when you look at the value of response
15 seconds later, it's still None
.
在您的示例中,invoke()
立即返回None
,并且不会在后台隐式启动任何内容以在以后更改该值(谢天谢地!)。因此,当您查看response
15 秒后的值时,它仍然是None
。
It seems what you really want is the RequestResponse
invocation type, with asynchronous Python code. You have a bunch of options to choose from, but my favorite is concurrent.futures
. Another is threading
.
看起来您真正想要的是RequestResponse
具有异步 Python 代码的调用类型。您有很多选择可供选择,但我最喜欢的是concurrent.futures
. 另一个是threading
。
Here's an example using concurrent.futures
:
这是一个使用示例concurrent.futures
:
(If you're using Python2 you'll need to pip install futures
)
(如果您使用的是 Python2,则需要pip install futures
)
from concurrent.futures import ThreadPoolExecutor
import json
payload = {...}
with ThreadPoolExecutor(max_workers=5) as executor:
futs = []
for x in xrange(0, 5):
futs.append(
executor.submit(client.invoke,
FunctionName = "loadSpotsAroundPoint",
InvocationType = "RequestResponse",
Payload = bytes(json.dumps(payload))
)
)
results = [ fut.result() for fut in futs ]
print results
Another pattern you might want to look into is to use the Event
invocation type, and have your Lambda function push messages to SNS, which are then consumed by another Lambda function. You can check out a tutorial for SNS-triggered lambda functions here.
您可能想要研究的另一种模式是使用Event
调用类型,并将您的 Lambda 函数推送消息到 SNS,然后由另一个 Lambda 函数使用。您可以在此处查看有关 SNS 触发的 lambda 函数的教程。
回答by ylev
The following are a python function that accepts lambda-function-Name to invoke and payload to send to that function.
以下是接受 lambda-function-Name 调用和有效载荷发送到该函数的 python 函数。
It invokes the lambda function by boto3 client.
它通过 boto3 客户端调用 lambda 函数。
import boto3, json, typing
def invokeLambdaFunction(*, functionName:str=None, payload:typing.Mapping[str, str]=None):
if functionName == None:
raise Exception('ERROR: functionName parameter cannot be NULL')
payloadStr = json.dumps(payload)
payloadBytesArr = bytes(payloadStr, encoding='utf8')
client = boto3.client('lambda')
response = client.invoke(
FunctionName=functionName,
InvocationType="RequestResponse",
Payload=payloadBytesArr
)
return response
And usage:
和用法:
if __name__ == '__main__':
payloadObj = {"something" : "1111111-222222-333333-bba8-1111111"}
response = invokeLambdaFunction(functionName='myLambdaFuncName', payload=payloadObj
print(f'response:{response}')