In the below hierachy, is there a convenient and universal way to reference to the top_package using a generic term in all .py file below? I would like to have a consistent way to import other modules, so that even when the "top_package" changes name nothing breaks.
I am not in favour of using the relative import like "..level_one_a" as relative path will be different to each python file below. I am looking for a way that:
A decoupling reference to "top_package" in any .py file inside the package, so whatever name "top_package" changes to, nothing breaks.
top_package/ __init__.py level_one_a/ __init__.py my_lib.py level_two/ __init__.py hello_world.py level_one_b/ __init__.py my_lib.py main.py
Hence, if you want to get the top package name, you just need to get the first component of the path and import it using __import__ . Despite the variable name used to access the package is still called top_package , you can rename the package and if will still work.
You need to use the import keyword along with the desired module name. When interpreter comes across an import statement, it imports the module to your current program. You can use the functions inside a module by using a dot(.) operator along with the module name.
This should do the job:
top_package = __import__(__name__.split('.')[0])
The trick here is that for every module the __name__
variable contains the full path to the module separated by dots such as, for example, top_package.level_one_a.my_lib
. Hence, if you want to get the top package name, you just need to get the first component of the path and import it using __import__
.
Despite the variable name used to access the package is still called top_package
, you can rename the package and if will still work.
Put your package and the main
script into an outer container directory, like this:
container/ main.py top_package/ __init__.py level_one_a/ __init__.py my_lib.py level_two/ __init__.py hello_world.py level_one_b/ __init__.py my_lib.py
When main.py
is run, its parent directory (container
) will be automatically added to the start of sys.path
. And since top_package
is now in the same directory, it can be imported from anywhere within the package tree.
So hello_world.py
could import level_one_b/my_lib.py
like this:
from top_package.level_one_b import my_lib
No matter what the name of the container directory is, or where it is located, the imports will always work with this arrangement.
But note that, in your original example, top_package
it could easily function as the container directory itself. All you would have to do is remove top_package/__init__.py
, and you would be left with efectively the same arrangement.
The previous import statement would then change to:
from level_one_b import my_lib
and you would be free to rename top_package
however you wished.
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