告诉__import__在哪里查找 - 我被sys.path限制了吗?
我有一个用纯Python写的项目,里面有一个简单的插件系统:你需要写一个模块,这个模块里定义一个特定接口和名称的类,然后程序会导入这个模块,并根据需要实例化这个类。
现在,这些插件都来自一个特定的文件夹(就是主.py文件所在的子目录)。我希望能够把插件放在其他地方,并告诉程序去特定的位置寻找插件。我可以用比修改sys.path
更简单的方法来实现一次性的动态导入吗?我不想弄得全局环境一团糟。
相关问题:我能指望sys.path[0]
是脚本的路径吗,即使这个路径和当前工作目录(os.getcwd()
)不同?
补充说明:我忘了提,我希望能够从多个不同的文件夹获取插件,用户可以指定插件文件夹的路径。目前,这些文件夹都是作为包设置的(里面有一个__init__.py
文件);如果这造成了问题,我可以轻松去掉这个设置。
1 个回答
6
这听起来可能有点奇怪,但你可以修改一个模块的 __path__
变量,然后从这个模块导入内容。这样的话,你就不会影响到系统路径中的全局导入空间。
补充说明:如果这些目录是在运行时加载的,那么你就不需要一个 plugins.py 文件来存储它们。你可以动态创建这个模块:
main.py:
#create the plugins module (pseudo-package)
import sys, os
sys.modules['plugins'] = plugins = type(sys)('plugins')
plugins.__path__ = []
for plugin_dir in ['plugins1', 'plugins2']:
path = os.path.join(sys.path[0], 'addons', plugin_dir)
plugins.__path__.append(path)
在创建了动态模块后,你可以像之前一样加载插件,可以使用 import_module
或 __import__
:
from importlib import import_module
myplugins = []
for plugin in ['myplugin1', 'myplugin2']:
myplugins.append(import_module('plugins.' + plugin))
myplugins[-1].init()
##or using __import__:
myplugins = []
for plugin in ['myplugin1', 'myplugin2']:
myplugins.append(getattr(__import__('plugins.' + plugin), plugin))
myplugins[-1].init()
addons/plugins1/myplugin1.py:
def init():
print('myplugin1')
addons/plugins2/myplugin2.py:
def init():
print('myplugin2')
我自己从来没有用过这个,但它在 Python 2 和 3 中都能正常工作。