如何dynamic加载一个Python类

给定一个Python类的string,例如my_package.my_module.MyClass ,加载它的最佳方法是什么?

换句话说,我正在寻找一个相当于Java的Class.forName() ,在Python中的function。 它需要在Google App Engine上工作。

最好这是一个函数,接受类的FQN作为一个string,并返回一个类的引用:

 my_class = load_class('my_package.my_module.MyClass') my_instance = my_class() 

从Python文档,这里是你想要的function:

 def my_import(name): components = name.split('.') mod = __import__(components[0]) for comp in components[1:]: mod = getattr(mod, comp) return mod 

简单的__import__的原因是因为任何经过包string中的第一个点的任何input都是您正在导入的模块的属性。 因此,这样的事情是行不通的。

 __import__('foo.bar.baz.qux') 

你必须像这样调用上面的函数:

 my_import('foo.bar.baz.qux') 

或者以你的例子为例:

 klass = my_import('my_package.my_module.my_class') some_object = klass() 

编辑 :我有点在这个。 你基本上想要做的是这样的:

 from my_package.my_module import my_class 

只有当你有一个空的 fromlist时,上面的函数才是必须的。 因此,适当的电话会是这样的:

 mod = __import__('my_package.my_module', fromlist=['my_class']) klass = getattr(mod, 'my_class') 

如果你不想推出你自己的,那么在pydoc模块中有一个可用的function就是:

 from pydoc import locate my_class = locate('my_package.my_module.MyClass') 

这种方法比其他列出的方法的优点是, locate将在提供的虚线path中find任何 python对象,而不仅仅是一个模块中的对象。 例如my_package.my_module.MyClass.attr

如果你好奇他们的食谱是什么,这里的function:

 def locate(path, forceload=0): """Locate an object by name or dotted path, importing as necessary.""" parts = [part for part in split(path, '.') if part] module, n = None, 0 while n < len(parts): nextmodule = safeimport(join(parts[:n+1], '.'), forceload) if nextmodule: module, n = nextmodule, n + 1 else: break if module: object = module else: object = __builtin__ for part in parts[n:]: try: object = getattr(object, part) except AttributeError: return None return object 

它依赖于pydoc.safeimport函数。 这里是文档:

 """Import a module; handle errors; return None if the module isn't found. If the module *is* found but an exception occurs, it's wrapped in an ErrorDuringImport exception and reraised. Unlike __import__, if a package path is specified, the module at the end of the path is returned, not the package at the beginning. If the optional 'forceload' argument is 1, we reload the module from disk (unless it's a dynamic extension).""" 
 import importlib module = importlib.import_module('my_package.my_module') my_class = getattr(module, 'MyClass') my_instance = my_class() 
 def import_class(cl): d = cl.rfind(".") classname = cl[d+1:len(cl)] m = __import__(cl[0:d], globals(), locals(), [classname]) return getattr(m, classname) 

好吧,对我来说,这是它的工作方式(我使用Python 2.7):

 a = __import__('file_to_import', globals(), locals(), ['*'], -1) b = a.MyClass() 

然后,b是类“MyClass”的一个实例,

在Google App Engine中,有一个名为import_stringwebapp2函数。 有关更多信息,请参阅此处: https : //webapp-improved.appspot.com/api/webapp2.html

所以,

 import webapp2 my_class = webapp2.import_string('my_package.my_module.MyClass') 

例如,在webapp2.Route ,您可以使用处理程序或string。

 module = __import__("my_package/my_module") the_class = getattr(module, "MyClass") obj = the_class()