2

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

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

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

4

2 回答 2

20

'super' 是内置的。除非您竭尽全力删除内置函数,否则您永远不会看到“未定义全局名称 'super'”。

我正在查看您的用户 Web 链接,其中有 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__ 模块成员。一点点魔法可以是一个巧妙的技巧,但这非常脆弱。就在我浏览它的时候,代码可能会被以下内容破坏:

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

从 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() 并不总是“更新、更好的做事方式”,在你开始使用它之前,你应该了解一些事情。

于 2009-03-04T22:02:24.943 回答
0

除非您运行的 Python 版本早于 2.2(不太可能),否则super()绝对是一个内置函数(在每个范围内都可用,并且无需导入任何内容)。

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

于 2009-03-04T22:05:07.430 回答