har*_*ant 14 python python-3.x
有没有其他选择可以防止在python中导入模块时键入重复的长路径。
当前代码:
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
Run Code Online (Sandbox Code Playgroud)
我尝试了以下代码:
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
Run Code Online (Sandbox Code Playgroud)
但是不幸的是它没有用。我不能这样做,a.b.c.d.e.f.g import *因为中可能有太多模块ref_path。
如果我能够做到这一点,我可以轻松地ref_paths从一个公共位置维护在不同模块中使用的不同公共资源。
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
Run Code Online (Sandbox Code Playgroud)
use
from a.b.c.d.e.f.g import g1, g2
Run Code Online (Sandbox Code Playgroud)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
Run Code Online (Sandbox Code Playgroud)
with
from .f.g.h import h1
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
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
>>>
Run Code Online (Sandbox Code Playgroud)
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.
您可以尝试importlib如下使用:
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
Run Code Online (Sandbox Code Playgroud)
编辑:另一种方法可以是将引用路径作为一个包导入,然后将子模块分配给局部变量,如下所示:
import a.b.c.d.e.f as ref
g1 = ref.g1
h1 = ref.h.h1
Run Code Online (Sandbox Code Playgroud)