2

我有以下目录结构

+ 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”模块时遇到了麻烦。它一直说“没有这样的文件或目录”。我的理解是它在某种程度上没有正确理解路径。有人可以帮我解决这个问题吗?

4

3 回答 3

0

好的,您的问题是与路径相关的问题。您希望脚本在与 load.py 所在的目录相同的目录中运行,但情况并非如此。

你必须做的是这样的:

import imp, os, plugins

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

其中 plugins 是包含所有插件的模块(即只是空的__init__.py),它将帮助您获得插件模块文件的完整路径。

于 2013-05-08T10:50:38.273 回答
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'。你不必初始化你的插件,但你仍然可以在运行时加载你的插件时运行这个函数。

于 2013-05-08T10:57:59.120 回答
-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])
于 2013-05-08T10:13:07.543 回答