MayaとかPhotoshopとかで機能を追加するための『プラグイン』システムがありますが、
そういうのを自作のツールにも設けられないか、というメモです。
importlib
具体的には「importlib」モジュールを使います。
-
importlib — import() の便利なラッパー (Pythonドキュメント-標準ライブラリ)
http://docs.python.jp/2/library/importlib.html
このモジュールの「import_module」関数に モジュール名 を文字列で渡すことで、
import hogehoge
という書き方によらないモジュールのインポートができます。
文字列を受け取ってくれるので、見つけたモジュールを随時代入しながらインポートさせられそうです。
使うのは import_module だけなので、このようにインポートして使います。
from importlib import import_module
(importという文字列の登場頻度の高さ。。。)
引っ掛かりポイント
1: 絶対パスで渡そうとする
てっきりPythonファイルを渡すものだと勘違いしており、このように書いていました。
pluginPath = 'path/to/plugin'
for plugin in os.listdir(pluginPath):
mod_path = os.path.join(pluginPath,plugin)
mod = import_module(mod_path,)
ダメでした。
モジュール名を渡すのです。
また、そのためにはプラグイン用Pythonファイルを置いている場所を
sys.path.appendに追加しておく必要があります。
かつ、見つけたPythonファイルも拡張子は除去しておく必要があります。
渡すのはモジュール名だけです。
pluginPath = 'path/to/plugin'
sys.path.append(pluginPath)
for plugin in os.listdir(pluginPath):
mod_name = os.path.splitext(plugin)[0]
mod = import_module(mod_name,)
これで、プラグインフォルダにPythonファイルを追加すればインポートしてくれるようになりました。
2: pycが邪魔
インポートしてくれるようになりましたが、
インポートできたらできたで、pyc作られます。読んでほしくありません。
# 前略
for plugin in os.listdir(pluginPath):
split_name = os.path.splitext(plugin)
if split_name[1] == '.pyc':
continue
mod = import_module(split_name[0],)
見つけたプラグイン分だけボタンを増やす
あとは見つけた分だけボタンを配置します。
plugin.py の仕様
仕様というほどでもありませんが、
プラグインの機能を利用するための関数をあらかじめお約束しておきます。
exec
とか doIt
とか run
とかが考えられます。
また、ボタンに記載するラベルもモジュールに持たせておきましょう。
LABEL = 'create poly sphere'
"""
some your scripts...
"""
def exec():
pass
# or
def doIt():
pass
# or
def run():
pass
#-----------------------------------------------------------------------------
# EOF
#-----------------------------------------------------------------------------
module_name.exec
(など)をボタンにconnectします
ボタンへconnect
QPushButton
をつくり、.clicked.connect
にさっき決めた実行用関数を渡します。
btn = QtGui.QPushButton( mod.LABEL )
btn.clicked.connect(mod.exec)
これを、モジュール読んでるfor文に加えます。
まとめ
import os
import sys
from PySide import QtCore, QtGui
from importlib import import_module
pluginPath = 'path/to/plugin'
sys.path.append(pluginPath)
for plugin in os.listdir(pluginPath):
split_name = os.path.splitext(plugin)
if split_name[1] == '.pyc':
continue
mod = import_module(split_name[0],)
btn = QtGui.QPushButton( mod.LABEL )
btn.clicked.connect(mod.exec)
こういう感じのをGUIつくってるスクリプトのどこかにいい具合にいれます
結局一番時間かかったのは
import_moduleに絶対パス渡そうとして「通らないなー」って唸ってたあたり
とpluginを pluing とタイポしてたあたり でした…。
ドキュメントよく読もう!
GUIの部分についてはこちらもどうぞ
- 【補完】[PySide] QtDesignerで遊ぼう
http://qiita.com/it_ks/items/449b7418e83956ecdc8c
参考?