plugpyをリリースした
こんにちわ、あらびきプログラマーmopemopeです。
某ライブラリをpythonに移植しようとしてて、plugin周りはなんだかかライブラリ化した方が良さそうだっだので適当に作りました。
plugpy · PyPI
基本実装は以下の奴です。
Pluginシステムの実装 - def __mopemope__(self, *args, **kwargs):
Pluginの書き方
制限はコンストラクタに引数を持たないといかんって事ぐらいであとは自由です。
一応デフォルトでPluginクラスを継承を推奨します。
(Pluginはコンストラクタに引数を持っています)
足し算するplugin
plugins/test_plugin.py
from plugpy import * class TestPlugin(Plugin): def on_test(self, x, y ): return x + y
場所は適当なdir以下、plugin/とかにしておきます
呼び出し
まあそんなに難しくありません。
pluginのload周りなどはdebug=Trueでログを標準出力に吐きます。
from plugpy import * config = dict(plugin_path='<pluginのdir>', debug=True) load_plugin = load_plugins(config) print load_plugin result = dispatch('test', 1,2) print result
load_pluginsに設定の辞書を渡すとpluginはインスタンス化されます。
dispatchでキーになるメッセージと引数を渡すとpluginのメソッドが呼ばれ値が返ってきます
(結果とpluginクラスのtupleのリストが帰る)
デフォルトでon_ + メッセージのメソッドを呼び出します。
呼び出しのログはこんな感じ
2009-06-22 13:21:48,596 plugpy DEBUG plugin load config {'debug': True, 'plugin_path': './test/plugin'}
2009-06-22 13:21:48,597 plugpy DEBUG import plugin testplugin
2009-06-22 13:21:48,597 plugpy DEBUG find plugin class's plugin classes [ , ]
2009-06-22 13:21:48,598 plugpy DEBUG all target plugin classes [, ]
2009-06-22 13:21:48,599 plugpy DEBUG loaded plugins [, ]
2009-06-22 13:21:48,600 plugpy DEBUG dispatch send message:'test' call_method: 'on_test'
2009-06-22 13:21:48,600 plugpy DEBUG dispatch tocall_method 'on_test' arg_info: (1, 2) {} : result 3
2009-06-22 13:21:48,601 plugpy DEBUG dispatch finish message:'test' call_method: 'on_test' : results [(3,)]
またデフォルトではPluginのサブクラスをplugin扱いしますが設定で変更できます。
from plugpy import * config = dict(plugin_path='<pluginのdir>', debug=True, plugin_class=[<任意のクラス>])
__subclasses__()でヒットするものであればなんでも読み込みます。
(逆に再帰でsuperクラスをずっと辿ったりはしません)
呼び出し側もplugin_classでメッセージを送るpluginを制限できます。
(issubclassで判断してるのでsubclassか同classであれば呼び出します)
prefxiもon_から変更可能です。
result = dispatch('test', 1,2, plugin_class=[<メッセージを送りたいクラス>], prefix='')
まあ利点はこんな感じかな
- pluginはどこにでも置いていい(sys.pathに突っ込んでimportするから)
- plugpy経由で値をやり取りするのでplugin間はお互いのインスタンスを知らなくてよい
- 複数のpluginにメッセージを送れる(メッセージは対照全てに送る)
- subclassでも引っ掛けれるので具体的な実装pluginクラスを知らなくてもいい