Dave
Dave

Reputation: 19320

In Python Azure functions, how do I import a shared library in my function with just a single line?

I'm using Python 3.8 and creating functions for Azure. I have this directory structure ..

shared
    __init__.py
my_function
    __init.py
tests
    __init__.py
    functions
        __init__.py
        test_myfunction.py

In the shared/init.py file, I have some constants ...

import os
  
HEADERS = {"Content-Type": "text/plain"}

In my my_function/init.py file, I haven't figured out how to write a single line to include the shared file. If I do this

from ..shared import HEADERS

I get this error when running pytest ..

pytest tests/functions/test_myfunction.py
...
ERROR tests/functions/test_myfunction.py - ValueError: attempted relative import beyond top-level package

If I do this,

from shared import HEADERS

I get this error when starting my application (e.g. using "func start") ...

Exception: ModuleNotFoundError: No module named 'shared'

I have to resort to using try-except

try:
    from ..shared import HEADERS
except:
    from shared import HEADERS

but this just feels really messy and wrong. What's the proper way to write a single line to include what I need for both?

Edit: Here are the main contents of the pytest test file, tests/functions/test_myfunction.py ...

_import = __import__('myfunction')
...
req = func.HttpRequest(
        method='GET',
        body=None,
        url='/myfunction',
        params=params,
        headers=headers
    )
resp = _import.main(req) 

Upvotes: 2

Views: 2073

Answers (1)

suziki
suziki

Reputation: 14113

from ..shared import HEADERS should be the right way.

I am not sure what do you mean about pytest in your description.

Please have a look of the structure on my side, it works:

enter image description here

__init__.py in shared:

import os
  
HEADERS = {"Content-Type": "text/plain"}

test.py in shared:

import os
  
HEADERS = {"Content-Type": "text/plain"}

And this is __init__.py in HttpTrigger1(the function):

import logging

import azure.functions as func
import json
from ..shared import HEADERS

def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info(HEADERS)
    HEADERS
    return func.HttpResponse(
            json.dumps(HEADERS),
            status_code=200
    )

When I hit the endpoint, I can get the HEADERS:

enter image description here

If I want to get HEADERS in test.py, then I do from ..shared import test, then do test.HEADERS, also works.

This is the import behaviour doc:

https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-python#import-behavior

I am not sure, but It should have something differences between you and me.

Upvotes: 3

Related Questions