what i do (for example in an engine of mine Contemplate), is this:
- have a set of classes available in subfolder
- dynamicaly import the appropriate class file
- 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:
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)
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.
Set of dynamic classes is specific and not ad-hoc, although it can be dynamicaly changed and/or enlarged at run-time if needed