Во-первых, вы, вероятно, на самом деле не хотите этого делать - и если бы вы объяснили, почему вы так думаете, мы могли бы показать вам лучший способ сделать это.
Но в некоторых случаяхэто может быть разумноНапример, я мог бы представить файл 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.
Если вы хотите сделать каждый из них одним, а не четырьмя, вы можете сделать это, используя 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
Но обратите внимание, что помимо необходимости повторять себя намного больше таким образом, чем с другими динамическими опциями, вы также не можете делать ничего разумного, например x = None
, не анализируя оператор внутриexec
блок, потому что иначе у вас нет названия x
.Это не совсем сложно в этом случае, но это добавляет еще больше сложности и запаха кода ...