Я хочу динамически импортировать модуль в Python (3.7), при этом код модуля определяется в строке.
Ниже приведен рабочий пример, в котором используется модуль imp, который устарел в пользу importlib (начиная с версии 3.4):
import imp
def import_code(code, name):
# create blank module
module = imp.new_module(name)
# populate the module with code
exec(code, module.__dict__)
return module
code = """
def testFunc():
print('spam!')
"""
m = import_code(code, 'test')
m.testFunc()
В документации Python указано, что вместо importlib.util.module_from_spec() следует использовать imp.new_module(). Однако, похоже, нет способа создать пустой объект модуля с помощью модуля importlib, как я мог бы с imp.
Как я могу использовать importlib вместо imp для достижения того же результата?






Вы можете просто создать экземпляр types.Module:
import types
mod = types.ModuleType("mod")
Затем вы можете заполнить его exec так же, как и вы:
exec(code, mod.__dict__)
mod.testFunc() # will print 'spam!'
Итак, ваш код будет выглядеть так:
import types
def import_code(code, name):
# create blank module
module = types.ModuleType(name)
# populate the module with code
exec(code, module.__dict__)
return module
code = """
def testFunc():
print('spam!')
"""
m = import_code(code, 'test')
m.testFunc()
Как прокомментировал @Error - Syntactical Remorse, вы должны иметь в виду, что exec в основном выполняет любой код, содержащийся в строке, которую вы ему даете, поэтому вы должны использовать его с особой осторожностью.
По крайней мере, проверьте, что вам дали, но было бы хорошо использовать исключительно предопределенные строки.
@Error-SyntacticalRemorse Вы правы, я добавил примечание.
Согласно документации Python module_from_spec()
importlib.util.module_from_spec(spec)
...
This function is preferred over using types.ModuleType to create a new module as spec is used to set as many import-controlled attributes on the module as possible.
Вот что я придумал, чтобы загрузить модуль из исходного кода, расположенного в репозитории github. Это способ без записи файла на диск.
import requests
url = "https://github.com/udacity/deep-learning-v2-pytorch/raw/master/intro-to-pytorch/helper.py"
r = requests.get(url)
import importlib.util
spec = importlib.util.spec_from_loader('helper', loader=None, origin=url)
helper = importlib.util.module_from_spec(spec)
exec(r.content, helper.__dict__)
helper.view_classify() # executes function from github file
именно то, что я искал
Вы можете добавить предупреждение о том, что он должен использовать только предварительно указанные
strили проверять их перед вызовом методаexec.