Учитывая, что у меня есть объект кода для модуля, как я получаю соответствующий объект модуля?
Это похоже moduleNames = {}; exec code in moduleNames
делает что-то очень близко к тому, что я хочу. Это возвращает globals, объявленный в модуле в словарь. Но если я хочу фактический объект модуля, как я получаю его?
Править: Похоже, что можно прокрутить собственный объект модуля. Тип модуля удобно не документируется, но можно сделать что-то вроде этого:
import sys
module = sys.__class__
del sys
foo = module('foo', 'Doc string')
foo.__file__ = 'foo.pyc'
exec code in foo.__dict__
Как уже указано в одном из комментариев, в современном Python предпочтительным способом инстанцирования типов, не имеющих встроенных имен, является вызов типа, полученного через модуль types из стандартной библиотеки:
>>> import types
>>> m = types.ModuleType('m', 'The m module')
обратите внимание, что это не автоматически вставляет новый модуль в sys. modules
:
>>> import sys
>>> sys.modules['m']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'm'
Эту задачу вы должны выполнить вручную:
>>> sys.modules['m'] = m
>>> sys.modules['m']
<module 'm' (built-in)>
Это может быть важно, поскольку объект кода модуля обычно выполняется после добавления модуля в sys. modules
-- например, совершенно правильно, если такой код будет ссылаться на sys.modules[__name__]
, и это приведет к ошибке (KeyError
), если вы забудете этот шаг. После этого шага и установки m.__file__
, как вы уже сделали в вашей правке,
>>> code = compile("a=23", "m.py", "exec")
>>> exec code in m.__dict__
>>> m.a
23
(или эквивалент Python 3, где exec
- функция, если, конечно, вы используете Python 3;-) будет правильным (конечно, вы обычно получаете объект кода более тонким способом, чем компиляция строки, но это не имеет значения для вашего вопроса;-).
В старых версиях Python вы бы использовали модуль new
вместо модуля types
для создания нового объекта модуля в начале, но new
устарел с Python 2.6 и удален в Python 3.