Is there any alternative to prevent typing repeated long paths while importing modules in python.
Current code:
from a.b.c.d.e.f.g import g1
from a.b.c.d.e.f.g import g2
from a.b.c.d.e.f.g.h import h1
from a.b.c.d.e.f.g.i import i1
I tried following code:
ref_path = a.b.c.d.e.f.g
from ref_path import g1
from ref_path import g2
from ref_path.h import h1
from ref_path.i import i1
But unfortunately it did not work. I cannot do from a.b.c.d.e.f.g import *
since there might be too many modules within the ref_path
.
If I am able to do this, I could easily maintain different common ref_paths
used in different modules from one common location with minimal efforts.
So each module is imported only one time. To better understand import mechanics I would suggest to create toy example. So import really happens only once. You can adjust this toy example to check cases that are interesting to you.
This is the easiest way to import a Python module by adding the module path to the path variable. The path variable contains the directories Python interpreter looks in for finding modules that were imported in the source files. Syntax : sys.path.append("module_path")
The rules are quite simple: the same module is evaluated only once, in other words, the module-level scope is executed just once. If the module, once evaluated, is imported again, it's second evaluation is skipped and the resolved already exports are used.
PACKAGES. In the __init__.py file of a package __all__ is a list of strings with the names of public modules or other objects. Those features are available to wildcard imports. As with modules, __all__ customizes the * when wildcard-importing from the package.
There is no miracle cure for this problem.
There are, however, a few strategies you can use to make your imports a little bit nicer:
Import all names from a module at the same time
Instead of
from a.b.c.d.e.f.g import g1
from a.b.c.d.e.f.g import g2
use
from a.b.c.d.e.f.g import g1, g2
Use relative imports (if you're importing within your own package)
Assuming that this import is happening in a.b.c.d.e
, you can replace
from a.b.c.d.e.f.g.h import h1
with
from .f.g.h import h1
This also works if you're in a sibling (sub-)module. For example, if this import is taking place in a.b.c.d.e.x.y
, you can use
from ...f.g.h import h1
For more details about relative imports, see
Refactor your package (if it's your own code)
If your package has more than 4 levels of submodules (like a.b.c.d.e
), there's a pretty high chance that you should rethink your package structure. At that point you're really just shooting yourself in the foot. Perhaps c
could be a standalone package, outside of a
. Or perhaps e
doesn't really need to be inside d
and can be moved up a level or two. To quote the Zen of Python: Flat is better than nested.
importlib.import_module
Someone suggested this:
import importlib
ref_path = 'a.b.c.d.e.f.g'
g1 = importlib.import_module(ref_path).g1
h1 = importlib.import_module(ref_path).h.h1
This serves absolutely no purpose. Now you have to write importlib.import_module(ref_path)
instead of from a.b.c.d.e.f import
. It's not shorter. It's not more readable. It's nothing but a more verbose version of the next suggestion. (Read on...)
Assigning a.b.c.d.e.f
to a variable
The next suggestion was this:
import a.b.c.d.e.f.g as ref
g1 = ref.g1
h1 = ref.h.h1
This looks nice, but it doesn't always work. If the g
module doesn't automatically import the h
submodule, this code will throw an AttributeError. To demonstrate:
>>> import urllib as ref
>>> urlopen = ref.request.urlopen
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'urllib' has no attribute 'request'
>>>
>>> from urllib.request import urlopen # this works, though
>>>
If this is inside your own package, there's an additional disadvantage to this solution: Your IDE most likely won't understand your imports, and won't automatically update them for you if you ever refactor your package structure. In the long run, old-fashioned import
statements are more maintainable.
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