Assuming the following sample project structure:
src/
animals/
__init__.py
cat.py
dog.py
zoo.py
I want to achieve the following two behaviors:
animals
package dynamically imports all of its modules. This is required for the code that uses this package (say fromzoo.py
). This can be done in a fashion described here. For example like this:# animals/__init__.py from pathlib import Path from importlib import import_module for f in Path(__file__).parent.glob("*.py"): if f.name == '__init__.py': continue import_module(f".{f.parts[-1][-3]}", __name__)
Each of the modules in
animals
should be separately runnable from CLI, for example like this:python3 -m src.animals.dog # Runs some dog specific stuff, e.g. tests
So far, I fail to combine these two requirements together. The problem arises from the fact that this command line first loads the animals
package which in turn imports dog
among the other sub-modules. But later dog
is being imported for a second time as __main__
. This leads to a duplicate import (dog
code being processed twice). I also get the following warning:
RuntimeWarning: 'src.animals.dog' found in sys.modules after import of package 'src.animals', but prior to execution of 'src.animals.dog'; this may result in unpredictable behavior.
One possible way I thought of solving it is somehow detecting which module is being invoked from the command line and skip its loading in __init__
. But how do I find this info? Tried parsing sys.modules['__main__']
but it seems mostly uninitialized.
Note: In the real project I have one more hierarchy level under animals
, and I load all the sub packages, but that shouldn't matter for the sake of this example.