AWS Lambda Function can import a module when run locally, but not when deployed

为君一笑 提交于 2019-12-09 06:51:28

I found a "solution" to this, by installing the dependencies of my code in the main directory rather than the root directory. However, I believe that a superior option would be to use layers to hold dependencies.

CodeBuild build environments (specifically when using managed images) are based on Ubuntu base images - these dependencies might not be compatible when running on Lambda. This is because Lambda container environments are based on Amazon Linux - https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html

You can try fixing this by packaging the dependency in your source bundle and skipping this from your 'requirements.txt' file.

If I'm not wrong a similar issue is addressed at - Using moviepy, scipy and numpy in amazon lambda

The reason that your lambda execution says "Unable to import module" when running in the actual AWS Lambda execution environment is because your lambda deployment package (that was uploaded to S3 by aws cloudformation package command) is missing required dependencies specified in your requirements.txt.

Command like aws cloudformation package or sam package will work with AWS::Serverless::Function resource in your CloudFormation template by zipping all contents (regardless of whether it is source code, dependencies or any other stuff) in a directory specified via CodeUri property then it will upload that resulting zip file to S3 bucket giving you a transformed CloudFormation template where the S3 bucket path to your deployment package replaces the path to the source code in your local machine specified in CodeUri property.

Looking at your buildspec.yml, I think the problem comes from -t . option you specified in pip install -r hello_world/requirements.txt -t . command in the install phase. This will install dependencies in a current directory (usually the root directory of your project) and not in the directory where the source code of hello_world lambda function resides. Thus, the dependencies will not get zipped together with the source code in the later aws cloudformation package step.

In general, when you create a lambda function deployment package (whether it's SAM-enabled or plain-old Lambda), you need to bundle everything (source code, dependencies, resources, etc.) that is used in your app. You usually do that by:-

  1. Use sam build command if it's SAM-enabled CloudFormation template. This command will automatically find your requirements.txt and install specified dependencies into the .aws-sam directory in preparation for uploading to S3.

  2. Manually run pip install -r requirements.txt to the right directory where contents get zipped as a deployment package for deploying lambda function. This works in both SAM-enabled or plain-old Lambda CloudFormation template.

If your CodeUri is pointing to /main, the content of this folder will be zip and uploaded to S3 when running aws cloudformation package, but without the dependencies.

The difference when running sam package is that it installs the dependencies from requirements.txt for you and outputs it to .aws-sam/build/<functionname> folder.

So, in order to package the dependencies you need to access the function folder and install the dependencies locally, eg.

  • pip install -r requirements.txt -t .
  • then run aws cloudformation package --s3-bucket <YOUR_BUCKET> --template-file <YOUR TEMPLATE YAML> --output-template-file <OUTPUT TEMPLATE NAME YAML>.
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!