如何从Python中的代码对象生成模块对象

时间:2010-02-22 23:21:26

标签: python bytecode

鉴于我有一个模块的代码对象,我如何获得相应的模块对象?

看起来moduleNames = {}; exec code in moduleNames做了一件非常接近我想要的事情。它将模块中声明的全局变量返回到字典中。但是,如果我想要实际的模块对象,我该如何获得它呢?

编辑: 看起来您可以滚动自己的模块对象。模块类型不方便记录,但您可以这样做:

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

1 个答案:

答案 0 :(得分:20)

正如评论已经指出的那样,在今天的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后执行 - 例如,这样的代码引用{{1}完全正确如果你忘了这一步,那就失败了(sys.modules[__name__])。 完成此步骤后,按照您在编辑中设置的KeyError进行设置,

m.__file__

(或者Python 3等价物>>> code = compile("a=23", "m.py", "exec") >>> exec code in m.__dict__ >>> m.a 23 是一个函数,如果你正在使用Python 3,当然;-)是正确的(当然,你通常已经获得了代码对象微妙意味着比编译一个字符串,但这对你的问题不重要; - )。

在旧版本的Python中,你可以使用exec模块而不是new模块在​​开始时创建一个新的模块对象,但是自Python 2.6以来不推荐使用types在Python 3中删除。