#python #amazon-web-services #aws-lambda
#python #amazon-веб-сервисы #aws-lambda
Вопрос:
Я пытаюсь придумать хороший шаблон для будущих лямбд, которые мы пишем в нашей команде.
Одна из целей — попытаться научить объектно-ориентированной разработке некоторых членов команды, поэтому я хотел бы использовать этот шаблон здесь. У меня это нормально работает с другими реальными лямбдами, но, пытаясь добавить полезную библиотеку ‘aws-lambda-powertools-python’, я сталкиваюсь с некоторыми проблемами.
Лямбда-код:
from aws_lambda_powertools import Logger
logger = Logger()
class LambdaExample:
@classmethod
def get_handler(cls, *args, **kwargs):
"""Get handler"""
def handler(event, context):
return cls(*args, **kwargs).handle(event, context)
return handler
@logger.inject_lambda_context(log_event=True)
def handle(self, event, context):
logger.info("Hello World")
lambda_handler = LambdaExample.get_handler()
В документах для powertools есть пример кода для pytest. Однако их пример кода не является полным файлом, и, похоже, предполагается, что лямбда-обработчик является автономной функцией, а не методом класса. Я попытался его адаптировать:
from collections import namedtuple
import pytest
from lambda_example import LambdaExample
@pytest.fixture
def lambda_context():
lambda_context = {
"function_name": "test",
"memory_limit_in_mb": 128,
"invoked_function_arn": "arn:aws:lambda:eu-west-1:809313241:function:test",
"aws_request_id": "52fdfc07-2182-154f-163f-5f0f9a621d72",
}
return namedtuple("LambdaContext", lambda_context.keys())(*lambda_context.values())
class TestLambdaHandler:
def test_handle_will_pass_when_env_setup(self, lambda_context):
# Given
test_event = {'test': 'event'}
lambda_handler = LambdaExample()
# When
lambda_handler.handle(test_event, lambda_context)
Результат, который я получаю, таков:
> lambda_handler.handle(test_event, lambda_context)
E TypeError: decorate() takes 2 positional arguments but 3 were given
Если я удалю эту строку из метода обработчика, все будет работать нормально:
«@logger.inject_lambda_context(log_event=True)»
Проблема, похоже, в том, что декоратор не работает с аргументом ‘self’ в методе.
Есть идеи о том, как это сделать?
Комментарии:
1. Почему вы хотите запутать вызов лямбда-функции, отличной от OO, с помощью объектно-ориентированной оболочки?
2. не показано в этом простом примере, но в полном примере объект lambda создает экземпляры зависимостей и объединяет их вместе. по сути, это простая реализация внедрения зависимостей. Поскольку зависимым классам не требуется разрешать свои собственные зависимости, это упрощает их тестирование. кроме того, я предпочитаю этот шаблон использованию глобальных переменных для повторного использования ресурсов в нескольких вызовах lambda
Ответ №1:
Понял это. Это был простой случай перемещения аннотации следующим образом:
from aws_lambda_powertools import Logger
logger = Logger()
class LambdaExample:
@classmethod
def get_handler(cls, *args, **kwargs):
"""Get handler"""
@logger.inject_lambda_context(log_event=True)
def handler(event, context):
return cls(*args, **kwargs).handle(event, context)
return handler
def handle(self, event, context):
logger.info("Hello World")
lambda_handler = LambdaExample.get_handler()
Затем в тестовом классе вызовите его так же, как и lambda:
lambda_handler = LambdaExample.get_handler()
response = lambda_handler(test_event, lambda_context)