2013-12-19 51 views
1

我的項目必須是可擴展的,我有很多與網上查找的東西相同的接口腳本。我使用__import__之前但是,這並不讓我把我的「插件」上的專用目錄:Python從子目錄3進口

root/ 
    main.py 
    plugins/ 
     [...] 

所以我的問題是:有沒有辦法單獨從該子目錄導入模塊?我猜導入庫,但我很迷失在Python模塊加載過程是如何工作的?我想要做的是這樣的:

for pluginname in plugins: 
    plugin = somekindofimport("plugins/{name}".format(name=pluginname)) 
    plugin.unififedinterface() 

此外,作爲一個側面的問題,在上午方式我試圖實現可擴展性是一個好方法?

我在python3.3在路徑中的條款

回答

3

停止思考,並開始在包裝方面的思考。請閱讀教程中的Packages,如果需要更多詳細信息,請參閱The import system

但其基本思路是這樣的:

創建一個文件名plugins/__init__.py。它可以是空的;這足以讓plugins。這意味着你可以從該包中導入模塊:

import plugins.plugin 

那麼,你如何動態地做到這一點?這就是importlib的用途。 (您也可以使用__import__在這裏,但它的彈性較差,而且在不平凡的情況下的可讀性,所以除非你需要預先3.3的兼容性,不要。)

plugin = importlib.import_module('plugins.{name}'.format(name=pluginname)) 

它很可能是吸塵器import plugins獲取軟件包,然後使用該軟件包內的相關導入,如import_module文檔中的示例所示。

這也意味着Python的需要照顧的.pyc文件創建和緩存等

這也意味着以後可以擴大plugins是一個「命名包」,它可以在多個目錄中被分割像/usr/share/myapp/plugins股票插件,/etc/myapp/plugins站點插件和~/myapp/plugins用戶特定的插件。


如果你真的想從一個目錄不是一個包導入,您可以創建一個模塊加載器並使用它,但是這是一個整個工作很多沒有實際的好處。 (這其實並不難在3.3(SourceLoader和朋友將做最適合你的工作),但你會發現幾乎沒有例子在那裏來指導你;相反,你會發現的2.6-3.2方式的例子,或2.0-2.5方式,這兩者是)。此外,它意味着如果有人創建了一個名爲,比如說,gzip插件,你可以最終阻斷STDLIB gzip模塊插件。 (如果gzip插件嘗試使用gzip STDLIB模塊,因爲它有可能將那特別好玩的...)如果插件最終被命名爲plugins.gzip,沒有任何問題。


此外,作爲一個側面的問題,順便我是試圖實現的可擴展性是一個好辦法?

只要你只想支持3.3+,是的,我認爲這是一個很好的解決方案。

在3.3之前,使用插件包是一個問題。人們已經想出了各種不同的插件系統 - 在一種情況下,動態創建模塊對象並將其插入到它們中。如果您需要處理這個問題,我會建議查看帶有插件的現有Python應用程序(例如MusicBrainz Picard)以獲得不同的想法。

+0

感謝您的示例!我真的無法弄清楚importlib是如何工作的。 – gcq