2013-05-08 63 views
2

我有以下目錄結構的Python:導入文件基於哪些文件用戶想要

+ code 
| 
--+ plugins 
    | 
    -- __init__.py 
    -- test_plugin.py (has a class TestPlugin) 
    -- another_test_plugin.py (has a class AnotherTestPlugin) 
--+ load.py 
--+ __init__.py 

在load.py,我希望能夠僅初始化用戶指定的類。例如,可以說我做類似

$ python load.py -c test_plugin # Should only import test_plugin.py and initialize an object of the TestPlugin class 

我無法嘗試使用「imp」模塊來執行此操作。它一直說「沒有這樣的文件或目錄」。我的理解是,它不知道如何正確理解路徑。有人可以幫我解決這個問題嗎?

+0

你說你嘗試使用'imp'模塊時遇到問題,但是你到底嘗試了哪些代碼?你有什麼麻煩?什麼部分的教程/文檔不瞭解? stackoverflow不是其他人爲你寫代碼的地方! – zmo 2013-05-08 10:08:50

+0

你有看看http://stackoverflow.com/questions/10675054/how-to-import-the-module-in-python? – zmo 2013-05-08 10:10:14

+0

我正在嘗試下面的代碼 'import imp' 'import.load_source('TestPlugin','plugins/test_plugin.py')' – 2013-05-08 10:34:44

回答

-7
exec('import ' + sys.argv[2]) 
obj = test_plugin.TestPlugin() 

這裏sys.argv [2]是來自命令行參數的'test_plugin'字符串。

編輯:另一種方法來避免使用EXEC:

import importlib 
mod = importlib.import_module(sys.argv[2]) 
+5

如果'sys.argv [2]'是'os; os.system(「邪惡命令」)'? – Bakuriu 2013-05-08 10:43:10

+1

'exec','eval'就像功能是邪惡的,永遠不會被使用。 – zmo 2013-05-08 10:47:48

0

OK,你的問題是路徑相關的問題。你期望腳本運行在load.py所在的目錄下,而不是這種情況。

你必須做的是一樣的東西:

import imp, os, plugins 

path = os.path.dirname(plugins.__file__) 
imp.load_source('TestPlugin', os.path.join(path, 'test_plugin.py') 

其中插件是包含所有插件模塊(即剛好空__init__.py),這將有助於你得到的完整路徑插件模塊文件。

+0

謝謝,沒有注意到我犯了這個錯字:-) – zmo 2013-05-08 11:39:03

0

另一種解決辦法,如果你想要一個「插件」搜索工具:

import imp, os 
import glob 

def load_plugins(path): 
    """ 
    Assuming `path` is the only directory in which you store your plugins, 
    and assuming each name follows the syntax: 
    plugin_file.py -> PluginFile 
    Please note that we don't import files starting with an underscore. 

    """ 
    plugins = {} 
    plugin_files = glob.glob(path + os.sep + r'[!_]*.py') 
    for plugin_path in plugin_files: 
    module_name, ext = os.path.splitext(plugin_path) 
    module_name = os.path.basename(module_name) 
    class_name = module_name.title().replace('_', '') 
    loaded_module = imp.load_source(class_name, plugin_path) # we import the plugin 
    plugins[module_name] = getattr(loaded_module, class_name) 
    return plugins 

plugins = load_plugins(your_path_here) 
plugin_name = sys.argv[3] 
plugin = plugins.get(plugin_name) 
if not plugin: 
    # manage a not existing plugin 
else: 
    plugin_instance = plugin() # creates an instance of your plugin 

這樣,你也可以通過更改鍵指定不同的名稱,例如,「test_plugins」 =>「TP」。你不必初始化你的插件,但是當你想在運行時加載你的插件時,你仍然可以運行這個函數。

+0

如果用戶編寫了自己的插件並且想要加載它,該怎麼辦?主程序無法對其名稱進行硬編碼,因此插件的動態發現和*動態導入是必要的。 – Bakuriu 2013-05-08 11:44:27

+0

是的,這並不難。 – Markon 2013-05-08 12:49:40