python - How to invoke AWS lambda function with context argument - Stack Overflow
python - How can I import LambdaContext? - Stack Overflow
amazon web services - How to access context.identity from a Python AWS Lambda function? - Stack Overflow
python - Use context manager in lambda, how? - Stack Overflow
Videos
I am writing a Python Lambda that will be invoked via HTTP. A web service will make an HTTP call to an API Gateway resource that I define, which will then invoke the Lambda. My Lambda handler will look like:
def lambda_handler(event, context):
// do stuff down here
return responseObjectI am trying to find documentation on event and context so I know how to do things like:
-
extract query string parameters from requests
-
extract path parameters from requests
-
inspect the request entity
-
etc.
Surprising I can find no official AWS documentation on what fields/properties these two objects have on them when they are invoked from an API Gateway resource action. I found this article which was sort of helpful but nothing official from AWS. Can anyone point me in the right direction?
You could try using LocalStack:
LocalStack provides an easy-to-use test/mocking framework for developing Cloud applications.
Currently, the focus is primarily on supporting the AWS cloud stack.
LocalStack spins up the following core Cloud APIs on your local machine:
API Gateway at http://localhost:4567
Kinesis at http://localhost:4568
DynamoDB at http://localhost:4569
DynamoDB Streams at http://localhost:4570
Elasticsearch at http://localhost:4571
S3 at http://localhost:4572
Firehose at http://localhost:4573
Lambda at http://localhost:4574
SNS at http://localhost:4575
SQS at http://localhost:4576
Redshift at http://localhost:4577
ES (Elasticsearch Service) at http://localhost:4578
SES at http://localhost:4579
Route53 at http://localhost:4580
CloudFormation at http://localhost:4581
CloudWatch at http://localhost:4582
class LambdaContext defined in /var/runtime/awslambda/bootstrap.py which is used to launch users functions and has the following structure:
class LambdaContext(object):
def __init__(self, invokeid, context_objs, client_context, invoked_function_arn=None):
self.aws_request_id = invokeid
self.log_group_name = os.environ['AWS_LAMBDA_LOG_GROUP_NAME']
self.log_stream_name = os.environ['AWS_LAMBDA_LOG_STREAM_NAME']
self.function_name = os.environ["AWS_LAMBDA_FUNCTION_NAME"]
self.memory_limit_in_mb = os.environ['AWS_LAMBDA_FUNCTION_MEMORY_SIZE']
self.function_version = os.environ['AWS_LAMBDA_FUNCTION_VERSION']
self.invoked_function_arn = invoked_function_arn
self.client_context = make_obj_from_dict(ClientContext, client_context)
if self.client_context is not None:
self.client_context.client = make_obj_from_dict(Client, self.client_context.client)
self.identity = make_obj_from_dict(CognitoIdentity, context_objs)
def get_remaining_time_in_millis(self):
return lambda_runtime.get_remaining_time()
def log(self, msg):
str_msg = str(msg)
lambda_runtime.send_console_message(str_msg, byte_len(str_msg))
If you want to emulate it on your local environment, just add it into your script:
class ClientContext(object):
__slots__ = ['custom', 'env', 'client']
def make_obj_from_dict(_class, _dict, fields=None):
if _dict is None:
return None
obj = _class()
set_obj_from_dict(obj, _dict)
return obj
def set_obj_from_dict(obj, _dict, fields=None):
if fields is None:
fields = obj.__class__.__slots__
for field in fields:
setattr(obj, field, _dict.get(field, None))
class LambdaContext(object):
def __init__(self, invokeid, context_objs, client_context, invoked_function_arn=None):
self.aws_request_id = invokeid
self.log_group_name = os.environ['AWS_LAMBDA_LOG_GROUP_NAME']
self.log_stream_name = os.environ['AWS_LAMBDA_LOG_STREAM_NAME']
self.function_name = os.environ["AWS_LAMBDA_FUNCTION_NAME"]
self.memory_limit_in_mb = os.environ['AWS_LAMBDA_FUNCTION_MEMORY_SIZE']
self.function_version = os.environ['AWS_LAMBDA_FUNCTION_VERSION']
self.invoked_function_arn = invoked_function_arn
self.client_context = make_obj_from_dict(ClientContext, client_context)
if self.client_context is not None:
self.client_context.client = None
self.identity = None
def get_remaining_time_in_millis(self):
return None
def log(self, msg):
str_msg = str(msg)
print(str_msg)
# lambda_runtime.send_console_message(str_msg, byte_len(str_msg))
You can't replace the work with does with an expression, no. There are no hacks to get you there either, because there is no way to handle exceptions and finalisation within an expression.
That's because you can only use one expression in a lambda. with is a statement, not an expression. You'd have to replace that with exception handling (try..except..finally) and calls to the __enter__ and __exit__ methods (storing the __exit__ method first). However, exception handling can only be done with statements, because an exception ends the current expression immediately. See Python Try Catch Block inside lambda.
Your only option is to stick to using a proper function instead.
One possible workaround for getting lambdas working with a context manager is to make the context manager a ContextDecorator, then both with statements and lambda expressions will work because a lambda can use the decorator pattern instead.
Example
from contextlib import ContextDecorator
def f(x):
"""Just prints the input, but this could be any arbitrary function."""
print(x)
class mycontext(ContextDecorator):
def __enter__(self):
f('Starting')
return self
def __exit__(self, *exc):
f('Finishing')
return False
with mycontext():
f('The bit in the middle')
mycontext()(lambda: f('The bit in the middle'))()