【问题标题】:Python: Importing files based on which files the user wants [duplicate]Python:根据用户想要的文件导入文件[重复]
【发布时间】:2013-05-02 12:26:36
【问题描述】:

我有以下目录结构

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

【问题讨论】:

  • 您说您在尝试使用“imp”模块时遇到了问题,但到目前为止您尝试了哪些代码?你有什么问题吗?您不了解教程/文档的哪一部分? stackoverflow 不是别人为你写代码的地方!
  • 我正在尝试以下代码import impimport.load_source('TestPlugin', 'plugins/test_plugin.py')
  • 我打错了import.load_source。应该是imp.load_source
  • ... 当您:1) 没有显示您正在使用的代码和 2) 没有显示完整的回溯时,我们应该如何知道出了什么问题> 你得到了吗?

标签: python


【解决方案1】:
exec('import ' + sys.argv[2])
obj = test_plugin.TestPlugin()

这里 sys.argv[2] 是来自命令行参数的“test_plugin”字符串。

编辑:另一种避免使用 exec 的方法:

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

【讨论】:

  • 如果sys.argv[2]os; os.system("evil command") 怎么办?
  • exec, eval 之类的函数是邪恶的,永远不要使用。
【解决方案2】:

另一个解决方案,如果你想要一个“插件”发现工具:

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'。你不必初始化你的插件,但你仍然可以在运行时加载你的插件时运行这个函数。

【讨论】:

  • 如果用户编写了自己的插件并想加载它怎么办?主程序不能硬编码它的名字,因此插件的动态发现和动态导入是必要的。
  • 是的,做到这一点并不难。
【解决方案3】:

好的,你的问题是路径相关的问题。您希望脚本在 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),它将帮助您获得插件模块文件的完整路径。

【讨论】:

  • 谢谢,没注意到我打错字了 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-17
  • 1970-01-01
  • 2019-08-03
  • 2019-12-03
  • 2013-06-05
  • 2016-07-08
  • 2019-02-23
相关资源
最近更新 更多