告诉__import__在哪里看 - 我是否坚持使用sys.path?

Kar*_*tel 6 python

我有一个纯Python的项目和一个基本的插件系统:你编写一个模块来定义一个具有特定接口和名称的类,程序导入模块,然后根据需要实例化该类.

目前,插件都来自特定文件夹(主.py文件所在的子目录).我希望能够将它们放在磁盘上的其他位置,并指示程序在特定位置查找插件.对于一次性动态导入,我能以比修改更简洁的方式执行此操作sys.path吗?我不想污染这种全球性的.

相关:我可以依靠sys.path[0]成为脚本的路径,即使它与当前工作目录(os.getcwd())不同吗?

编辑:我忘了提 - 我希望能够从几个不同的文件夹中获取插件,用户指定插件文件夹的路径.目前,这些文件夹中的每一个都被设置为一个包(带有__init__.py); 如果它导致问题,我可以简单地废弃它.

Ery*_*Sun 6

这可能看起来很奇怪,但您可以修改模块的__path__变量然后从中导入.那你就不会搞乱sys.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)
Run Code Online (Sandbox Code Playgroud)

创建动态模块后,可以像以前一样加载插件,无论是使用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()
Run Code Online (Sandbox Code Playgroud)

插件/ plugins1/myplugin1.py:

def init():
    print('myplugin1')
Run Code Online (Sandbox Code Playgroud)

插件/ plugins2/myplugin2.py:

def init():
    print('myplugin2')
Run Code Online (Sandbox Code Playgroud)

我从来没有使用过它,但它在Python 2和3中都有效.