How do I move my Python function handlers into a subdirectory?

I thought this would be as simple as:

functions:
  SignUp:
    handler: handler/unauthorized_api.sign_up
    events:
      - httpApi:
          path: /sign_up
          method: post

with a handler/unauthorized_api.py file but I get this error:

sls logs -f SignUp
START
[ERROR] Runtime.ImportModuleError: Unable to import module 'handler.unauthorized_api': No module named 'handler'
Traceback (most recent call last):
END Duration: 1.78 ms (init: 124.40 ms) Memory Used: 39 MB

Long story short, here’s the right way to do it. Assume a directory structure like this:

handler
|-- __init__.py
+-- unauthorized_api..py
constants.py
serverless.yml

Having an __init__.py seems important here.

serverless.yml:

functions:
  SignUp:
    handler: handler.unauthorized_api.sign_up

unauthorized_api.py:

import constants

def sign_up(event, context):
  pass

I found the right approach in Python relative imports in AWS Lambda fail with `attempted relative import with no known parent package` · GitHub.

This error occurs when you try to import a module using a relative import, but Python cannot find the module’s parent package.

To fix this error attempted relative import with no known parent package, you need to make sure that the module being imported is part of a package, and that the package is on the Python path. You can do this by adding an empty init.py file to the package’s directory, and by making sure that the directory containing the package is on the Python path.

Alternatively, you can run the module using the -m flag with the Python interpreter, like this:

python -m mypackage.mymodule

This tells Python to run mymodule.py as a module, which will allow it to correctly resolve relative imports.

The main advantage of using relative imports is that they make it easier to move packages and modules around within a project, without having to update all the import statements. They also make it easier to reuse code across multiple projects, because the import paths can be modified to match the package hierarchy of each project.