Как сгенерировать объект модуля из объекта кода в Python - PullRequest
12 голосов
/ 23 февраля 2010

Учитывая, что у меня есть объект кода для модуля, как мне получить соответствующий объект модуля?

Похоже, moduleNames = {}; exec code in moduleNames делает что-то очень близкое к тому, что я хочу. Возвращает глобальные переменные, объявленные в модуле, в словарь. Но если я хочу фактический объект модуля, как я получу это?

EDIT: Похоже, вы можете свернуть свой собственный объект модуля. Тип модуля удобно не задокументирован, но вы можете сделать что-то вроде этого:

import sys
module = sys.__class__
del sys
foo = module('foo', 'Doc string')
foo.__file__ = 'foo.pyc'
exec code in foo.__dict__

1 Ответ

20 голосов
/ 23 февраля 2010

Как уже отмечалось в комментарии, в современном 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.

...