AWS Lambda - dynamically import python module from S3 at runtime

Viewed 1372

I have some tens of python modules, each has one common method (e.g: run(params)) but with different implementations. I also have an AWS Lambda which will need to call that method from within one of those modules. Choosing which module depending on the input of that lambda.

It seems that I can achieve that by using Layers in Lambda. However, if I use one single layer for all those modules, then I could see problems with versioning that. If I need to update one module, I'll need to re-deploy that layer, which could bring unexpected changes to other modules. If I use one layer for each module, then there will be too many layers to manage.

I thought of putting each module into one individual zip file, and put those zip files into an S3 location. My lambda will then dynamically reads the required zip files from S3 and execute.

Is that approach viable?

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

My current solution is to have something like this:

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)

Looks complicate to me though, would expect an easier way.

1 Answers

You could try packaging each module as a separate distribution package, which would let you version them separately. However, creating a Python distribution package is not as simple as you might hope, especially if you want to publish it to a private repository hosted on S3.

Related