当exec源代码时忽略ImportError

Cha*_*les 4 python

我有一个应用程序,它在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__
Run Code Online (Sandbox Code Playgroud)

这会产生一个包含测试的新模块.不幸的是,如果测试试图导入控制器没有的东西,exec将引发ImportErrors.更糟糕的是,该模块将不会完全导入.

如果我可以保证控制器不会使用丢失的模块,那么我可以忽略这些异常吗?或者通过其他方式找出测试中定义的名称和类?

示例测试:

from controller import testUnit
import somethingThatTheControllerDoesNotHave

_testAttr = ['fast','foo','function']

class PartOne( testUnit ):
    def run( self ):
        pass
Run Code Online (Sandbox Code Playgroud)

控制器需要知道的是_testAttr中的数据以及从testUnit继承的所有类定义的名称.

kin*_*all 12

编写一个捕获异常的导入钩子,如果模块不存在则返回一个虚拟模块.

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
Run Code Online (Sandbox Code Playgroud)

您也可以将其写入以始终返回虚拟模块,或者如果尚未加载指定的模块则返回虚拟模块(提示:如果它sys.modules已经加载,则它已经被加载).