Proper way to dynamically import a module with relative imports?

时间:2022-01-28 03:32:25

I need to dynamically import modules into my project from another package.

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

The structure is like:

结构如下:

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

I made this function to load a module:

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

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)

It works, unless the module uses relative imports:

它有效,除非模块使用相对导入:

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

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

What am I doing wrong?

我究竟做错了什么?

3 个解决方案

#1


10  

I managed to solve my own issue after a LOT of googling. Turns out I needed to import using relative paths:

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

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

#2


3  

I had a similar problem not long ago. I added the path of the project folder to the sys.path using the module's absolute path like this:

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

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

This adds the project_folder to the sys.path thus allowing the import statement to find the plugin modules.

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

#3


-1  

How we can see in the official doc of importlib:

我们如何在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.

importlib.import_module(name,package = None)导入模块。 name参数指定以绝对或相对术语导入的模块(例如pkg.mod或..mod)。如果名称是以相对术语指定的,则必须将package参数指定给作为解析包名称的锚点的包(例如import_module('.. mod','pkg.subpkg')将导入pkg的.mod)。指定的模块将插入sys.modules并返回。

Why don't you try it?

你为什么不试试呢?

#1


10  

I managed to solve my own issue after a LOT of googling. Turns out I needed to import using relative paths:

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

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

#2


3  

I had a similar problem not long ago. I added the path of the project folder to the sys.path using the module's absolute path like this:

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

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

This adds the project_folder to the sys.path thus allowing the import statement to find the plugin modules.

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

#3


-1  

How we can see in the official doc of importlib:

我们如何在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.

importlib.import_module(name,package = None)导入模块。 name参数指定以绝对或相对术语导入的模块(例如pkg.mod或..mod)。如果名称是以相对术语指定的,则必须将package参数指定给作为解析包名称的锚点的包(例如import_module('.. mod','pkg.subpkg')将导入pkg的.mod)。指定的模块将插入sys.modules并返回。

Why don't you try it?

你为什么不试试呢?