I have the following conundrum. I'm trying to expose some modules from a subpackage of a package at the parent package level.
The folder structure is the essentially like this:
script.py
package/
__init__.py
module1.py
subpackage/
__init__.py
submodule1.py
submodule2.py
In the script.py
file I currently have to write
from package.subpackage.submodule1 import foo
if I want to import something from the submodule1.py
file, but I would like to be able to expose the files submodule1.py
and submodule2.py
at package level, so that all my imports can look like
from package.module1 import bar
from package.submodule1 import foo
from package.submodule2 import goo
Note that I don't want to expose bar
, foo
and goo
at package
level, i.e. not
from package import bar
from package import foo
because the separation between modules is still important in my case.
Is this even possible? Is there a trick in the __init__.py
file to do so?
Thanks!
Yes It's possible.
Let's see what happens step by step;
from package.submodule1 import foo
, sys.modules
is checked if it has package
. package/__init__.py
is run and loaded sys.modules
is checked for package.submodule1
package/submodule1.py
is checked for existence.We can make step 3 pass by making an entry in sys.modules
for package.submodule1
in step 2.
package/__init__.py
import sys
from .subpackage import submodule1
from .subpackage import submodule2
for module in (submodule1, submodule2):
full_name = '{}.{}'.format(__package__, module.__name__.rsplit('.')[-1])
sys.modules[full_name] = sys.modules[module.__name__]
For your purpose, python modules are just namespaces. That is, everything in the globals of a module can be imported and used as module.thingy
. You may have noticed that in many modules, you also find some builtins. For example, logging.os
is just the regular os
module.
So, in your package (package/__init__.py
) import whatever you wish, and bind it to the name you want to expose it as.
# package/__init__.py
# import package.module1 as module1 # one *can* do this, but its at best without benefit (see comments)
import package.subpackage.submodule1 as submodule1
import package.subpackage.submodule2 as submodule2
This allows to do import package.submodule1
and import package.submodule1 as foo
.
Note that this simple way will not allow you to do from package.submodule1 import bar
. For this, you need an actual dummy module.
# package/submodule1/__init__.py
from package.subpackage.submodule1 import *
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With