我正在为我的程序编写一个插件系统,但我无法克服一件事:

class ThingLoader(object):
'''
Loader class
'''

    def loadPlugins(self):
        '''
        Get all the plugins from plugins folder
        '''
        from diones.thingpad.plugin.IntrospectionHelper import loadClasses

        classList=loadClasses('./plugins', IPlugin)#Gets a list of 
        #plugin classes
        self.plugins={}#Dictionary that should be filled with 
        #touples of objects and theirs states, activated, deactivated.
        classList[0](self)#Runs nicelly
        foo = classList[1]
        print foo#prints <class 'TestPlugin.TestPlugin'>
        foo(self)#Raise an exception

测试插件如下所示:

import diones.thingpad.plugin.IPlugin as plugin
   class TestPlugin(plugin.IPlugin):
       '''
     classdocs
    '''
    def __init__(self, loader):
        self.name='Test Plugin'
        super(TestPlugin, self).__init__(loader)

现在 IPlugin 看起来像这样:

class IPlugin(object):
    '''
    classdocs
    '''
    name=''
    def __init__(self, loader):
        self.loader=loader
    def activate(self):
        pass

所有 IPlugin 类本身都能完美运行,但当由 ThingLoader 调用时,程序会出现异常:

File "./plugins\TestPlugin.py", line 13, in __init__
    super(TestPlugin, self).__init__(loader) NameError: 
global name 'super' is not defined

我环顾四周,根本不知道发生了什么。

有帮助吗?

解决方案

‘super’是一个内置的。除非您不遗余力地删除内置函数,否则您不应该看到“全局名称'super'未定义”。

我正在看着你的 用户网页链接 那里有 IntrospectionHelper 的转储。如果没有缩进,很难阅读,但看起来您可能正在这样做:

built_in_list = ['__builtins__', '__doc__', '__file__', '__name__']

for i in built_in_list:
    if i in module.__dict__:
        del module.__dict__[i]

这是您要在那里更改的原始模块字典,而不是您要返回的信息副本!从实时模块中删除这些成员,您可以预见到不仅仅是“超级”会被破坏。

很难跟踪该模块正在做什么,但我的反应是它有太多的魔力。一般的 Python 程序永远不需要搞乱导入系统、sys.path 和猴子修补 __magic__ 模块成员。一点点魔法可能是一个巧妙的技巧,但这非常脆弱。浏览代码后,我突然想到,代码可能会被以下因素破坏:

  • 名称与顶级模块冲突
  • 任何新式类的使用
  • 仅作为编译字节码提供的模块
  • zip导入器

从 getClassDefinitions、extractModuleNames 和 isFromBase 等令人难以置信的迂回函数中,在我看来,关于 Python 工作原理的基础知识,您还有很多东西需要学习。(线索:分别是 getattr、module.__name__ 和 issubclass。)

在这种情况下现在是 不是 是时候深入研究进口魔法了!它是 难的. 。相反,以正常的 Python 方式做事。在包的 mypackage/__init__.py 的底部可能需要多输入一些内容:

from mypackage import fooplugin, barplugin, bazplugin
plugins= [fooplugin.FooPlugin, barplugin.BarPlugin, bazplugin.BazPlugin]

但它可以在任何地方发挥作用并被理解,而不需要依赖复杂而脆弱的魔法。

顺便说一句,除非您计划进行一些深入的多重继承工作(再说一次,现在可能不是这样做的时候),否则您可能甚至不需要使用 super()。调用已知超类的通常“IPlugin.__init__(self, ...)”方法是很简单的事情;super() 并不总是“更新、更好的做事方式”并且 有些事情你应该了解 在您开始充电使用它之前。

其他提示

除非您运行的是早于2.2的Python版本(非常不可能),否则 super()肯定是内置函数(适用于所有范围,无需导入任何内容)。

可能值得检查你的Python版本(只需在命令行输入python启动交互式提示)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top