Aaron
Aaron

Reputation: 2305

AWS SAM Local and docker-lambda: keep getting Unable to import module 'lambda_function': No module named 'lambda_function'

Edit 2: The root cause was I had several DOCKER environment variables set which were causing my function invocations to re-route to a remote Docker host and not hit SAM Local. Once I unset those, the functions started running.

Edit: I cloned docker-lambda and tried running one of their examples and get the same error.

docker run --rm -v "$PWD":/var/task lambci/lambda:python3.6
START RequestId: 73a433fc-1d8a-4cdb-a66d-61bd667e13ba Version: $LATEST
Unable to import module 'lambda_function': No module named 'lambda_function'
END RequestId: 73a433fc-1d8a-4cdb-a66d-61bd667e13ba
REPORT RequestId: 73a433fc-1d8a-4cdb-a66d-61bd667e13ba Duration: 1 ms Billed Duration: 100 ms Memory Size: 1536 MB Max Memory Used: 15 MB

{"errorMessage": "Unable to import module 'lambda_function'"}

I'm trying to set up SAM Local with a Python lambda function and keep getting frustrated by the module import error in the title.

My template.yaml looks like this:

AWSTemplateFormatVersion : '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
  ProposalsTable:
    Type: "AWS::Serverless::SimpleTable"
  AddProposal:
    Type: "AWS::Serverless::Function"
    Properties:
      Handler: lambda_function.lambda_handler
      Runtime: python3.6
      Policies: AmazonDynamoDBFullAccess
      Environment:
        Variables:
          TABLE_NAME: !Ref ProposalsTable
      Events:
        Vote:
          Type: Api
          Properties:
            Path: /proposals
            Method: get

I have a lambda_function.py in the same folder as the template.yaml.

I run: sam local start-api and it starts up fine:

Mounting lambda_function.lambda_handler (python3.6) at http://127.0.0.1:3000/proposals [GET]

Then I do:

curl http://127.0.0.1:3000/proposals

Then on the "server" it shows:

Unable to import module 'lambda_function': No module named 'lambda_function'
Function returned an invalid response (must include one of: body, headers or statusCode in the response object): %!s(<nil>)

I've tried all different ways of naming the file (e.g. putting it inside a folder with an init.py)

I googled and read a dozen or more threads but most people are talking about deploying to the real AWS Lambda; there's not a lot on SAM Local.

I wonder if it's something in my environment. The node.js sample function here fails with a timeout. https://github.com/awslabs/aws-sam-local/tree/develop/samples/hello-world/node

2018/01/04 15:20:41 Invoking index.handler (nodejs6.10)
2018/01/04 15:20:41 Mounting /Users/me/code/sam-local-prototype as /var/task:ro inside runtime container
2018/01/04 15:20:46 Function index.handler timed out after 3 seconds

Ideas?

Upvotes: 5

Views: 13445

Answers (2)

Nicholas Martinez
Nicholas Martinez

Reputation: 586

Regarding the Unable to import module 'lambda_function': No module named 'lambda_function' error:

In the repo link you provided within the template.yaml the Handler key reads: Handler: index.handler. This corresponds to the index.js file that contains the function named handler written as exports.handler = () => {}

If you are re-writing this in Python, your template.yaml handler key will need to read Handler: {file_name}.{function_name}. If the file carrying your lambda function is called lambda.py and the function within it is def lambda_handler you will need to write your handler key in the .yaml as Handler:lambda.lambda_function. I remember having to modify the key beneath Resources but give make sure your file name and function name are accurate and try again.

I just copied the code out of the repo and ran it successfully. Do you have docker installed correctly? Or did you have sam local api started when you tried to run the test code from the repo? If it attempted to connect on the same port, you may get the timeout as well.

2018/01/16 13:39:14 Successfully parsed template.yaml
2018/01/16 13:39:14 Connected to Docker 1.35
2018/01/16 13:39:14 Runtime image missing, will pull....
2018/01/16 13:39:14 Fetching lambci/lambda:nodejs6.10 image for nodejs6.10 runtime...
nodejs6.10: Pulling from lambci/lambda
f338a32fa56c: Already exists 
4926b20b634f: Already exists 
8040e979acbc: Pull complete 
160b6838355f: Pull complete 
Digest: sha256:e34f92bc0df0cf4a8ba560c6c7bf201183d5f6773ddf44440a97295486906744
Status: Downloaded newer image for lambci/lambda:nodejs6.10
2018/01/16 13:39:28 Invoking index.handler (nodejs6.10)
2018/01/16 13:39:28 Mounting /Users/me/sam_local_test as /var/task:ro inside runtime container
START RequestId: 8970d865-2d59-1d54-0825-d56f1fd035f7 Version: $LATEST
2018-01-16T20:39:32.315Z    8970d865-2d59-1d54-0825-d56f1fd035f7    LOG: Name is Bob
END RequestId: 8970d865-2d59-1d54-0825-d56f1fd035f7
REPORT RequestId: 8970d865-2d59-1d54-0825-d56f1fd035f7  Duration: 22.02 ms  Billed Duration: 0 ms   Memory Size: 0 MB   Max Memory Used: 28 MB  

"Hello Bob"

Upvotes: 2

gotjava2012
gotjava2012

Reputation: 751

Aaron,

Check out this video : https://www.youtube.com/watch?v=xaCbIFH_d9k

You have listed:

  • Handler: lambda_function.lambda_handler
  • Is your file called lambda_function?
  • Where is this file located? This matters because the element "CodeUri:" is where you specify the path to the file and I don't see that element in your explanation. Or if you zip up the project you can specify the file name here. For example I zip my project up then within the template.yml I specify my CodeUri to point to the zip as such:

    CodeUri: lambda.zip

.

I hope this helps.

Upvotes: 2

Related Questions