内部编译代码中缺少模块

时间:2014-05-14 22:32:24

标签: python

我尝试使用compile / exec嵌套python脚本。

#!/usr/bin/env python
#file: a.py
import sys

def in_a():
    pass

print '__name__=',__name__
print 'modules[__name__]=', dir(sys.modules[__name__])

直接运行会给我一个包含in_a函数的对象列表。

使用编译/代码从另一个脚本运行它不会再给我in_a了。

#!/usr/bin/env python
# file: b.py
import sys

def in_b():
    pass

script = open('a.py','r').readlines()
context = dict(
      __name__='__main__',
      __file__='a.py',
   )
code = compile("\n".join(script), 'a.py', 'exec')
exec(code, context)

是否可以在a.py中找到对内部模块的引用?

1 个答案:

答案 0 :(得分:1)

使用exec时,您没有获得模块。模块通常来自进口机械。您可以通过types模块准备模块:

import types
someModule = types.ModuleType("anyModuleNameIsFine")
context = someModule.__dict__
context.update({'ambient': 'globals'})
exec(code, context)

但这似乎有点奇怪。这也不会将它们放在sys.modules中,您也可以 将它们放在那里:

sys.modules['anyOtherName'] = someModule

但现在我们已经危险地接近自定义导入程序,在这种情况下,您应该只是明确地使用自定义导入程序:

import imp, sys

class HelloImporter(object):

    def get_code(self, fullname):
        return "print 'hello world'"

    def is_package(self, fullname):
        return False

    def find_module(self, fn, p):
        if fn == 'hello':
            return self

    # see: http://legacy.python.org/dev/peps/pep-0302/#id27
    def load_module(self, fullname):
        code = self.get_code(fullname)
        ispkg = self.is_package(fullname)
        mod = sys.modules.setdefault(fullname, imp.new_module(fullname))
        mod.__file__ = "<%s>" % self.__class__.__name__
        mod.__loader__ = self
        if ispkg:
            mod.__path__ = []
            mod.__package__ = fullname
        else:
            mod.__package__ = fullname.rpartition('.')[0]
        exec(code, mod.__dict__)
        return mod

要使用它,请将其添加到sys.meta_path

>>> import sys
>>> sys.meta_path.append(sa_import.HelloImporter())
>>> import hello
hello world