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

2024-05-15 09:54:18 发布

您现在位置:Python中文网/ 问答频道 /正文

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

结构如下:

project_folder/
    project/
        __init__.py
        __main__.py
    plugins/
        __init__.py
        plugin1/
            __init__.py
            ...
        plugin2/
            __init__.py
            ...

我使用此函数加载模块:

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)

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

failed to load module /path/to/plugins/plugin1 --> Parent module 'plugin1' not loaded, cannot perform relative import

我做错什么了?


Tags: 模块topathnamefrompyimportproject
3条回答

我们如何在importlib的官方文档中看到:

importlib.import_module(name, package=None) Import a module. The name argument specifies what module to import in absolute or relative terms (e.g. either pkg.mod or ..mod). If the name is specified in relative terms, then the package argument must be specified to the package which is to act as the anchor for resolving the package name (e.g. import_module('..mod', 'pkg.subpkg') will import pkg.mod). The specified module will be inserted into sys.modules and returned.

你为什么不试试呢?

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

import sys
import os
sys.path.append(os.path.dirname(os.path.realpath(__file__))+'/..')

这会将project_文件夹添加到sys.path,从而允许import语句查找插件模块。

我通过大量的谷歌搜索,终于解决了我自己的问题。原来我需要使用相对路径导入:

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

相关问题 更多 >