给定一个Python类的字符串,例如my_package.my_module.MyClass
,加载它的最佳方式是什么?
换句话说,我在Java中寻找等效的Class.forName()
,用Python编写。它需要在Google App Engine上运行。
最好这是一个函数,它接受类的FQN作为字符串,并返回对类的引用:
my_class = load_class('my_package.my_module.MyClass')
my_instance = my_class()
答案 0 :(得分:166)
从python文档中,这是你想要的功能:
def my_import(name):
components = name.split('.')
mod = __import__(components[0])
for comp in components[1:]:
mod = getattr(mod, comp)
return mod
简单__import__
不起作用的原因是因为任何超出包字符串中第一个点的内容都是您要导入的模块的属性。因此,这样的事情是行不通的:
__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')
答案 1 :(得分:102)
如果您不想自己推送,pydoc
模块中有一个功能可以完成此操作:
from pydoc import locate
my_class = locate('my_package.my_module.MyClass')
此方法优于此处列出的其他方法的优点是locate
将在提供的虚线路径中找到任何 python对象,而不仅仅是模块中直接的对象。例如my_package.my_module.MyClass.attr
。
如果你很好奇他们的食谱是什么,这就是功能:
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)."""
答案 2 :(得分:73)
import importlib
module = importlib.import_module('my_package.my_module')
my_class = getattr(module, 'MyClass')
my_instance = my_class()
答案 3 :(得分:29)
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)
答案 4 :(得分:5)
如果您使用的是Django,则可以使用它。 是的,我知道OP并没有要求django,但是我遇到了这个问题,寻找Django解决方案,没有找到一个解决方案,并将其放在这里供下一个寻找它的下一个男孩/女孩使用。
Service
请记住,如果要导入没有# It's available for v1.7+
# https://github.com/django/django/blob/stable/1.7.x/django/utils/module_loading.py
from django.utils.module_loading import import_string
Klass = import_string('path.to.module.Klass')
func = import_string('path.to.module.func')
var = import_string('path.to.module.var')
的内容,例如.
或re
,请使用:
argparse
答案 5 :(得分:1)
好的,对我而言,这就是它的工作方式(我使用的是Python 2.7):
a = __import__('file_to_import', globals(), locals(), ['*'], -1)
b = a.MyClass()
然后,b是“MyClass”类的实例
答案 6 :(得分:0)
如果您碰巧已经有了所需类的实例,则可以使用'type'函数提取其类类型并使用它来构造新的实例:
class Something(object):
def __init__(self, name):
self.name = name
def display(self):
print(self.name)
one = Something("one")
one.display()
cls = type(one)
two = cls("two")
two.display()
答案 7 :(得分:0)
在这里分享我在__import__
和importlib
上发现的东西,同时尝试解决此问题。
我正在使用Python 3.7.3。
当我尝试进入模块d
中的课程a.b.c
时,
mod = __import__('a.b.c')
mod
变量引用顶部的命名空间a
。
因此,要进入课程d
,我需要
mod = getattr(mod, 'b') #mod is now module b
mod = getattr(mod, 'c') #mod is now module c
mod = getattr(mod, 'd') #mod is now class d
如果我们尝试做
mod = __import__('a.b.c')
d = getattr(mod, 'd')
我们实际上是在寻找a.d
。
使用importlib
时,我想该库已为我们完成了递归getattr
。因此,当我们使用importlib.import_module
时,实际上是在最深层的模块上获得了句柄。
mod = importlib.import_module('a.b.c') #mod is module c
d = getattr(mod, 'd') #this is a.b.c.d
答案 8 :(得分:-2)
module = __import__("my_package/my_module")
the_class = getattr(module, "MyClass")
obj = the_class()
答案 9 :(得分:-2)
在Google App Engine中有一个名为webapp2
的{{1}}函数。有关详细信息,请参阅此处:https://webapp-improved.appspot.com/api/webapp2.html
所以,
import_string
例如,这可以在import webapp2
my_class = webapp2.import_string('my_package.my_module.MyClass')
中使用,您可以使用处理程序或字符串。