We’ve developed this to be able to run trusted methods as batch operations that were saved into database to be performed later on. The code is easy to understand reading its tests:

Tests: Check out this file

Code:

import os
import inspect
import inspect

class PythonInvoker():
    def __init__(self, targetBaseClass=None):
        self.targetBaseClass = targetBaseClass 
        
    def evalArgumentsIfNotStrings(self, param):
        if len(param) > 0:
            param = param.strip()
            if param[0] == "\"" or param[0] == "'":
                return param
            else:
                try:
                    return eval(param,{"__builtins__":None},{})
                except NameError:
                    raise ApplicationException("Security exception: arguments can only be variables. This argument is -> " + param) 
        else:
            return param
                
    def secureDynamicInvoke(self, classInstance, methodName, arguments):
        if isinstance(classInstance, self.targetBaseClass):
           return self.dynamicInvoke(classInstance, methodName, arguments)
        else:
           raise ApplicationException(str(classInstance) + " does not extends " + str(self.targetBaseClass))   
        
    def dynamicInvoke(self, classInstance, methodName, arguments):
        if arguments == None:
            arguments = ""
        try:
            method = getattr(classInstance, methodName)
        except AttributeError:
            raise ApplicationException("Method does not belong in class!: " + str(classInstance) + "-" + str(methodName))
        retInfo = None
        try:
            if re.search(",", arguments):
               args = arguments.split(",")
               args = map(self.evalArgumentsIfNotStrings, args)
               retInfo= method(*args)
            else:
               retInfo= method()
        except TypeError, e:
            raise ApplicationException(str(classInstance) + "." + str(methodName) + " - " + e.message)
        return retInfo