У меня есть несколько десятков модулей 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)
Выглядит сложно, хотя, ожидал бы более легкий путь.