170

I am creating a AWS Lambda python deployment package. I am using one external dependency requests. I installed the external dependency using the AWS documentation. Below is my Python code.

import requests

print('Loading function')

s3 = boto3.client('s3')


def lambda_handler(event, context):
    #print("Received event: " + json.dumps(event, indent=2))

    # Get the object from the event and show its content type
    bucket = event['Records'][0]['s3']['bucket']['name']
    key = urllib.unquote_plus(event['Records'][0]['s3']['object']['key']).decode('utf8')
    try:
        response = s3.get_object(Bucket=bucket, Key=key)
        s3.download_file(bucket,key, '/tmp/data.txt')
        lines = [line.rstrip('\n') for line in open('/tmp/data.txt')]
        for line in lines:
            col=line.split(',')
            print(col[5],col[6])
        print("CONTENT TYPE: " + response['ContentType'])
        return response['ContentType']
    except Exception as e:
        print(e)
        print('Error getting object {} from bucket {}. Make sure they exist and your bucket is in the same region as this function.'.format(key, bucket))
        raise e

Created the Zip the content of the project-dir directory and uploaded to the lambda(Zip the directory content, not the directory). When I am execute the function I am getting the below mentioned error.

START RequestId: 9e64e2c7-d0c3-11e5-b34e-75c7fb49d058 Version: $LATEST
**Unable to import module 'lambda_function': No module named lambda_function**

END RequestId: 9e64e2c7-d0c3-11e5-b34e-75c7fb49d058
REPORT RequestId: 9e64e2c7-d0c3-11e5-b34e-75c7fb49d058  Duration: 19.63 ms  Billed Duration: 100 ms     Memory Size: 128 MB Max Memory Used: 9 MB
Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
Nithin
  • 9,661
  • 14
  • 44
  • 67
  • Is it your full code? By the error it seems somewhere something would want to `import lambda_function` which is not found. Perhaps you want `from future import lambda_function`? Or just *pip install lambda_function* on cmd line. – Berci Feb 11 '16 at 13:45
  • @Berci Am running this python codein AWS platform . I cannot use pip. anywhere in my code am using lambda_function. IF i copy paste the same code in AWS console it will work – Nithin Feb 11 '16 at 13:49
  • See the last comment on [this thread](https://gist.github.com/kapilt/770bdf5d2a55b7385a9c) — maybe applies to you? – Matt Hall Feb 11 '16 at 13:50
  • @kwinkunks I tried that. Actually am zipping the content not the directory!! – Nithin Feb 11 '16 at 13:52
  • 5
    My guess is that "handler" option in your function is incorrect. Check that your filename called "lambda_function.py" and handler method is "lambda_handler" – Vor Feb 11 '16 at 15:19
  • 3
    I spent hours, finally came to know that you have to zip the content of your directory ( including lambda_function.py ) and not the directory. – sumitb.mdi Sep 04 '16 at 02:57
  • My code is just in lambda as code -- not as a file. – Ben Wheeler Aug 29 '17 at 18:36
  • Agreed with comments from @Vor. His suggestions helped clear the doubt. – Swapnadeep Mukherjee Jun 06 '21 at 11:08
  • **Make sure that you are zipping the contents of the directory and not the directory itself.** – Michael Jan 27 '22 at 22:57

32 Answers32

193

Error was due to file name of the lambda function. The console no longer asks you what handler name you want - it just sets it to "lambda_function.lambda_handler".

So, you need to make sure your filename is "lambda_function.py" and the function name in there is "lambda_handler".

The other alternative is explicitly setting the name of the handler after creating the function.

N R
  • 333
  • 3
  • 14
Nithin
  • 9,661
  • 14
  • 44
  • 67
  • 3
    My code is just in lambda as code -- not as a file. – Ben Wheeler Aug 29 '17 at 18:35
  • 6
    @BenWheeler: Even-though it is inline code, it is to a file you actually write it. You can see the filename and whole directory structure to left of the window. – Vineeth Jan 31 '18 at 06:13
  • So I had named my code as "lambda_function.py", should I name the handler as Python_lambda_function.lambda_handler? – RB17 Aug 26 '19 at 00:05
  • 1
    @RahulBanerjee No. you would call it as lambda_function.lambda_handler – Dinesh Nov 27 '19 at 18:43
  • I received the same error, but my handle is called lambda_function.lamda_handler and my code is called lambda_function.py, it should work – Ace Cabbie Jun 24 '21 at 18:27
161

If you are uploading a zip file. Make sure that you are zipping the contents of the directory and not the directory itself.

2ank3th
  • 2,948
  • 2
  • 21
  • 35
36

Another source of this problem is the permissions on the file that is zipped. It MUST be at least world-wide readable. (min chmod 444)

I ran the following on the python file before zipping it and it worked fine.

chmod u=rwx,go=r
Catalin Ciurea
  • 771
  • 1
  • 9
  • 7
  • 4
    This. I was using Python's ZipFile to programatically package up the lambda functions into the ZIP, it defaults to having `0600` which as you mention is not enough. Further, the integrated Lambda source code editor (on the Amazon web page) will happily read the file without warning of permissions issues. – cjhanks Sep 25 '16 at 21:54
  • 2
    Second. I got it working by setting file permissions using the method shown here: http://stackoverflow.com/a/434689/931277 – dokkaebi Feb 15 '17 at 19:59
28

I found Nithin's answer very helpful. Here is a specific walk-through:

Look-up these values:

  1. The name of the lambda_handler function in your python script. The name used in the AWS examples is lambda_handler looking like def lambda_handler(event, context). In this case, the value is lambda_handler
  2. In the Lambda dashboard, find the name of the Handler in the Handler text-box in the Configuration section in the lambda dashboard for the function (shown in Nithin's screenshot). My default name was lambda_function.lambda_handler.
  3. The name of your python script. Let's say it's cool.py

With these values, you would need to rename the handler (shown in the screenshot) to cool.lambda_handler. This is one way to get rid of the "Unable to import module lambda_function" errorMessage. If you were to rename the handler in your python script to sup then you'd need to rename the handler in the lambda dashboard to cool.sup

Krithick S
  • 408
  • 3
  • 15
user3303554
  • 2,215
  • 2
  • 16
  • 16
24

Here's a quick step through.

Assume you have a folder called deploy, with your lambda file inside call lambda_function.py. Let's assume this file looks something like this. (p1 and p2 represent third-party packages.)

import p1
import p2

def lambda_handler(event, context):
    # more code here

    return {
        "status": 200,
        "body" : "Hello from Lambda!",
    }

For every third-party dependency, you need to pip install <third-party-package> --target . from within the deploy folder.

pip install p1 --target .
pip install p2 --target .

Once you've done this, here's what your structure should look like.

deploy/
├── lambda_function.py
├── p1/
│   ├── __init__.py
│   ├── a.py
│   ├── b.py
│   └── c.py
└── p2/
    ├── __init__.py
    ├── x.py
    ├── y.py
    └── z.py

Finally, you need to zip all the contents within the deploy folder to a compressed file. On a Mac or Linux, the command would look like zip -r ../deploy.zip * from within the deploy folder. Note that the -r flag is for recursive subfolders.

The structure of the file zip file should mirror the original folder.

deploy.zip/
├── lambda_function.py
├── p1/
│   ├── __init__.py
│   ├── a.py
│   ├── b.py
│   └── c.py
└── p2/
    ├── __init__.py
    ├── x.py
    ├── y.py
    └── z.py

Upload the zip file and specify the <file_name>.<function_name> for Lambda to enter into your process, such as lambda_function.lambda_handler for the example above.

openwonk
  • 14,023
  • 7
  • 43
  • 39
  • 4
    Additionally, do NOT zip the entire folder like `zip -r deploy.zip deploy`. This will create a deploy folder within the zip file. – openwonk Aug 17 '19 at 03:42
17

There are just so many gotchas when creating deployment packages for AWS Lambda (for Python). I have spent hours and hours on debugging sessions until I found a formula that rarely fails.

I have created a script that automates the entire process and therefore makes it less error prone. I have also wrote tutorial that explains how everything works. You may want to check it out:

Hassle-Free Python Lambda Deployment [Tutorial + Script]

joarleymoraes
  • 1,891
  • 14
  • 16
  • 3
    Great post but I miss details on the hardest part which is how to package native libs. Its really not normal how complex this is – WJA Jan 09 '19 at 15:54
12

I found this hard way after trying all of the solutions above. If you're using sub-directories in the zip file, ensure you include the __init__.py file in each of the sub-directories and that worked for me.

Nathan Tuggy
  • 2,237
  • 27
  • 30
  • 38
KApuri
  • 121
  • 1
  • 2
12

In lambda_handler the format must be lambda_filename.lambda_functionName. Supposing you want to run the lambda_handler function and it's in lambda_function.py, then your handler format is lambda_function.lambda_handler.

Another reason for getting this error is module dependencies.

Your lambda_function.py must be in the root directory of the zip file.

Taras Melnyk
  • 3,057
  • 3
  • 38
  • 34
Primit
  • 825
  • 7
  • 13
8

I had the error too. Turn out that my zip file include the code parent folder. When I unzip and inspect the zip file, the lambda_function file is under parent folder ./lambda.

Use the zip command, fix the error:

zip -r ../lambda.zip ./*
taras
  • 6,566
  • 10
  • 39
  • 50
Joe
  • 81
  • 1
  • 3
  • 1
    run the zip inside your code folder. my case here, cd lambda && zip -r ../lambda.zip ./* – Joe Sep 16 '17 at 09:07
7

Go to Lambda functions, then select Layers, then scroll to Runtime settings and click Edit.

enter image description here

You may also configure the SAM with the specific Handler in your YAML file. Example below.

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: An AWS Serverless Specification template describing your function.
Resources:
  getRecommendation:
    Type: 'AWS::Serverless::Function'
    Properties:
      Handler: pythonfilename.lambda_handler
      Runtime: python3.7
      CodeUri: .
      Description: ''
      MemorySize: 128
      Timeout: 3
      Role: 'arn:aws:iam::xxxxx:role/lambdaroleIam'
rabkaman
  • 121
  • 1
  • 6
4

Make sure that you are zipping all dependencies in a folder structure as python/[Your All Dependencies] to make it work as per this documentation.

https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html#configuration-layers-path

Sachin Kumar
  • 470
  • 6
  • 7
4

The issue here that the Python version used to build your Lambda function dependencies (on your own machine) is different than the selected Python version for your Lambda function. This case is common especially if the Numpy library part of your dependencies.

Example: Your machine's python version: 3.6 ---> Lambda python version 3.6

Sharhabeel Hamdan
  • 1,273
  • 13
  • 15
4

I was building the lambda via a container, rather than a zip file.

What solved it in my case was to copy the project into the "${LAMBDA_TASK_ROOT}" folder, and not just a custom folder of my choosing.

FROM public.ecr.aws/lambda/python:3.8

WORKDIR ${LAMBDA_TASK_ROOT}
COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt
COPY . .
CMD ["lambda_function.lambda_handler"]

Even though I previously set the WORKDIR, and even tried to use the "WORKDIR override" setting in Lambda, it only worked when I used the "${LAMBDA_TASK_ROOT}" folder.

Dharman
  • 30,962
  • 25
  • 85
  • 135
UriP
  • 526
  • 1
  • 5
  • 8
2

@nithin, AWS released layers concept inside Lambda functions. You can create your layer and there you can upload as much as libraries and then you can connect the layer with the lambda functions. For more details: https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html

muTheTechie
  • 1,443
  • 17
  • 25
2

A perspective from 2019:

AWS Lambda now supports Python 3.7, which many people (including myself) choose to use as the runtime for inline lambdas.

Then I had to import an external dependency and I followed AWS Docs as the OP referred to. (local install --> zip --> upload).

I had the import module error and I realised my local PC had Python 2.7 as the default Python. When I invoked pip, it installed my dependency for Python 2.7.

So I switched locally to the Python version that matches the selected runtime version in the lambda console and then re-installed the external dependencies. This solved the problem for me. E.g.:

$ python3 -m pip install --target path/to/lambda_file <external_dependency_name>
l001d
  • 723
  • 9
  • 15
2

TL;DR, try chmod 755 python

I know this is a very long thread already, but if you still can't solve the following issue after reading all the potential solutions posted here by all the community members, you can try the solution that solved my problem.

{
  "errorMessage": "Unable to import module 'xxx': No module named 'yyy'",
  "errorType": "Runtime.ImportModuleError",
  "stackTrace": []
}

To be clear, I'm talking about the zip file for the AWS Lambda Layer (NOT the deployment package) for the Python runtime. In my case, all the dependencies are placed under a folder named python according to the doc.

AWS Lambda Include library dependencies in a layer

Note that using a folder named python is better than the other folder structure since it does not depend on the version of Python.

Then you should try doing an ls in Lambda using the following code snippet:

import os

def lambda_handler(event, context):
    print(os.listdir('/opt'))
    print(os.listdir('/opt/python'))

Here is the expected output:

['python']
['OpenSSL', '__pycache__', ... 'urllib3', 'urllib3-1.24.2.dist-info']

In my case, before the issue was solved, the output was

{
  "errorMessage": "[Errno 13] Permission denied: '/opt/python'",
  "errorType": "PermissionError",
  "stackTrace": [
    "  File \"/var/task/lambda_function.py\", line 16, in lambda_handler\n    print(os.listdir('/opt/python'))\n"
  ]
}

Therefore, it's clearly a permission issue. After doing a chmod 755 python, zip -r9 lambda-layer python, and uploading lambda-layer.zip to Lambda, the issue is solved.

jellycsc
  • 10,904
  • 2
  • 15
  • 32
2

Not sure if it was mentioned above, but .zip file name and the contents of the zip should match. Ex: file: lambda.zip and the content: lambda.py

MederD
  • 65
  • 7
1

I ran into the same issue, this was an exercise as part of a tutorial on lynda.com if I'm not wrong. The mistake I made was not selecting the runtime as Python 3.6 which is an option in the lamda function console.

Nadeem
  • 17
  • 9
1

Sharing my solution for the same issue, just in case it helps anyone.

Issue: I got error: "[ERROR] Runtime.ImportModuleError: Unable to import module 'lambda_function': No module named 'StringIO'" while executing aws-big-data-blog code[1] provided in AWS article[2].

Solution: Changed Runtime from Python 3.7 to Python 2.7

[1] — https://github.com/bsnively/aws-big-data-blog/blob/master/aws-blog-vpcflowlogs-athena-quicksight/CloudwatchLogsToFirehose/lambdacode.py [2] — https://aws.amazon.com/blogs/big-data/analyzing-vpc-flow-logs-with-amazon-kinesis-firehose-amazon-athena-and-amazon-quicksight/

user72789
  • 11
  • 2
1

You can configure your Lambda function to pull in additional code and content in the form of layers. A layer is a ZIP archive that contains libraries, a custom runtime, or other dependencies. With layers, you can use libraries in your function without needing to include them in your deployment package. Layers let you keep your deployment package small, which makes development easier.

References:-

  1. https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html
  2. https://towardsdatascience.com/introduction-to-amazon-lambda-layers-and-boto3-using-python3-39bd390add17
Rahul Satal
  • 2,107
  • 3
  • 32
  • 53
1

Adding this answer for anyone else coming to this question with the same issue and none of the other solutions are working for them. The same error will be observed if you've uploaded code to the lambda, and try to test it without clicking Deploy; you must deploy the lambda before being able to run the test. enter image description here

JMercer
  • 352
  • 2
  • 9
1

I understand that I'm replying to an old thread, but in case someone else runs into this issue:

I had this same problem today deploying a Python Lambda function using CloudFormation from my M1 Mac. The filename and handler seemed correct, but the Lambda framework was still unable to find my module.

In the end it turns out that I was configuring the function to use the x86_64 architecture. Changing the CloudFormation template to use the arm64 architecture fixed the problem.

0

You need to zip all the requirements, use this script

#!/usr/bin/env bash
rm package.zip
mkdir package
pip install -r requirements.txt --target package
cat $1 > package/lambda_function.py
cd package
zip -r9 "../package.zip" .
cd ..
rm -rf package

use with:

package.sh <python_file>
Uri Goren
  • 13,386
  • 6
  • 58
  • 110
0

My problem was that the .py file and dependencies were not in the zip's "root" directory. e.g the path of libraries and lambda function .py must be:

<lambda_function_name>.py
<name of library>/foo/bar/

not

/foo/bar/<name of library>/foo2/bar2

For example:

drwxr-xr-x  3.0 unx        0 bx stor 20-Apr-17 19:43 boto3/ec2/__pycache__/
-rw-r--r--  3.0 unx      192 bx defX 20-Apr-17 19:43 boto3/ec2/__pycache__/__init__.cpython-37.pyc
-rw-r--r--  3.0 unx      758 bx defX 20-Apr-17 19:43 boto3/ec2/__pycache__/deletetags.cpython-37.pyc
-rw-r--r--  3.0 unx      965 bx defX 20-Apr-17 19:43 boto3/ec2/__pycache__/createtags.cpython-37.pyc
-rw-r--r--  3.0 unx     7781 tx defN 20-Apr-17 20:33 download-cs-sensors-to-s3.py
lobi
  • 344
  • 1
  • 4
  • 16
0

Please add below one after Import requests

import boto3

What I can see that is missing in your code.

Mrinal
  • 125
  • 5
0

Your package directories in your zip must be world readable too.

To identify if this is your problem (Linux) use:

find $ZIP_SOURCE -type d -not -perm /001 -printf %M\ "%p\n"

To fix use:

find $ZIP_SOURCE  -type d -not -perm /001 -exec chmod o+x {} \;

File readable is also a requirement. To identify if this is your problem use:

find $ZIP_SOURCE -type f -not -perm /004 -printf %M\ "%p\n"

To fix use:

find $ZIP_SOURCE  -type f -not -perm /004 -exec chmod o+r {} \;

If you had this problem and you are working in Linux, check that umask is appropriately set when creating or checking out of git your python packages e.g. put this in you packaging script or .bashrc:

umask 0002 
hi2meuk
  • 1,080
  • 11
  • 9
0

change python file name to lambda_function.py, for example in my case the filename was app.py the error gone once i change filename to lambda_function.py

zaheer
  • 143
  • 10
0

Make sure your lambda function name and handler name matches. For eg: if your lambda function name is 'index.py' and you have given handler name as 'lambda_function.lambda_handler' then you will get an error as 'Unable to import module 'lambda_function': No module named 'lambda_function'.

Resolution: you have to update the lambda_handler name from 'lambda_function.lambda_handler' to 'index.lambda_handler'

0

I am working on an AWS training course which goes through Lambda functions. It seems very basic, but you have to choose Deploy before test events will work - especially if you have uploaded code that did not contain the lambda_function.lambda_handler method - this was my mistake. This was not clear to me through my training, and thus lost 30+ minutes on this silly error.

kirrer
  • 13
  • 4
0

This is because maybe your code contains some packages(eg. request module of python) that are unknown to the lambda function. To solve this, AWS introduced the layers concept inside Lambda functions, there you can upload as many as libraries, and then you can connect the layer with the lambda functions.

sarvesh_r
  • 340
  • 1
  • 4
0

One thing that took me some research to realize was that I had python3.10 locally and thus in the folder structure, and lambda only accepts up to python3.9. In my case, I could just change the name of the folder from python3.10 to python 3.9 (python/lib/python3.9/site-packages), but you should just make sure you're using a version of python that is allowed by lambda.

SomeDE
  • 1
0

simple soluton

  1. create a zip of content for example I have a lambda function named as

    testfunction then the .zip will be zip -r testfunction.zip lambda_function.py other_conent.py

  2. deploy the changes after every change