2010年12月1日水曜日

PythonでPluginローダを書いてみた

http://d.hatena.ne.jp/jkani4/20080105
参考サイトでプラグイン管理モジュールを公開されているのをみて、
自分流にリメークしてみた。

違いは、シンプルにした点。
オリジナルは必須関数と推奨関数2つ登録できるのに対して、
リメークしたものは必須関数限定にしてある。
それと呼び出し用クラスを介してプラグインモジュールを呼び出せるようにした。

使い方はこんな感じ
[手順]
#プラグインローダを生成
pl = PluginLoader("./plugins")

#使いたいプラグインモジュール名を指定して関数を呼び出す。
func = pl.get_plugin_module("plugin_name")
func.get_name()

これでスレッド処理に対応させれば満足。

# -*- coding: utf-8 -*-

import os
import sys
import inspect

#targetDirパス内のプラグインファイルを読み込む
class PluginLoader:
 def __init__(self, targetDir):
  self.plugFuncNames = ['run', 'test', 'get_name', 'get_ver']
  self.pluginDict = {}
  sys.path.append(targetDir)
  # プラグイン検索&登録
  for item in os.listdir(targetDir):
   modname = inspect.getmodulename(item)
   if modname not in self.pluginDict.keys():
    self.import_plugin(modname)

 def import_plugin(self, modName):
  cnt = 0
  funcDict = {}
  # プラグイン関数検索
  funcList = inspect.getmembers(__import__(modName), inspect.isfunction)
  funcNames = [item[0] for item in funcList]
  for fname in self.plugFuncNames:
   if fname in funcNames:
    cnt = cnt + 1
  # プラグイン関数登録
  if cnt == len(self.plugFuncNames):
   for name, funcObj in funcList:
    if name in self.plugFuncNames:
     funcDict[name] = funcObj
   self.pluginDict[modName] = funcDict
   print "plugin registered:%s" % modName

 def get_plugin_count(self):
  return len(self.pluginDict)
 def get_plugin_list(self):
  return self.pluginDict.keys()
 def get_plugin_module(self, modName):
  return PluginFunc(self.pluginDict[modName])
 
#プラグインモジュールを呼び出すクラス
class PluginFunc:
 def __init__(self, ptr):
  self.plugin_ptr = ptr
 def run(self):
  return self.plugin_ptr['run']()
 def test(self):
  return self.plugin_ptr['test']()
 def get_name(self):
  return self.plugin_ptr['get_name']()
 def get_ver(self):
  return self.plugin_ptr['get_ver']()

#動作確認用
if __name__ == '__main__':
 pl = PluginLoader("./plugins")
 print 'plugin module count : %d' % pl.get_plugin_count()
 print '------------------------'
 for name in pl.get_plugin_list():
  print "plugin name: " + name
  func = pl.get_plugin_module(name)
  print func.get_name()
  print func.get_ver()
  print func.run()
  print func.test()
  print '------------------------'

プラグインの雛形
# -*- coding: utf-8 -*-

def run():
 return "run"
 
def get_name():
 return "get_name"

def get_ver():
 return "get_version"

def test():
 return "test"

0 件のコメント:

Androider