8

I'm trying to use the serverless framework to create and deploy an AWS Lambda function. I created a folder named vendored in the root of the project and installed (using pip install) the function dependencies. However, whenever I try to run it (using serverless function run) I got an error:

Serverless: Running isNewUser...
Serverless: WARNING: This variable is not defined: region
Serverless: -----------------
Serverless: Failed - This Error Was Returned:
Serverless: {"exception": ["Traceback (most recent call last):\n", " File \"/home/fernando/.nvm/versions/node/v5.10.1/bin/serverless-run-python-handler\", line 170, in \n handler = import_program_as_module(path)\n", " File \"/home/fernando/.nvm/versions/node/v5.10.1/bin/serverless-run-python-handler\", line 149, in import_program_as_module\n module = make_module_from_file('lambda_handler', handler_file)\n", " File \"/home/fernando/.nvm/versions/node/v5.10.1/bin/serverless-run-python-handler\", line 129, in make_module_from_file\n py_source_description\n", " File \"/home/fernando/workspace/os-cac/isNewUser/handler.py\", line 11, in \n from vtex.order import Order\n", "ImportError: No module named vtex.order\n"], "success": false} Serverless: Exception message from Python
Serverless: Traceback (most recent call last): , File "/home/fernando/.nvm/versions/node/v5.10.1/bin/serverless-run-python-handler", line 170, in handler = import_program_as_module(path) , File "/home/fernando/.nvm/versions/node/v5.10.1/bin/serverless-run-python-handler", line 149, in import_program_as_module module = make_module_from_file('lambda_handler', handler_file) , File "/home/fernando/.nvm/versions/node/v5.10.1/bin/serverless-run-python-handler", line 129, in make_module_from_file py_source_description , File "/home/fernando/workspace/os-cac/isNewUser/handler.py", line 11, in from vtex.order import Order ,ImportError: No module named vtex.order `

vtex.order is a module imported in handler.py

The structure of my project is something like:

/root/
     |
     |--_meta/
     |--vendored/
                |--dependencies...
     |--function-name/
                     |--handler.py
                     |--event.json
                     |--s-function.json
     |--requirements.txt
     |--admin.env
     |--package.json
     |--s-project.json
     |--s-resources-cf.json
     |--s-project.json

Is there anything I'm doing wrong? Should I somehow configure my function to include the dependencies from vendored?

Cœur
  • 37,241
  • 25
  • 195
  • 267

3 Answers3

9

Here are a few steps that should make it work:

  1. Make sure that the handler entry in s-function.json has the function-name in its path: "handler": "function-name/handler.handler",
  2. in handler.py add the following:

    import os
    import sys
    
    here = os.path.dirname(os.path.realpath(__file__))
    sys.path.append(os.path.join(here, "../vendored"))
    
    from vtex.order import Order
    

That's it. Let me know if it worked.

Benny Bauer
  • 1,035
  • 1
  • 6
  • 19
  • 1
    Be aware that the libraries you vendor into the serverless package may not work in the AWS Lambda environment. This is usually only true for non-pure-Python libraries like cryptography, cffi and others. If you run into that, you can either pick up libraries from a resource like https://github.com/Miserlou/lambda-packages, or you can do the pip installs on a Linux machine that's close enough to Amazon Linux (I used centos 6-x64) and copy out of the site-packages directory that populates. If anyone needs more details, respond here and I'll add a question & answer. – Chris Johnson Oct 12 '16 at 17:23
  • Thanks, this is working for me. But, is there a PEP 8 compliant way to achieve the same results? – WhiteHotLoveTiger Mar 26 '18 at 18:17
4

I followed below steps to deploy with dependencies:

  • Created a directory for dependencies in project root mkdir .vendor

  • Add dependencies in requirements.txt file manually or use pip freeze > requirements.txt

  • Update serverless.yml file

package: include: - .vendor/**

  • Include .vendor directory to system path in handler.py file

import sys sys.path.insert(0, './.vendor')

  • Install dependencies pip install -r requirements.txt -t .vendor

Now serverless deploy will upload function with dependencies.

Rajesh Hegde
  • 2,702
  • 1
  • 18
  • 23
4

I'd recommend using the serverless-python-requirements plugin to include packages installed via pip

maafk
  • 6,176
  • 5
  • 35
  • 58
  • Except that it blows up on hitting the setup.py of a project brought in via github. Not fun. See https://github.com/serverless/serverless/issues/6495# – Samantha Atkins Aug 03 '19 at 00:37