I'm trying to dynamically import a Python module using importlib
.
My project is an Azure function app and has the following file structure:
Shared_Code/
├── __init__.py
├── model.py
└── rule_engine.py
In the file rule_engine.py
I'm trying to import model.py
:
logging.info(__name__)
importlib.import_module(
'Shared_Code.model', package=None
)
The above code prints
__app__.Shared_Code.rule_engine.py
and imports the module correctly on Linux and Azure Cloud.
However, when executing the exact same code on Windows I get an error that the module Shared_Code
could not be found.
I've then used the following
importlib.import_module(
'__app__.Shared_Code.model', package=None
)
which works on both, but breaks when running it on Azure Cloud.
Is there a generic solution for this without having to perform manual checks and if-clauses depending on the OS?
You can try to import model
using a relative path:
importlib.import_module('.model', package='Shared_Code')
Edit: After some research, I'm concluding that this is an Azure issue, not a Python one.
There isn't a single coincidence of the string __app__
in the full CPython code.
There is, however, this azure-functions-python-worker PR where the __app__
top-level module is implemented for absolute imports.
I guess this is a bug in azure-functions-python-worker, or whatever Azure platform you're working on, where they have different behavior between Linux and Azure Cloud VS Windows.
The only things I can think you can do are:
__app__
inside a try/except ModuleNotFoundError
, and if it fails import it again with __app__
:try:
importlib.import_module(
'Shared_Code.model', package=None
)
except ModuleNotFoundError:
# In Windows, __app__ is mandatory
importlib.import_module(
'__app__.Shared_Code.model', package=None
)
I know this last one is exactly what you're asking for not to do, but if it's a platform problem (and I'm pretty sure it is) there is nothing more you can do except to deal with it.