Search code examples
pythonpython-3.xazure-functions

Deploying a python Function App where the source is in a subdirectory


I've got a mono-repo with a python project that I'm deploying to Azure. There's an API being deployed as a container and I'm trying to add a function app.

My python code is structured in a few folders underneath a /backend folder, like

./backend
./backend/domain/ - contains domain logic .py files
./backend/entrypoints/api - contains Flask app files
./backend/entrypoints/my-func - contains my new function app
./backend/... - various other folder hierarchies that are imported.

I have a venv set up and a requirements.txt in the root of the project.

The function app imports domain and other modules. All folders have an __init__.py to mark them as modules.

I'm struggling to run the project. If I func start in the ./backend/entrypoints/my-func directory I get a ModuleNotFoundError:

Exception: ModuleNotFoundError: No module named 'dotenv'. Cannot find module. Please check the requirements.txt file for the missing module. 

My flask app can load dotenv just fine and it's in the requirements.txt and installed.

$ pip install -r requirements.txt
... 
Requirement already satisfied: python-dotenv~=1.0.1 in /home/greg/.pyenv/versions/3.12.2/envs/fish12-2/lib/python3.12/site-packages (from -r requirements.txt (line 27)) (1.0.1)
...

Is this possible?


Solution

  • Set PYTHONPATH to ensure Python locates the directories that contain the modules and also allows you to control which directories can be included in the module search path.

    Eg: set PYTHONPATH=../../../

    I have followed below steps to use the modules in the sub-directory of the project.

    Project Structure:

    Monorepo
    |
    |---requirements.txt
    \---env
    |
    +---backend
    |   \---entrypoint
    |       +---api
    |       |       app.py
    |       |
    |       \---my-func
    |           |   .gitignore
    |           |   function_app.py
    |           |   host.json
    |           |   local.settings.json
    |           |
    |           +---.vscode
    |           |       extensions.json
    |           |
    |           \---__pycache__
    |                   function_app.cpython-311.pyc
    

    requirements.txt

    azure-functions
    flask
    python-dotenv
    

    Create and activate virtual environment in the root directory:

    py -m venv env
    .\env\Scripts\activate
    

    Install the packages in the virtual environment:

    pip install -r requirements.txt
    

    enter image description here

    Navigate to the function folder and run the command:

    (env) C:\Users\uname\monorepo\backend\entrypoint\my-func>set PYTHONPATH=../../../
    

    Able to run the function with dotenv module:

    code snippet:

    import azure.functions as func
    import datetime
    import json
    import logging
    from dotenv import load_dotenv
    
    app = func.FunctionApp()
    
    @app.route(route="http_trigger", auth_level=func.AuthLevel.ANONYMOUS)
    def http_trigger(req: func.HttpRequest) -> func.HttpResponse:
        logging.info('Python HTTP trigger function processed a request.')
    

    Response:

    (env) C:\Users\uname\monorepo\backend\entrypoint\my-func>func start
    Found Python version 3.11.9 (py).
    
    Azure Functions Core Tools
    Core Tools Version:       4.0.5907 Commit hash: N/A +807e89766a92b1XXX8777ab209 (64-bit)
    Function Runtime Version: 4.834.3.22875
    
    [2024-08-30T07:39:25.263Z] Worker process started and initialized.
    
    Functions:
    
            http_trigger:  http://localhost:7071/api/http_trigger
    
    For detailed output, run func with --verbose flag.
    [2024-08-30T07:39:30.124Z] Executing 'Functions.http_trigger' (Reason='This function was programmatically called via the host APIs.', Id=bc1ffc1c-089b-47f4-XX3108)
    [2024-08-30T07:39:30.228Z] Python HTTP trigger function processed a request.
    [2024-08-30T07:39:30.362Z] Executed 'Functions.http_trigger' (Succeeded, Id=bc1ffc1c-089b-47f4-992XXX08, Duration=252ms)
    [2024-08-30T07:39:30.384Z] Host lock lease acquired by instance ID '000000000000000000000000F72731CC'.
    

    enter image description here