AWS 노트

AWS Lambda Python 실행기 (2)

Jonchann 2020. 4. 6. 10:56

event:

{
  "key1": "value1",
  "key2": "value2",
  "key3": "value3"
}

 

저번 글에 작성한 함수의 에러를 찾기보다 먼저 handler를 파악해야 했다.
AWS Lambda에서 제공하는 위의 테스트 이벤트를 사용해 handler를 만든다.

handler 1:

import json

def lambda_handler(event, context):
    return event["key1"]

result 1:

Response:
"value1"    

에러가 나지 않고 실행되었다.


 

handler 2:

import json

def lambda_handler(event, context):
    return event

retult 2:

Response:
{
  "key1": "value1",
  "key2": "value2",
  "key3": "value3"
}

얘도 에러가 나지 않는다.


 

handler 3:

import json

def lambda_handler(event, context):
    return context

result 3:

Response:
{
  "errorMessage": "Unable to marshal response: <bootstrap.LambdaContext object at 0x7f3b0de18ed0> is not JSON serializable",
  "errorType": "Runtime.MarshalError"
}

에러가 났다. Lambda는 에러 메세지를 Json 형식으로 반환한다.

 

사실 인수로 받는 context는 런타임(여기서는 Python3.x) 정보인데 에러 메세지를 보니 이 객체가 JSON 직렬화 가능한 것이 아니라서 marshal response를 못하겠다는 것 같다.

 

AWS Lambda 함수 핸들러(Python)을 보면 핸들러가 json.dumps로 직렬화가 불가능한 객체를 반환하는 경우 런타임에서 오류를 반환하게 됩니다.라고 되어있다.

좀 더 자세하게 찾아봤다.
Stack Overflow에 이런 답이 있었다: How to serialize Python dict to JSON

Python can serialize only the objects that is a built in data type. In your case, "SomeObject" is a User defined type that Python cannot serialize. If you try to serialize any data type which is not json serializable, you get a TypeError "TypeError: is not JSON serializable". So there should be an intermediate step that converts these non built in data types into Python built in serializable data structure (list, dict, number and string).

So let us convert your SomeObject into a python dictionary, since dictionary is the easiest way to represent your Object(as it has key/value pairs). You could just copy all your SomeObject instance attributes to a new dictionary and you are set!

 

사용자가 정의한 객체는 Python이 직렬화 할 수 없고 TypeError: Json 직렬화 불가 에러 메세지를 받는다는거다.
만약 그 객체를 Json 직렬화 시키고 싶다면 dict형태로 바꿔야 한다.

return context.__dict__는 실패했지만 print context.__dict__는 성공했다.

dict_keys(['aws_request_id', 'log_group_name', 'log_stream_name', 'function_name', 'memory_limit_in_mb', 'function_version', 'invoked_function_arn', 'client_context', 'identity', '_epoch_deadline_time_in_ms'])

 

내부 정보는 가져올 수 있는지 확인해보자.

import json

def lambda_handler(event, context):
    return context.log_group_name
Response:
"/aws/lambda/hello-lambda"

성공했다.

 

그럼 dict형태로 만들어주면 return 가능할까.

import json

def lambda_handler(event, context):
    cont_keys = [key for key in context.__dict__.keys()]
    cont_vals = [val for val in context.__dict__.values()]
    return {
        cont_keys[i]: cont_vals[i] for i in range(len(cont_keys))
    }

아래의 'identity'값이 bootstrap.CognitoIdentity 객체라 전체 return은 불가능했다.
'identity': <bootstrap.CognitoIdentity object at 0x7fe9b1cb9990>

 

context는 print만 하는걸로...
gene1wood/example_aws_lambda_cloudformation_context.md