停止思考,並開始在包裝方面的思考。請閱讀教程中的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)以獲得不同的想法。
感謝您的示例!我真的無法弄清楚importlib是如何工作的。 – gcq