serverless-python-requirements icon indicating copy to clipboard operation
serverless-python-requirements copied to clipboard

invoke local issue when "module" is defined

Open lepirlouit opened this issue 4 years ago • 9 comments

I'm unable to invoke my function locally when I use the module functionality:

severless.yml

package:
  individually: true

functions:
  my_function:
     handler: my_function.lambda_handler
     module: src/my_function_folder

invoke local : serverless invoke local -f my_function

got error : ModuleNotFoundError: No module named 'my_function'

lepirlouit avatar Jun 03 '20 06:06 lepirlouit

warkaround : this can be fixed in the serverless/lib/plugins/aws/invokeLocal/invoke.py file by adding

line 72: import os
line 73: sys.path.append(os.path.join('.', "src", "my_function_folder"))```

lepirlouit avatar Jun 03 '20 08:06 lepirlouit

Having the same issue, have you been able to find any other solutions?

jorgeandresvasquez avatar Jun 12 '20 01:06 jorgeandresvasquez

temporary try my workaround https://github.com/UnitedIncome/serverless-python-requirements/issues/520#issuecomment-638047127

lepirlouit avatar Jun 12 '20 06:06 lepirlouit

I'm also affected by this issue. Removing the module: parameter works but then the plugin can't see my requirements.txt file as it's nested, so there's always going to be a discrepancy between the handler path determined locally and remotely. Thanks for the temporary workaround @lepirlouit!

sndrsnk avatar Jun 22 '20 17:06 sndrsnk

I've found another temporary workaround using environment variables in serverless.yml:

functions:
  LambdaTestFunction:
    handler: ${env:HANDLER_PATH_PREFIX, ""}handler.handler
    module: src/test_lambda
  ...
  ...
package:
  individually: true

When I invoke locally, I use the following command:

HANDLER_PATH_PREFIX=src/test_lambda/ LOCAL=true ./node_modules/serverless/bin/serverless.js invoke local -f LambdaTest -p ./tests/resources/base_event.yml

I've tested local and remote invocations and I can confirm it's working as expected.

sndrsnk avatar Jun 23 '20 08:06 sndrsnk

Thanks @sndrsnk. This works. But I then have a problem with importing modules from alongside handler.py. I find that they either work in local or lambda, depending on my syntax. As a workaround, I have to do this:

if "IS_LOCAL" in os.environ:
    from test_lambda import my_other_module
else:
    import my_other_module

Note that IS_LOCAL is automatically set by serverless framework - you don't need to make it yourself.

Python isn't my fave language, so I'm probably doing something dumb. Or is this required? (I tried doing from . import my_other_module but it only worked locally and not in lambda.)

jamesoflol avatar Jun 25 '20 07:06 jamesoflol

@jamesoflol You're welcome, and thanks for raising the issue regarding relative imports. I tested it on my end and can confirm that I'm experiencing the same issue. I did some research and found a really nice workaround here.

Simply add the following block of code to your package's __init__.py file:

import os
import sys

sys.path.append(os.path.dirname(os.path.realpath(__file__)))
└── test_lambda
    ├── __init__.py <=== add the code to this one
    ├── handler.py
    ├── requirements.txt
    └── some_module
        ├── __init__.py
        └── example.py

Hope it helps!

sndrsnk avatar Jun 25 '20 09:06 sndrsnk

@sndrsnk Thanks for sharing!

Here' another workaround by setting the PYTHONPATH environment variable to the module field in serverless.yml when you invoke local. In this case, you don't need to add local-only logic to the serverless.yml, and the good thing is the relative imports would still work as-is.

PYTHONPATH=YOUR_MODULE serverless invoke local --function YOUR_FUNCTION

thomaschen avatar Oct 10 '20 20:10 thomaschen

The provided workaround works great for functions without an import of an external package. However it does not include the packages installed in venv. Is there any solution to this?

tw1t611 avatar Jun 30 '22 13:06 tw1t611