Trouble loading local modules only with AWS Lambda

Question:

app structure:

.
├── Makefile
├── Pipfile
├── Pipfile.lock
├── README.md
├── template.yaml
├── tests
│   ├── __init__.py
│   └── unit
│       └── lambda_application
│           ├── test_handler.py
│           └── test_parent_child_class.py
└── lambda_application
    ├── __init__.py
    ├── first_child_class.py
    ├── lambda_function.py
    ├── second_child_class.py
    ├── requirements.txt
    └── parent_class.py

4 directories, 14 files

Code sample from lambda_function.py:

import os
import json
from hashlib import sha256
import boto3
from requests import Session
from .first_child_class import FirstChildClass


def lambda_handler(event, context):
    # Do some stuff.

As is, I get the error message

Unable to import module ‘lambda_function’

but If I comment out the last import, from .first_child_class import FirstChildClass, it is able to get past that part and get the error that I haven’t loaded the module for that class.

I only seem to get this error when I run it in the lambci/lambda:python3.7 docker image and when I deploy on AWS. All my tests pass and it is able to import the module with no problems.

Is there something I should load/setup in the __init__.py file?

EDIT I changed the names of some of the files to post it here.

Asked By: Hayden

||

Answers:

You are using a relative import here which works in case the code you are executing is in a module. However, since your code is being executed not as a module, your AWS Lambda fails.

https://stackoverflow.com/a/73149/6391078

A quick run locally gave the following error:

PYTHON 3.6

Traceback (most recent call last):
  File "lambda_function.py", line 4, in <module>
    from .first_child_class import FirstChildClass
ModuleNotFoundError: No module named '__main__.first_child_class'; '__main__' is not a package

Your tests pass because your testing suite imports the file as a module from the lambda_application folder which gets treated as a package in the testing module


This got me going in the correct direction but didn’t quite give me the answer but did lead me to the answer, so I thought I would update what I found here.

I didn’t try it but from what I found, I believe that:

from first_child_class import FirstChildClass

would be the simplest resolution.

What I ended up doing was moving the classes into a sub-directory and essentially did the same as above but with a package name prepended.

So, the file structure changed to:

.
├── Makefile
├── Pipfile
├── Pipfile.lock
├── README.md
├── template.yaml
├── tests
│   ├── __init__.py
│   └── unit
│       └── lambda_application
│           ├── test_handler.py
│           └── test_parent_child_class.py
└── lambda_application
    ├── __init__.py
    └── lib
        ├── first_child_class.py
        ├── second_child_class.py
        └── parent_class.py
    ├── lambda_function.py
    └── requirements.txt

and my import became from lib.first_child_class import FirstChildClass

Answered By: Parth Verma