我尝试使用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中找到对内部模块的引用?
答案 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