我有一个应用程序,它在python中读取测试脚本,并通过网络发送它们,以便在远程python实例上执行。由于控制程序不需要运行这些脚本,我不希望在控制器的python环境中安装测试脚本使用的所有模块。但是,控制器确实需要测试脚本中的信息来告诉它如何运行测试。 目前我所做的阅读和导入测试脚本数据类似于
with open( 'test.py', 'r' ) as f:
source = f.read()
m = types.ModuleType( "imported-temp", "Test module" )
co = compile( source, 'test.py', 'exec' )
exec co in m.__dict__
产生一个包含测试的新模块。不幸的是,如果测试试图导入控制器没有的东西,exec将引发ImportErrors。更糟糕的是,该模块将无法完全导入。
如果我可以保证控制器不会使用丢失的模块,那么我可以忽略这些异常吗?或者用其他方法找出测试中定义的名称和类?
示例测试:
from controller import testUnit
import somethingThatTheControllerDoesNotHave
_testAttr = ['fast','foo','function']
class PartOne( testUnit ):
def run( self ):
pass
控制器需要知道的是_testAttr中的数据以及从testUnit继承的所有类定义的名称。
答案 0 :(得分:10)
编写一个捕获异常的导入钩子,如果模块不存在则返回一个虚拟模块。
import __builtin__
from types import ModuleType
class DummyModule(ModuleType):
def __getattr__(self, key):
return None
__all__ = [] # support wildcard imports
def tryimport(name, globals={}, locals={}, fromlist=[], level=-1):
try:
return realimport(name, globals, locals, fromlist, level)
except ImportError:
return DummyModule(name)
realimport, __builtin__.__import__ = __builtin__.__import__, tryimport
import sys # works as usual
import foo # no error
from bar import baz # also no error
from quux import * # ditto
您还可以将其写入始终返回虚拟模块,或者如果指定的模块尚未加载则返回虚拟模块(提示:如果它在sys.modules
中,已经加载了。)
答案 1 :(得分:3)
我认为,根据你所说的,你可以说:
try:
exec co in m.__dict__
except ImportError: pass
这有帮助吗?
答案 2 :(得分:2)
您可以使用python ast模块,并将脚本解析为AST树,然后在树中扫描以查找感兴趣的元素。这样你根本不必执行脚本。