Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.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 2.7 为自注册插件使用元类?(接近帮助)_Python 2.7_Dynamic_Plugins_Metaclass - Fatal编程技术网

Python 2.7 为自注册插件使用元类?(接近帮助)

Python 2.7 为自注册插件使用元类?(接近帮助),python-2.7,dynamic,plugins,metaclass,Python 2.7,Dynamic,Plugins,Metaclass,我正试图编写一个Python 2.7库,在运行时加载某些类。这些类包含一组预定义的方法 我的方法是定义我在库中使用的几个元类。例如,我将定义一个导航元类并在库中使用它。然后有人可以编写一个类主菜单,其中包含某种类型的类型定义,它是一个导航插件。然后图书馆可以使用这个类 我能够加载模块,也能够编写元类。我的问题在于把这两件事结合起来 首先有一个问题,我希望插件类位于不同的可配置文件夹中。因此,我不能: __metaclass__ = Navigation 因为导航类是我的库的一部分,不会出现在插

我正试图编写一个Python 2.7库,在运行时加载某些类。这些类包含一组预定义的方法

我的方法是定义我在库中使用的几个元类。例如,我将定义一个导航元类并在库中使用它。然后有人可以编写一个类主菜单,其中包含某种类型的类型定义,它是一个导航插件。然后图书馆可以使用这个类

我能够加载模块,也能够编写元类。我的问题在于把这两件事结合起来

首先有一个问题,我希望插件类位于不同的可配置文件夹中。因此,我不能:

__metaclass__ = Navigation
因为导航类是我的库的一部分,不会出现在插件文件夹中。。。 我怎样才能解决告诉插件的类型的问题呢?导航、内容。。。。e、 g

编辑2:我解决了以下问题。我发现我可以让模块给我一个口述。 但我的第一个问题仍然存在

编辑:

我一直在使用注册表注册和加载普通类,直到以下几点:

from os import listdir
from os.path import isfile, join
import imp


class State:
    registry = {}

    def register_class(self,target_class):
        self.registry[target_class.__name__] = target_class
        print target_class.__name__+" registered!"

    def create(self,classname):
        tcls = self.registry[classname]
        print self.registry[classname]
        return tcls()

s = State()
mypath = """C:\metatest\plugins"""
files = [f for f in listdir(mypath) if isfile(join(mypath, f))]
for f in files:
    spl = f.split(".")
    if spl[1] == "py":
        a = imp.load_source(spl[0], mypath + """\\""" + f)
        s.register_class(a)
最后的问题是,a是加载的模块,所以它是一个模块对象。在我的例子中,它只有一个类。
如何从加载的模块中获取类对象,以便正确注册该类???

因此,让我们检查一下您的问题,然后回到您当前的建议。 您需要一种为更大的系统提供插件的方法——更大的系统在编码时不知道插件的情况——但事实并非如此:您的插件应该能够在更大的系统上加载模块、导入基类和调用函数

除非你真的有一个可插拔的东西,插件可以与多个更大的系统一起工作。我对此表示怀疑,但如果是这样的话,您需要一个能够在不同类之间注册接口、检索类和适配器实现的框架。该框架是Zope接口-您应该在此处阅读关于它的文档:

更实际的是一个插件系统,它可以为Python文件搜索一些预设目录并导入这些目录。正如我上面所说的,如果这些文件确实导入基类或元类,对于主系统上的记录来说是没有问题的:这些已经由Python在运行过程中导入了,它们在插件中的导入将只是补充,然后在插件代码中显示为可用

您可以使用上面的代码,只需添加一个短元类来注册State的派生类-您可以约定不同插件类别的每个基类都具有registry属性:

class RegistryMeta(type):
    def __init__(cls, name, bases, namespace):
        for base in cls.__mro__:
            if 'registry' in base.__dict__:
                  if cls.__name__ in base.registry:
                       raise ValueError("Attempting to registrate plug-in with the name {} which is already taken".format(cls.__name__))
                  base.registry[cls.__name__] = cls
                  break
        super(RegistryMeta, cls).__init__(name, base, namespace)

class State(object):
    __metaclass__ = RegistryMeta
    registry = {}
    ...
保留用于扫描目录和加载模块的代码-只需将所有目录分隔栏切换到/-您仍然没有正确地执行此操作,并且使用\

在插件代码上包括:

from mysystem import State

class YourClassCode(State):
   ...

最后,正如我在评论中所说的:您应该检查一下使用Python3.6的可能性。在其他细节中,您可以使用_init_subclass__u;特殊方法,而不需要自定义元类来保存注册表。

首先要注意的是:如果这是Python2,那么yur类必须从具有适当元类集的对象继承。否则,它是一个旧式的类,许多被认为是理所当然的机制在对象上根本不起作用。第二件事:您没有在新代码中使用Python 3,因为?谢谢!我仍然必须完全理解这一切,但这似乎正是我想要的!我会使用Python 3.6,但我不能。。。现有的结构和老板和东西:DOkay。现在仔细看一下,有几件事我不太明白:1。我将State对象视为保存和维护已加载插件注册表的对象。为什么我希望插件从州继承?2.我想我不完全明白这里发生了什么。有没有比和cls更有效的方法将状态本身排除在注册表之外插件3。*args、**kwargs来自哪里?4.我真的不明白这句话,你可以约定不同插件类别的每个基类都有注册表属性。我想我现在明白了。你的意思是我可以为不同的插件类别提供不同版本的State类,对吗?是的。-针对不同插件类别的不同类。args和kwargs之所以存在,是因为我以前的想法中存在复制和粘贴错误,现在我已经修复了它们。