2

私は自分のプログラムのプラグイン システムを書いていますが、次の 1 つの問題を乗り越えることができません。

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

「スーパー」は組み込みです。わざわざビルトインを削除しない限り、「global name 'super' is not defined」が表示されることはありません。

IntrospectionHelper のダンプがあるユーザー Web リンクを見ています。インデントなしで読むのは非常に困難ですが、まさにそれを行っているようです:

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

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

それはあなたが変更しようとしている元のモジュール dict であり、あなたが返そうとしている情報のコピーではありません! これらのメンバーをライブ モジュールから削除すると、'super' よりもはるかに多くのことが中断されることが予想されます。

そのモジュールが何をしているのかを追跡するのは非常に難しいですが、私の反応は、そこにはあまりにも多くの魔法が含まれているということです. 平均的な Python プログラムは、インポート システム、sys.path、モンキー パッチ __magic__ モジュール メンバーをいじる必要はありません。少しの魔法は巧妙なトリックになる可能性がありますが、これは非常に脆弱です。ブラウジングして思いついたのですが、コードは次のようなもので壊れている可能性があります。

  • トップレベルのモジュールと名前が衝突する
  • 新しいスタイルのクラスの使用
  • コンパイルされたバイトコードとしてのみ提供されるモジュール
  • zipimporter

getClassDefinitions、extractModuleNames、isFromBase などの信じられないほど回りくどい関数から、Python の仕組みの基本について学ぶことがまだかなりあるように思えます。(手がかり: それぞれ、getattr、module.__name__、issubclass)

この場合、今はインポート マジックに飛び込む時ではありません。大変です。代わりに、The Normal Python Way を実行してください。パッケージの 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

2.2 より前のバージョンの Python を実行している場合を除き (ほとんどありません)、super()は間違いなく組み込み関数です (すべてのスコープで使用可能で、何もインポートする必要はありません)。

Python のバージョンを確認する価値があるかもしれません (コマンド ラインで python と入力して対話型プロンプトを起動するだけです)。

于 2009-03-04T22:05:07.430 に答える