2016-06-14 49 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並返回。

你爲什麼不嘗試呢?