I have a directory structure like the following in my serverless application(simplest app to avoid clutter) which I created using AWS SAM with Python 3.8 as the runtime:
├── common
│ └── a.py
├── hello_world
│ ├── __init__.py
│ ├── app.py
│ └── requirements.txt
└── template.yaml
I would like to import common/a.py
module inside the Lambda handler - hello_world/app.py
. Now I know that I can import it normally in Python by adding the path to PYTHONPATH
or sys.path
, but it doesn't work when the code is run in Lambda inside a Docker container. When invoked, the Lambda handler function is run inside /var/task
directory and the folder structure is not regarded.
I tried inserting /var/task/common
, /var/common
, /var
and even /common
to sys.path
programmatically like this:
import sys
sys.path.insert(0, '/var/task/common')
from common.a import Alpha
but I still get the error:
ModuleNotFoundError: No module named 'common'
I am aware of Lambda Layers but given my scenario, I would like to directly reference the common code in multiple Lambda functions without the need of uploading to a layer. I want to have something like the serverless-python-requirements
plugin in the Serverless framework but in AWS SAM.
So my question is, how should I add this path to common
to PYTHONPATH
or sys.path
? Or is there an alternative workaround for this like [serverless-python-requirements][3]
to directly import a module in a parent folder without using Lambda Layers?
__init__.py
? Python 3.3+ has implicit namespace packages, which means that there is no requirement anymore for adding__init__.py
#37140286 As I mentioned, I am using Python 3.8. I also mentioned that I am able to import packages like this in non-lambda environment, I am asking specifically for AWS Lambda(run in a container) which is different from the normal Python execution scenario(/var/task
is the execution directory when run in AWS Lambda) – Ataliecommon
toalphaFolder
, inserted/alphaFolder
,/var/alphaFolder
&/var/task/alphaFolder
tosys.path
in separate runs; still fails! – Ataliesys.path
or nosys.path
, it doesn't matter to me whatsoever. I just want a way to import modules from the parent folder in a Lambda function handler. If you know the answer, please consider posting one and mention the details! – Atalietemplate.yaml
, I am not sure what you have underCodeUri
. I am guessing that you have it asCodeUri: hello_world/
and that's why it isn't working because SAM would only copy the code inside thehello_world
directory. To also include thecommon
folder, you would need to change yourCodeUri
toCodeUri: .
and then you would be able to importfrom common.a import Alpha
. To verify that your directory structure is correct or the file is even present, add this to the top of your lambda handlerimport os
os.system("ls /path/you/want/")
– ThinkerCodeUri
. If your case is like, you have multiple directories at root but only want a couple in the lambda, you won't be able to do that. There are workarounds though and you can have a preprocessing step that updates your directory structure beforesam build
. For example, copyingcommon/
directory inside thehello_world/
one. – Thinker