大家好
我正在嘗試使用Python(2.7.6)建立一個“插件”系統。我有一個類,它在自定義硬體闆上實作基本操作(使用C++共享庫),我希望開發人員能夠使用某種插件系統來擴充這個類的功能。由于各種原因,所有功能都應該在同一級别上可用(例如,一個類執行個體),是以所有的函數調用,無論是顯式實作還是從插件導入,都應該可以從board執行個體調用。在
此外,這些插件中的函數需要使用調用類中定義的函數。例如,一個通道化插件需要使用在導入它的Board類中實作的讀寫調用。我從插件的抽象基類開始,如下所示:class FirmwareBlock(object):
""" Abstract super class which must be used to implement firmware
block plugins to be used with the access layer """
def __init__(self):
""" Class initialiser """
# Define class as an abstract class
__metaclass__ = ABCMeta
@abstractmethod
def initialise(self):
""" Abstract method where all firmware block initialisation should be performed """
pass
@abstractmethod
def status_check(self):
""" Abstract method where all status checks should be performed """
pass
@abstractmethod
def clean_up(self):
""" Abstract method where all cleaning up should be performed when unloading firmware """
pass
此類中定義的函數必須由所有子類實作。反過來,子類可以實作它們自己的特定函數,這些函數必須包含在board類中,例如:
^{pr2}$
然後,board(calling)類應該能夠加載子產品,檢查自定義函數并包裝它們,以便可以直接從中調用它們。這就是我現在所擁有的:def loadPlugin(self, plugin):
# Check if module is available
if plugin not in self._availablePlugins:
print "Module %s is not available" % plugin
return Error.Failure
# Get list of class methods and remove those availale in superclass
methods = [name for name, mtype in
inspect.getmembers(eval(plugin), predicate=inspect.ismethod)
if name not in
[a for a, b in inspect.getmembers(FirmwareBlock, predicate=inspect.ismethod)] ]
# Create plugin instances
instance = globals()[plugin]
self.__dict__[plugin] = instance
# Import plugins function into this class
for method in methods:
# Link class method to function pointer
self.__dict__[method] = getattr(instance, method)
這應該允許我調用插件方法,但是插件不能通路闆本身定義的函數。當然,當執行個體化類時,我可以将board的執行個體傳遞給init,但是這将插件與board類緊密地耦合在一起。我想知道是否有更好的方法來實作這一點(例如,提取方法并将其直接附加到board類,假設沒有使用執行個體成員)