<p>首先,你可能真的不想这么做,如果你解释了你为什么这么想,我们可能会给你一个更好的方法。你知道吗</p>
<p>但在某些情况下,这可能是合理的。例如,我可以想象一个<code>PYTHONSTARTUP</code>文件为一个交互式会话预加载了一堆模块;作为一个交互式用户,您可以查看加载了什么并决定要做什么。你知道吗</p>
<hr/>
<p>如果您只需要其中的一小部分,那么最好明确地这样做:</p>
<pre><code>try:
from path1.path2.path3 import x
except ImportError:
pass
try:
from path1.path2.path4 import y
except ImportError:
pass
try:
from path1.path2.path3 import z
except ImportError:
pass
</code></pre>
<hr/>
<p>对于除交互式使用以外的任何其他用途,您实际上可能需要<code>x = None</code>而不是<code>pass</code>,除非您希望在代码中包装一堆<code>try:</code>/<code>except NameError:</code>测试。你知道吗</p>
<pre><code>try:
from path1.path2.path3 import x
except ImportError:
x = None
# etc.
</code></pre>
<hr/>
<p>如果你想让每一个都是1行而不是4行,你可以用<a href="https://docs.python.org/3/library/importlib.html#examples" rel="nofollow noreferrer">^{<cd6>}</a>来做,代价是重复你自己:</p>
<pre><code>from importlib.util import find_spec
if find_spec('path1.path2.path3.x'): from path1.path2.path3 import x
if find_spec('path1.path2.path4.y'): from path1.path2.path4 import y
if find_spec('path1.path2.path3.z'): from path1.path2.path3 import z
</code></pre>
<hr/>
<p>如果您需要做一大堆这样的工作,那么最好还是编写一个包装函数,再次使用<code>importlib</code>:</p>
<pre><code>import importlib
def try_import(mod):
try:
return importlib.import_module(mod)
except ImportError:
return None
x = try_import('path1.path2.path3.x')
y = try_import('path1.path2.path4.y')
z = try_import('path1.path2.path3.z')
</code></pre>
<hr/>
<p>如果您有一个动态生成的模块列表,那么您需要弄清楚如何存储结果,因为您可能还需要动态地访问它们。一个明显的可能性是把它们放进一个字典里:</p>
<pre><code>import importlib
def try_import(mod):
try:
return importlib.import_module(mod)
except ImportError:
return None
names = ['path1.path2.path3.x', 'path1.path2.path4.y', 'path1.path2.path3.z']
mods = [try_import(name) for name in names]
mods = {name.split('.')[-1]: mod for name, mod in zip(names, mods)}
</code></pre>
<p>…或者,如果要跳过缺少的模块而不是使用<code>None</code>:</p>
<pre><code>mods = {name.split('.')[-1]: mod for name, mod in zip(names, mods) if mod}
</code></pre>
<p>…或者,如果这是准静态的,比如交互示例,可能是一个名称空间,所以您可以访问<code>mods.x</code>:</p>
<pre><code>import types
mods = types.SimpleNamespace(**mods)
</code></pre>
<p>…或者,如果您想将它们转储到全局变量中,这样您就可以作为<code>x</code>访问它们,这很简单:</p>
<pre><code>globals().update(mods)
</code></pre>
<hr/>
<p>如果确实需要构建语句列表而不是模块列表,请使用<a href="https://docs.python.org/3/library/functions.html#exec" rel="nofollow noreferrer">^{<cd11>}</a>:</p>
<pre><code>statements = ['from path1.path2.path3 import x', 'from path1.path2.path4 import y']
for statement in statements:
try:
exec(statement)
except ImportError:
pass
</code></pre>
<p>但是请注意,除了必须以这种方式比使用其他动态选项更频繁地重复自己之外,如果不解析<code>exec</code>块中的语句,您也不能做任何明智的事情,比如<code>x = None</code>,因为否则您就没有名称<code>x</code>。在本例中,这并不是很难做到的,但是它增加了更多的复杂性和代码的味道</p>