Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何动态加载Python类_Python_Reflection_Python Import - Fatal编程技术网

如何动态加载Python类

如何动态加载Python类,python,reflection,python-import,Python,Reflection,Python Import,给定Python类的字符串,例如my_package.my_module.MyClass,加载它的最佳方式是什么 换句话说,我正在寻找Java中的等效函数Class.forName(),Python中的函数。它需要在谷歌应用程序引擎上运行 这最好是一个函数,它接受类的FQN作为字符串,并返回对类的引用: my_class = load_class('my_package.my_module.MyClass') my_instance = my_class() 根据python文档,您需要以下函

给定Python类的字符串,例如
my_package.my_module.MyClass
,加载它的最佳方式是什么

换句话说,我正在寻找Java中的等效函数
Class.forName()
,Python中的函数。它需要在谷歌应用程序引擎上运行

这最好是一个函数,它接受类的FQN作为字符串,并返回对类的引用:

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

根据python文档,您需要以下函数:

def my_import(name):
    components = name.split('.')
    mod = __import__(components[0])
    for comp in components[1:]:
        mod = getattr(mod, comp)
    return mod
简单的
\uuuu导入\uuuu
不起作用的原因是,任何超过包字符串中第一个点的内容的导入都是要导入的模块的属性。因此,像这样的事情是行不通的:

__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
模块中有一个函数可用于执行以下操作:

from pydoc import locate
my_class = locate('my_package.my_module.MyClass')
与这里列出的其他方法相比,这种方法的优点是
locate
将在提供的点路径中找到任何python对象,而不仅仅是模块中的直接对象。e、 g.
my\u package.my\u 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

在Google App Engine中有一个名为
import\u string
webapp2
函数。有关更多信息,请参见此处:

所以


例如,这在
webapp2.Route
中使用,您可以使用处理程序或字符串。

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


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

如果您恰好已经有了所需类的实例,则可以使用“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()

如果你用的是Django,你可以用这个。是的,我知道OP没有要求django,但我遇到了这个问题,正在寻找django的解决方案,但没有找到,并把它放在这里给下一个寻找它的男孩/女孩

#它适用于v1.7+
# https://github.com/django/django/blob/stable/1.7.x/django/utils/module_loading.py
从django.utils.module\u加载导入\u字符串
Klass=import_字符串('path.to.module.Klass')
func=导入字符串('path.to.module.func')
var=import\u字符串('path.to.module.var'))
请记住,如果要导入没有
的内容,如
re
argparse
,请使用:

re=\uuuuu导入('re'))

在尝试解决此问题时,我在
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
importlib
上找到了一些东西

我正在使用Python 3.7.3

当我试图进入模块
a.b.c
中的
d
课程时

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_模块时,我们实际上得到了最深模块的句柄

mod = importlib.import_module('a.b.c') #mod is module c
d = getattr(mod, 'd') #this is a.b.c.d


我还需要能够将类引用分配给一个变量,这似乎是:我从来没有在Python中加载过这样的类。你知道模块在哪里,那么为什么不加载模块,然后像Python希望你那样使用它的类呢?它非常简单如果你从来没有这样做过,那么你还没有编写足够有趣的程序。继续练习。有趣的是“够了”。这只是一种开玩笑的说法,说做奇怪的事情有时是必要的,因为你无法控制和难以预测的因素。前面的评论基本上是这样的:“为什么不以正常的方式导入呢?”我想说的是,有一天他们也会遇到一个奇怪的情况,需要做一些难看的事情。请注意,这是因为导入函数中有一个bug。导入函数中不应使用文件路径,在Python2.6及更高版本中也不起作用:我尝试了my_导入(“my_package.my_module.my_class”),但没有找到任何模块my_class,这很有意义,因为它是一个类而不是一个模块。但是,如果我可以在调用我的导入后使用getAttr获取类,这很奇怪。超过第一个点的所有内容都使用getattr调用。应该没什么区别。谢谢。我认为这是最好的办法。现在,我只需要最好的方法将字符串“my_pakcage.my_module.my_class”拆分为mod_name和klass_name,但我想我可以弄清楚:)import的python文档(在代码中)说要使用importlib。那么,Adam SpenceLink@naoko的结帐答案应该是指:这是干净的解决方案!您可以考虑使用:<代码>(MuleMeNeNe,CuleNeX)=C.R拆分('.',2)这是很好的)我已经创建了不同的UTILS的PUTILS包,也在那里导入了类。如果您愿意,您可以从该软件包中使用它。@vdboor
rsplit('.',1)
?我设法传递了{}而不是全局/局部变量,它仍然可以正常工作。一旦您动态导入了模块,您就可以通过模块访问该类。请编辑我的答案,使其更加简洁。这是在Python中加载类的最佳方法。B-B-B-Benny和Spence!;)伟大的它甚至是2.7及更高版本标准库的一部分。这是访问模块/类的正确方法。文件在这里声明:我对这个答案投了赞成票。顺便说一句,这里的代码也有safeimport,因为仅仅为了这个导入pydoc似乎有些奇怪:我也对这个答案进行了投票,这是所有相关答案中最好的一个。它似乎也能够正确处理
qualname
(对象不在模块名称空间的顶部)。实际上,最好的
a = __import__('file_to_import', globals(), locals(), ['*'], -1)
b = a.MyClass()
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()
mod = __import__('a.b.c')
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')
mod = importlib.import_module('a.b.c') #mod is module c
d = getattr(mod, 'd') #this is a.b.c.d