开发者

Ignore ImportError when exec source code

I have an application that reads test scripts in python and sends them across the network for execution on a remote python instance. As the controlling program does not need to run these scripts I do not want to have all the modules the test scripts use installed on the controller's python environment. However the controller does need information from the test script to tell it how to run the test. Currently what I do to read and import test script data is something like

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__

which yields a new module that contains the test. Unfortunately exec will raise ImportErrors if the test tries to import something the controller does not have. And worse, the module will not be fully imported.

If I can guarantee that the controller will not use the missing module开发者_高级运维s, is there someway I can ignore these exceptions? Or some other way to find out the names and classes defined in the test?

Examples test:

from controller import testUnit
import somethingThatTheControllerDoesNotHave

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

class PartOne( testUnit ):
    def run( self ):
        pass

What the controller needs to know is the data in _testAttr and the name of all class definitions inheriting from testUnit.


Write an import hook that catches the exception and returns a dummy module if the module doesn't exist.

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

You could also write it to always return a dummy module, or to return a dummy module if the specified module hasn't already been loaded (hint: if it's in sys.modules, it has already been loaded).


I think, based on what you're saying, that you can just say:

try:
    exec co in m.__dict__
except ImportError: pass

Does that help?


You could use python ast module, and parse the script to an AST tree and then scan through the tree looking for elements of interest. That way you don't have to execute the script at all.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜