Reputation: 609
I use CDK to deploy lambda function that consists of multiple files. The structure of the directory is as follows.
./
|- makeQ.py
|- lib/
|- module1.py
After deployment and run the labmda function, I got the following error.
[ERROR] Runtime.ImportModuleError: Unable to import module 'index': No module named 'lib'
Traceback (most recent call last):
How can I remove this error and deploy necessary modules with the main code? Are there any sample code of app.py for that purpose?
The codes are as follows:
makeQ.py
import lib.module1;
def main(event, context):
print("hello");
module1.py
def f():
print("f");
app.py
from aws_cdk import (
aws_lambda as lambda_,
core,
)
class MyStack(core.Stack):
def __init__(self, app: core.App, id: str) -> None:
super().__init__(app, id)
with open("makeQ.py", encoding="utf8") as fp:
handler_code = fp.read()
makeQFn = lambda_.Function(
self, "Singleton",
function_name='makeQ',
code=lambda_.InlineCode(handler_code),
handler="index.main",
timeout=core.Duration.seconds(300),
runtime=lambda_.Runtime.PYTHON_3_7,
)
app = core.App()
MyStack(app, "MyStack")
app.synth()
Upvotes: 0
Views: 2596
Reputation: 2400
If you keep each lambda in its own directory, then any sub directories (that have proper __init__.py
file in them to make them modules/packages) will be accessible just from import package.module as normal.
the key then is to use whatever deployment option you are using and specify that the code location is the directory. So if your project directory is as follows:
|- My Project
|- my_lambda/
|- handler.py
|- my_lambda_utilities/
|- __init__.py
|- utilities.py
Since you are using CDK, then you want to use lambda.Code.fromAsset(path)
and select the path to the lambda directory. This will zip the entire directory up and create an asset that CDK will upload to its s3 bucket for deployment. (dont worry, when you bootstraped CDK created its own asset bucket)
InlineCode
should really only be used for lambdas that are like 2-5 lines long because you are literrally writting the lambda code as a string before uploading it to Lambda. Its useful for quick and dirty functions, but not good for things like this.
If its common functionality, then I recommend you zip it up and put it in a layer. For instance:
|- .
|- my_lambda/
|- handler.py
|- my_lambda_utilities/
|- __init__.py
|- utilities.py
|- common_utilities/
|- __init__.py
|- dynamo_util.py
You can zip common_utilities
into a zip inside a python directory, and upload it into lambda as a layer.
So your zip would look like
|- python/
|- common_utilities/
|- __init__.py
|- dynamo_util.py
and then you can import common_utilities.dynamo_util
in any lambda that layer is included in.
Upvotes: 4