由import_module加载时从模块引用python文件

时间:2016-12-09 10:10:25

标签: python python-3.x python-import importerror

我想使用importlib中的import_module导入模块。当我这样做时,找不到我从模块引用的文件。如果我通常从python shell导入我的模块(不使用main.py)它按预期工作。此外,如果我将MyModule.py的路径添加到sys.path它可以工作,但据我所知,我不应该这样做(在下面的代码中注释掉)。

如何通过import_module加载模块时,如何加载我的引用文件?

我有以下文件结构

main.py
  subfolders
    folder1
      __init__.py
      MyModule.py
      hello.py

main.py

的内容
from importlib import import_module

modulename = 'subfolders.folder1.MyModule'
print("Import module ", modulename)
module = import_module(modulename)
m_instance = module.MyModule()

m_instance.module_hello()

MyModule.py

的内容
#This is the solution that works but feels wrong
#import os, sys
#sys.path.append(os.path.dirname(__file__))

from hello import hello_world

class MyModule(object):
    def __init__(self):
        print("Init MyModule")

    def module_hello(self):
        hello_world()

hello.py

的内容
def hello_world():
    print("Hello World!")

当我跑步时,我得到:

c:\git\PythonImportTest>python main.py
Import module  subfolders.folder1.MyModule
Traceback (most recent call last):
  File "main.py", line 5, in <module>
    module = import_module(modulename)
  File "C:\Miniconda3\lib\importlib\__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 986, in _gcd_import
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 673, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 665, in exec_module
  File "<frozen importlib._bootstrap>", line 222, in _call_with_frames_removed
  File "c:\git\PythonImportTest\subfolders\folder1\MyModule.py", line 5, in <module>
    from hello import hello_world
ImportError: No module named 'hello'

2 个答案:

答案 0 :(得分:2)

首先,您需要在subfolders目录中放置一个空的__init__.py。其次,您需要通过绝对导入或相对导入来导入hello模块。

绝对导入:

from subfolders.folder1.hello import hello_world

相对导入:

from .hello import hello_world

您现在的方式是在顶级包中找到hello.py(main.py所在的位置)。因为在那里找不到你的错误。

关于Python3中相对导入的说明

您可以从Python2切换到Python3,这就是使用隐式相对导入时遇到麻烦的原因。正如PEP404所说:

  

在Python 3中,包中的隐式相对导入不再存在   可用 - 仅限绝对导入和显式相对导入   支持的。此外,星级导入(例如来自x import *)仅是   在模块级代码中允许。

意味着您的代码应该适用于Python2,但对于Python3,您必须使用上述选项之一。另见:Changes in import statement python3

答案 1 :(得分:1)

您的代码存在的问题是子文件夹是文件夹而不是包。如果您使用的是import_module,则只能在包中搜索子包。

解决方案: 在子文件夹文件夹中创建 init .py并在那里导入folder1。