2010-07-15 71 views
6

我的Python應用程序是這樣構建的,即某些功能可用作插件。目前插件體系結構非常簡單:我有一個包含一些python模塊的插件文件夾/包。我加載相關插件如下:py2exe中未編譯的python插件的動態加載編譯代碼

plugin_name = blablabla 
try: 
    module = __import__(plugin_name, fromlist='do_something') 
except ImportError: 
    #some error handling ... 

,然後執行:

try: 
    loans = module.do_something(id_t, pin_t) 
except xxx: 
    # error handling 

我編譯應用程序到Windows二進制使用py2exe。 這工作正常,除了所有插件(並且必須)包含在二進制文件中的事實。這不是很實用,因爲對於每個新插件,我必須重新編譯併發布我的應用程序的新版本。如果新的插件(即python文件)可以被複制到某個應用程序插件文件夾中,並且文件代碼中的Python代碼可以被我的應用程序即時解釋,那將會更好。

這樣做的最佳方法是什麼?

(我雖然讀選定的插件文件的每一行,並應用exec statement它。但有可能是更好的方式...)

回答

0

我建議你使用通過pkg_resources entry_points功能(從setuptools的/分發)來實現插件發現和實例化:首先,這是一種標準的方式;其次,它不會遇到你提到AFAIK的問題。所有你需要做的擴展應用程序是將一些插件打包成一個聲明某些入口點的蛋(一個蛋可能會聲明多個插件),並且當你將這個蛋安裝到你的python發行版時,它聲明的所有插件都可以自動由您的應用程序發現。您也可以將您的應用程序和「工廠」插件打包到同一個蛋中,這非常方便。

+1

感謝您的回答。但是這不需要有人在他的電腦上安裝python嗎? (我提出的解決方案將需要現在我想到的) – Rabarberski 2010-07-16 15:11:23

+0

你說得對,應用程序和外部插件應該是相同的python安裝。我同意這很煩人。 – 2010-07-20 16:50:57

0

我不確定你必須將插件文件放入zip庫。 這可能是因爲您正在使用py2exe打包腳本​​的默認設置。

你可以嘗試使用compressed = False(如py2exe ListOfOptions所述),這將消除由py2exe生成的library.zip,並且可能允許你訪問python模塊(你的插件是python模塊,我假設,來自import)以「正常」的方式,而不是被迫將它們打包到您的zip或二進制文件中。

1

PyInstaller還允許您導入外部文件。如果通過應用程序運行它,它將不會將這些文件打包到可執行文件中。然後你必須確保路徑是正確的(也就是說,你的應用程序可以在正確的目錄中找到磁盤上的模塊),並且一切都應該工作。

2

如果你不介意這個插件會被釋放爲.py文件,你可以做如下的事情。將所有插件放在「插件」子目錄下,並創建一個空的「__init__.py」。在運行時,它會將該包與該目錄中的所有模塊一起導入。檢查Dive In Python的解釋...但這是我最終最終使用。

def load_plugin(path): 
    import imp 
    """Load plugin from directory and return list of modules""" 
    files = os.listdir(path) 
    test = re.compile(".py$", re.IGNORECASE)   
    files = filter(test.search, files)      
    filenameToModuleName = lambda f: os.path.splitext(f)[0] 
    moduleNames = sorted(map(filenameToModuleName, files)) 
    f, filename, desc = imp.find_module('plugin') 
    plugin = imp.load_module('plugin', f, filename, desc) 
    modules = [] 

    #print moduleNames 
    for m in moduleNames: 
     # skip any files starting with '__', such as __init__.py 
     if m.startswith('__'): 
      continue 
     try: 
      f, filename, desc = imp.find_module(m, plugin.__path__) 
      modules.append(imp.load_module(m, f, filename, desc)) 
     except ImportError: 
      continue 
    return modules 
+0

這些模塊是否可以加載編譯版本中存在的類? – 2013-03-01 13:06:49

0

我發現如何使用pyinstaller導入外部模塊(在編譯的可執行文件的頂部,在運行時)。 它認爲,最初,可執行文件的路徑被自動添加到sys.path中,但出於安全原因,他們在某個時候刪除了該文件。 重新啓用此功能,使用方法:

sys.path.append(os.path.dirname(sys.executable)) 

這將使進口的.py坐作爲可執行文件相同的路徑文件。 您可以將此行添加到運行時鉤子或主應用程序。