Ignore ImportError when exec source code

I have an application that reads test scripts in python and sends them over the network for execution on a remote python instance. Since the control program does not need to run these scripts, I do not want all the modules used by the test scripts to be installed in the python controller environment. However, the dispatcher needs information from the test script to tell him how to run the test. Currently, what I am doing for reading and importing test data script seems to be

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 gives a new module containing the test. Unfortunately, exec will increase ImportErrors if the test tries to import something that 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 modules, can I somehow ignore these exceptions? Or is there any other way to find out the names and classes defined in the test?

Test example:

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 inherited from testUnit.

+3
source share
3 answers

Write an import hook that catches the exception and returns a dummy module if the module does not 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 can also write it to always return a dummy module or return a dummy module if the specified module is not already loaded (hint: if it is in sys.modules, it is already loaded).

+8
source

python ast script AST, , . , script.

+2

I think based on what you say you can just say:

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

Does it help?

+1
source

All Articles