Python 用于测试具有附加依赖项的模块的导入

Python imports for testing modules with additional dependencies

我想将我的测试与我的包代码放在一个单独的文件夹中,这样我可以从我的项目的顶级目录 运行 python sample/run.pypython tests/test_run.py,并且让他们都正确解决所有导入问题。

我的目录结构是这样的:

sample/
   __init__.py
   helper.py
   run.py
tests/
   context.py
   test_run.py

我知道有很多方法可以实现这一点,正如这里所讨论的:Python imports for tests using nose - what is best practice for imports of modules above current package

但是,当我尝试 运行 python tests/test_run.py 时,我得到 ModuleNotFoundError for 'helper',因为 'sample/run.py' 导入'sample/helper.py'.

特别是,我试图遵循使用

显式修改路径的约定(在 Hitchhiker's Guide to Python 中建议)
import os, sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

因此,我有一个空白 sample/__init__.py,以及以下代码文件。

sample/run.py:

from helper import helper_fn
def run():
    helper_fn(5)
    return 'foo'
if __name__ == '__main__':
    run()

sample/helper.py:

def helper_fn(N):
    print(list(range(N)))

tests/context.py:

import os, sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

import sample

tests/test_run.py:

from context import sample
from sample import run

assert run.run() == 'foo'

所以我有两个问题:

  1. 为什么 Python 找不到 'helper' 模块?
  2. 我该如何解决才能从顶级目录中 运行 sample/run.pytests/test_run.py

已编辑:

要使sample/run.pytests/test_run.py都起作用,您应该将sample目录的路径添加到python路径中。所以,你的 tests/context.py 应该是

import os, sys
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../sample')))


import sample

此更改将使 Python 知道 helper 模块的路径。


sample/run.py 应该是:

  from .helper import helper_fn
  def run():
     helper_fn(5)
     return 'foo'
  if __name__ == '__main__':
     run()

包内的隐式相对导入在 Python 中不可用 3. 请检查以下内容:

The import system has been updated to fully implement the second phase of PEP 302. There is no longer any implicit import machinery - the full import system is exposed through sys.meta_path. In addition, native namespace package support has been implemented (see PEP 420). link

documentation 可能有助于理解包内引用。