Skip to content

Instantly share code, notes, and snippets.

@benkehoe
Last active October 23, 2023 20:30
Show Gist options
  • Save benkehoe/efb75a793f11d071b36fed155f017c8f to your computer and use it in GitHub Desktop.
Save benkehoe/efb75a793f11d071b36fed155f017c8f to your computer and use it in GitHub Desktop.
Code pattern for implementing class-based AWS Lambda handlers in Python
"""Base class for implementing Lambda handlers as classes.
Used across multiple Lambda functions (included in each zip file).
Add additional features here common to all your Lambdas, like logging."""
class LambdaBase(object):
@classmethod
def get_handler(cls, *args, **kwargs):
def handler(event, context):
return cls(*args, **kwargs).handle(event, context)
return handler
def handle(self, event, context):
raise NotImplementedError
"""Implementation of a Lambda handler as a class for a specific Lambda function.
The Lambda function is deployed with handler set to MyLambdaClass.handler.
Class fields will persist across invocations for a given Lambda container,
and so are a good way to implement caching.
An instance of the class is created for each invocation, so instance fields can
be set from the input without the data persisting."""
from LambdaBase import LambdaBase
class MyLambdaClass(LambdaBase):
def __init__(self, ...): # implementation-specific args and/or kwargs
# implementation
def handle(self, event, context):
# implementation
handler = MyLambdaClass.get_handler(...) # input values for args and/or kwargs
@Kashif-Rabbani
Copy link

Thank you!

@claytonpiccinin
Copy link

Hello @benkehoe. I was thinking about your pattern, and I'd like to know:

What if I have more then one function to call inside MyLambdaClass?

Could you provide an example using multiple functions in MyLambdaClass?

Thank's a lot.

@alastairmccormack
Copy link

I found this code very useful but didn't like the repetition of handler = MyLambdaClass.get_handler(...) for each class.

Instead, I created an annotation tag, so I can now do:

@LambdaHandler
class MyLambdaClass(LambdaBase):
    def __init__(self, ...): # implementation-specific args and/or kwargs
        # implementation

    def handle(self, event, context):
        # implementation

def LambdaHandler(func):
    # Creates dynamic handler in caller's module called MyCallingClassHandler

    module = func.__module__
    handler_name = f'{func.__name__}Handler'
    setattr(sys.modules[module], handler_name, func.get_handler() )
    return func

This createss a runtime magic attribute, which can be accessed by MyLambdaClassHandler

@evanerwee
Copy link

I found this code very useful but didn't like the repetition of handler = MyLambdaClass.get_handler(...) for each class.

Instead, I created an annotation tag, so I can now do:

@LambdaHandler
class MyLambdaClass(LambdaBase):
    def __init__(self, ...): # implementation-specific args and/or kwargs
        # implementation

    def handle(self, event, context):
        # implementation

def LambdaHandler(func):
    # Creates dynamic handler in caller's module called MyCallingClassHandler

    module = func.__module__
    handler_name = f'{func.__name__}Handler'
    setattr(sys.modules[module], handler_name, func.get_handler() )
    return func

This createss a runtime magic attribute, which can be accessed by MyLambdaClassHandler

Could you help with a hello world example. I tried but cant get this sample the way you describe to work.

@evanerwee
Copy link

Could you perhaps provide an hello world example based on this template. I tried to get it implemented but failed.

@evanerwee
Copy link

evanerwee commented Apr 27, 2021

I really just need to understand how to create "handler = MyLambdaClass.get_handler(...)" to input event and context.

@evanerwee
Copy link

Anybody else read this: Skip the below, it does not seem to work. The base pattern works well.

@LambdaHandler
class MyLambdaClass(LambdaBase):
def init(self, ...): # implementation-specific args and/or kwargs
# implementation

def handle(self, event, context):
    # implementation

def LambdaHandler(func):
# Creates dynamic handler in caller's module called MyCallingClassHandler

module = func.__module__
handler_name = f'{func.__name__}Handler'
setattr(sys.modules[module], handler_name, func.get_handler() )
return func

@MatiMonaco
Copy link

Thanks bro

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment