使用相对导入动态导入模块的正确方法?

use*_*162 6 python import dynamic

我需要从另一个包中动态地将模块导入到我的项目中.

结构如下:

project_folder/
    project/
        __init__.py
        __main__.py
    plugins/
        __init__.py
        plugin1/
            __init__.py
            ...
        plugin2/
            __init__.py
            ...
Run Code Online (Sandbox Code Playgroud)

我做了这个函数来加载一个模块:

import os

from importlib.util import spec_from_file_location, module_from_spec


def load_module(path, name=""):
    """ loads a module by path """
    try:
        name = name if name != "" else path.split(os.sep)[-1]  # take the module name by default
        spec = spec_from_file_location(name, os.path.join(path, "__init__.py"))
        plugin_module = module_from_spec(spec)
        spec.loader.exec_module(plugin_module)
        return plugin_module
    except Exception as e:
        print("failed to load module", path, "-->", e)
Run Code Online (Sandbox Code Playgroud)

除非模块使用相对导入,否则它可以工作:

无法加载module/path/to/plugins/plugin1 - >父模块'plugin1'未加载,无法执行相对导入

我究竟做错了什么?

use*_*162 15

经过大量的谷歌搜索,我设法解决了自己的问题.结果我需要使用相对路径导入:

>>> from importlib import import_module
>>> config = import_module("plugins.config")
>>> config
<module 'plugins.config' from '/path/to/plugins/config/__init__.py'>
>>> 
Run Code Online (Sandbox Code Playgroud)


Gáb*_*ete 5

不久前我遇到了类似的问题。我使用模块的绝对路径将项目文件夹的路径添加到 sys.path ,如下所示:

import sys
import os
sys.path.append(os.path.dirname(os.path.realpath(__file__))+'/..')
Run Code Online (Sandbox Code Playgroud)

这会将 project_folder 添加到 sys.path 从而允许 import 语句找到插件模块。