2016-06-14 54 views
4

我需要从另一个包中动态地将模块导入到我的项目中。使用相对导入动态导入模块的正确方法?

的结构是这样的:

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) 

它的工作原理,除非该模块使用相对导入:

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

我在做什么错?

回答

9

大量的Google搜索后,我设法解决了我自己的问题。原来我需要使用相对路径导入:

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

如何从'plugins.config import *',使用** import_module **或** __ import __ **? –

0

不久前我有类似的问题。

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

这增加了project_folder,从而允许import语句找到插件模块的sys.path:我使用模块的绝对路径这样加入到sys.path中的项目文件夹的路径。

+0

很遗憾,这对我不起作用。在我调用'load_module'之前,我将它添加到我的'project/__ main __。py'文件的开头。那是放正确的地方吗? – user3638162

+0

我忘了提及它使用Python3。您可以尝试将__init__.py添加到您的项目文件夹中。 –

+0

对不起,降价搞砸了我的评论。 它应该是project_folder中另一个'__init __。py'文件。 –

-1

我们如何能在importlib官方文档看:

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

你为什么不尝试呢?