运行 个存储在列表中的 python 个导入语句
Run individual python import statements which are stored in a list
我有一个要导入的库列表,但其中一些可能不在文件系统中。
基本上,我想做这样的事情:
list_of_imports = ['from path1.path2.path3 import x', 'from path1.path2.path4 import y', 'from path1.path2.path3 import z', 'from path1.path2.path2 import a']
for statement in list_of_imports:
try:
execute statement
except:
ignore error and import the next statement
我之所以要这样做,是因为列表中的一些库可能不在文件系统中,我不希望一次失败导致整个文件抛出导入错误。
我该怎么做?
你可以这样试试:
list_of_imports = ['from path1.path2.path3 import x', 'from path1.path2.path4 import y', 'from path1.path2.path3 import z', 'from path1.path2.path2 import a']
for statement in list_of_imports:
try:
exec(statement)
except ImportError as e:
continue
解释:
使用 exec()
遍历列表中的每个元素,您可以执行那些 import
语句。因此,如果没有错误,它将导入该模块
首先,您可能实际上并不想这样做 — 如果您解释了您认为自己这样做的原因,我们可能会向您展示更好的方法。
但在某些情况下这可能是合理的。例如,我可以想象一个 PYTHONSTARTUP
文件为交互式会话预加载一堆模块;作为交互式用户,您可以查看加载的内容并决定要做什么。
如果您只需要其中的一小部分,最好明确地执行它们:
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
除了交互式使用之外,您可能实际上想要 x = None
而不是 pass
,除非您想包装一堆 try:
/except NameError:
测试你的所有代码。
try:
from path1.path2.path3 import x
except ImportError:
x = None
# etc.
如果你想让每一个都成为 1 行而不是 4 行,你可以使用 importlib
来做到这一点,代价是重复你自己:
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
如果你需要做一大堆这些,你最好写一个包装函数,再次使用 importlib
:
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')
如果您有一个动态生成的模块列表,您需要弄清楚您希望如何存储结果,因为您可能还需要动态地访问它们。一种明显的可能性是将它们粘贴到字典中:
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)}
… 或者,如果您想跳过丢失的模块而不是使用 None
:
mods = {name.split('.')[-1]: mod for name, mod in zip(names, mods) if mod}
… 或者,如果这是针对一些准静态的,比如交互式示例,可能是命名空间,那么您可以访问 mods.x
:
import types
mods = types.SimpleNamespace(**mods)
… 或者,如果你想将它们转储到全局变量中,那么你可以像 x
一样访问它们,这就很简单:
globals().update(mods)
如果您确实需要构建语句列表而不是模块列表,请使用 exec
:
statements = ['from path1.path2.path3 import x', 'from path1.path2.path4 import y']
for statement in statements:
try:
exec(statement)
except ImportError:
pass
但是请注意,除了必须以这种方式比使用其他动态选项更多地重复自己之外,如果不解析 [=29= 中的语句,您也不能做任何像 x = None
这样明智的事情] 块,因为否则你没有名字 x
。在这种情况下,这并不完全 hard,但它增加了更多的复杂性和代码味道……
我有一个要导入的库列表,但其中一些可能不在文件系统中。
基本上,我想做这样的事情:
list_of_imports = ['from path1.path2.path3 import x', 'from path1.path2.path4 import y', 'from path1.path2.path3 import z', 'from path1.path2.path2 import a']
for statement in list_of_imports:
try:
execute statement
except:
ignore error and import the next statement
我之所以要这样做,是因为列表中的一些库可能不在文件系统中,我不希望一次失败导致整个文件抛出导入错误。
我该怎么做?
你可以这样试试:
list_of_imports = ['from path1.path2.path3 import x', 'from path1.path2.path4 import y', 'from path1.path2.path3 import z', 'from path1.path2.path2 import a']
for statement in list_of_imports:
try:
exec(statement)
except ImportError as e:
continue
解释:
使用 exec()
遍历列表中的每个元素,您可以执行那些 import
语句。因此,如果没有错误,它将导入该模块
首先,您可能实际上并不想这样做 — 如果您解释了您认为自己这样做的原因,我们可能会向您展示更好的方法。
但在某些情况下这可能是合理的。例如,我可以想象一个 PYTHONSTARTUP
文件为交互式会话预加载一堆模块;作为交互式用户,您可以查看加载的内容并决定要做什么。
如果您只需要其中的一小部分,最好明确地执行它们:
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
除了交互式使用之外,您可能实际上想要 x = None
而不是 pass
,除非您想包装一堆 try:
/except NameError:
测试你的所有代码。
try:
from path1.path2.path3 import x
except ImportError:
x = None
# etc.
如果你想让每一个都成为 1 行而不是 4 行,你可以使用 importlib
来做到这一点,代价是重复你自己:
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
如果你需要做一大堆这些,你最好写一个包装函数,再次使用 importlib
:
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')
如果您有一个动态生成的模块列表,您需要弄清楚您希望如何存储结果,因为您可能还需要动态地访问它们。一种明显的可能性是将它们粘贴到字典中:
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)}
… 或者,如果您想跳过丢失的模块而不是使用 None
:
mods = {name.split('.')[-1]: mod for name, mod in zip(names, mods) if mod}
… 或者,如果这是针对一些准静态的,比如交互式示例,可能是命名空间,那么您可以访问 mods.x
:
import types
mods = types.SimpleNamespace(**mods)
… 或者,如果你想将它们转储到全局变量中,那么你可以像 x
一样访问它们,这就很简单:
globals().update(mods)
如果您确实需要构建语句列表而不是模块列表,请使用 exec
:
statements = ['from path1.path2.path3 import x', 'from path1.path2.path4 import y']
for statement in statements:
try:
exec(statement)
except ImportError:
pass
但是请注意,除了必须以这种方式比使用其他动态选项更多地重复自己之外,如果不解析 [=29= 中的语句,您也不能做任何像 x = None
这样明智的事情] 块,因为否则你没有名字 x
。在这种情况下,这并不完全 hard,但它增加了更多的复杂性和代码味道……