Python: how to create a class name on the fly
Question: I am looking for a way to "identify" the class name on the fly based on an
incoming parameter and create its object. The code which I attempted gives
error "TypeError: 'str' object is not callable". Any suggestions on how to
achieve this?

    
    
    class interfaceMsg:
        def __init__(self):
            #Do some initializations
    
    
        def updateDB(self, cell_index, xml_msg):
            #Do something general
    
    
    class interfaceMsg_myMsg(interfaceMsg):
        def __init__(self):
            interfaceMsg.__init__(self)
            #Do some specific initializations
    
    
    class interfaceMsg_yourMsg(interfaceMsg):
        def __init__(self):
            interfaceMsg.__init__(self)
            #Do some special initializations
    
        def updateDB(self, cell_index, xml_msg):
            #Do something special
    
    
    
    ##and so on several derived classes
    
    
    
    def doUpdateDB(cell_index, xml_msg):
        # I basically want to create an object on the fly and call its updateDB function
    
        #Create the class name correspoding to this message
        class_name = "interfaceMsg_" + xml_msg.attrib["showname"]
    
        #class_name becomes interfaceMsg_myMsg or interfaceMsg_yourMsg or interfaceMsg_xyzMsg
    
        #This gives TypeError: 'str' object is not callable
        obj = class_name()
    
        obj.updateDB(cell_index, xml_msg)
    

Thanks


Answer: what i do (for example in an engine of mine
[Contemplate](https://github.com/foo123/Contemplate)), is this:

  1. have a set of classes available in subfolder
  2. dynamicaly import the appropriate class file
  3. get an instance of the class

All these assuming that the class is dynamic but from a specific set of
available classes, sample code follows:

sample available class:

    
    
    def __getClass__():
    
        class AClass:
    
            # constructor
    
            def __init__(self):
                pass
    
        return AClass
    
    
    
    # allow to 'import *'  from this file as a module
    
    __all__ = ['__getClass__']
    

sample dynamic class loading:

    
    
    def include( filename, classname, doReload=False ):
        # http://www.php2python.com/wiki/function.include/
        # http://docs.python.org/dev/3.0/whatsnew/3.0.html
        # http://stackoverflow.com/questions/4821104/python-dynamic-instantiation-from-string-name-of-a-class-in-dynamically-imported
    
        #_locals_ = {'Contemplate': Contemplate}
        #_globals_ = {'Contemplate': Contemplate}
        #if 'execfile' in globals():
        #    # Python 2.x
        #    execfile(filename, _globals_, _locals_)
        #    return _locals_[classname]
        #else:
        #    # Python 3.x
        #    exec(Contemplate.read(filename), _globals_, _locals_)
        #    return _locals_[classname]
    
        # http://docs.python.org/2/library/imp.html
        # http://docs.python.org/2/library/functions.html#__import__
        # http://docs.python.org/3/library/functions.html#__import__
        # http://stackoverflow.com/questions/301134/dynamic-module-import-in-python
        # http://stackoverflow.com/questions/11108628/python-dynamic-from-import
        # also: http://code.activestate.com/recipes/473888-lazy-module-imports/
        # using import instead of execfile, usually takes advantage of Python cached compiled code
    
        global _G
        getClass = None
        directory = _G.cacheDir
        # add the dynamic import path to sys
        os.sys.path.append(directory)
        currentcwd = os.getcwd()
        os.chdir(directory)   # change working directory so we know import will work
    
        if os.path.exists(filename):
    
            modname = filename[:-3]  # remove .py extension
            mod = __import__(modname)
            if doReload: reload(mod) # Might be out of date
            # a trick in-order to pass the Contemplate super-class in a cross-module way
            getClass = getattr( mod, '__getClass__' )
    
        # restore current dir
        os.chdir(currentcwd)
        # remove the dynamic import path from sys
        del os.sys.path[-1]
    
        # return the Class if found
        if getClass:  return getClass()
        return None
    

This scheme enables these things:

  1. dynamic file and module/class loading, where classname/file is dynamic but class name might not correspond to filename (have a generic `__getClass__` function for this in each module/class)

  2. the dynamic class file can be generated (as source code) on the fly or be pre-cached and so on... No need to (re-)generate if already available.

  3. Set of dynamic classes is specific and not ad-hoc, although it can be dynamicaly changed and/or enlarged at run-time if needed

