フレームワーク用の拡張可能なプラグイン サブシステムに取り組んでいますが、システムがプラグイン自体からプラグインを動的かつシームレスにロードする方法に行き詰まっています。プラグインを追加する方法はすでに知っています (おそらくエントリポイントを使用する予定です)。例として:
pluga.py
from framework.plug_lib import plugin
@plugin
def foo():
return 2
@plugin
def bar():
return foo()
plugb.py
from framework.plug_lib import plugin
@plugin
def foo():
return 3
フレームワーク.plug_lib.py
loaded_plugins = {}
class Plugin(object):
def __init__(self, plug): #note plug could be class, function, method, etc
self.plug = plug
def plug_load(self):
loaded_plugins[self.plug.__name__] = self.plug
def plug_get_loaded_version(self):
try:
return loaded_plugins[self.plug.__name__]
except KeyError:
raise RuntimeError('No plugin %s loaded.' % self.plug.__name__)
def plugin(plug):
return Plugin(plug)
def load(plugin_path):
# get plugin by searching entry-points, other basic logic
plugin.plug_load()
使用例:
from framework.plug_lib import load, loaded_plugins
load('pluga.foo')
load('pluga.bar')
loaded_plugins['bar']() # 2
.
from framework.plug_lib import load, loaded_plugins
load('plugb.foo')
load('pluga.bar')
loaded_plugins['bar']() # 3
これは、問題を簡潔に説明するために単純化されています。実際のフレームワークでは、複数の異なるタイプのプラグインがあり、それらはすべて異なるloaded_plugin
アナログに移動します。プラグインのコンテナーがクラスである場合、おそらくこれを記述子などに押し込む方法を考え出すことができますが、これのポイントの一部は、現在プラグインをラップしているボイラープレート コードをリファクタリングすることです。モジュール自体が独自の名前空間を検査し、プラグイン モジュール自体に単純な行がないか、最大で 1 行しかないメンバーを取得する方法をカスタマイズできますか? __getattribute__
私は基本的にモジュール自体に同等のものを必要とするのでPlugins
、貧しい人の記述子のように振る舞いself.plug_get_loaded_version()
、それら以外のものにアクセスしようとするたびに戻ることができますplug_load()
方法だと思いますが、それを行う方法がわかりません。おそらくパッケージ時のコード(setup.pyの何か)ですが、毎回再構築せずに開発モードでインストールされたパッケージで作業することはできないと思います。そこに何かアイデアはありますか?