AWS Lambda - динамический импорт модуля Python из S3 во время выполнения - PullRequest
1 голос
/ 07 октября 2019

У меня есть несколько десятков модулей Python, каждый из которых имеет один общий метод (например: run (params) ), но с разными реализациями. У меня также есть AWS Lambda, который должен вызывать этот метод из одного из этих модулей. Выбор модуля в зависимости от входа этой лямбды.

Кажется, что я могу добиться этого, используя Layers в Lambda. Однако, если я использую один единственный слой для всех этих модулей, то я могу увидеть проблемы с версионированием этого. Если мне потребуется обновить один модуль, мне потребуется повторно развернуть этот уровень, что может привести к неожиданным изменениям в других модулях. Если я использую один слой для каждого модуля, тогда будет слишком много слоев для управления.

Я подумал о том, чтобы поместить каждый модуль в один отдельный zip-файл и поместить эти zip-файлы в папку S3. Затем моя лямбда будет динамически считывать требуемые zip-файлы с S3 и выполнять.

Является ли такой подход жизнеспособным?

=============================

Мое текущее решение состоит в том, чтобы иметь что-то вроде этого:

def read_python_script_from_zip(bucket: str, key: str, script_name: str) -> str:
    s3 = boto3.resource('s3')

    raw = s3.Object(bucket, key).get()['Body'].read()
    zf = zipfile.ZipFile(io.BytesIO(raw), "r")
    scripts = list(filter(lambda f: f.endswith(f"/{script_name}.py"), zf.namelist()))
    if len(scripts) == 0:
        raise ModuleNotFoundError(f"{script_name} not found.")
    if len(scripts) > 1:
        raise ModuleNotFoundError(f"{script_name} is ambiguous.")

    source = zf.read(scripts[0])

    mod = ModuleType(script_name, '')
    exec(source, mod.__dict__)

    return mod

read_python_script_from_zip(source_bucket, source_key, module_name).run(params)

Выглядит сложно, хотя, ожидал бы более легкий путь.

...