传递导入错误:ModuleNotFoundError:没有名为'...'的模块

时间:2018-03-23 16:10:34

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

我现在很困惑。这是项目树:

project
- source
- - lib
- - - __init__.py
- - - utils.py
- - - stats.py
- test
- - lib
- - - test_stats.py

stats.pyimport utils,如果自己执行stats.py,它确实有效。现在test_stats.pyimport lib.stats但如果在ModuleNotFoundError: No module named 'utils'目录中以PYTHONPATH=source pytest执行,则会导致project错误:

==================================== ERRORS ====================================
___________________ ERROR collecting test/lib/test_stats.py ___________________
ImportError while importing test module '/lib/test_stats.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
test/lib/test_stats.py:40: in <module>
    import lib.stats
source/lib/__init__.py:42: in <module>
    from .stats import Stats
source/lib/stats.py:40: in <module>
    import utils
E   ModuleNotFoundError: No module named 'utils'
!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!
=========================== 1 error in 0.19 seconds ============================

正在发生什么以及如何使用这种目录结构正确执行测试?

PS 我知道(开发模式)pip install ...tox技巧(模块搜索路径),但我想了解它们是否绝对必要要做到这一点,或者我已经在这个简单的设置中假设出了问题。

1 个答案:

答案 0 :(得分:3)

Python 3中的

import utils是绝对导入的,utils中的Python查找模块sys.path

当您将stats.py作为脚本运行时,Python会将目录project/source/lib/添加到sys.path。所以脚本中的import utils可以工作。

但是当你运行test_stats.py时,Python不会将project/source/lib/添加到sys.path。所以import utils不起作用。

克服这种情况的一种方法是使用相对导入:from . import utils。在stats.py中,它表示:不要在与sys.path相同的目录中搜索utils,导入模块stats.py。但是你失去了作为脚本运行stats.py的能力。因此,请将主要代码从stats.py移至lib/以外的单独脚本。

稍微不同的解决方案是将主代码从stats.py移至模块__main__.py并使用python -m lib执行模块(project/source/必须位于sys.path