【问题标题】:Python nested subpackage doesn't import when running tests运行测试时不导入 Python 嵌套子包
【发布时间】:2018-03-30 08:23:53
【问题描述】:

我有一个这样的文件夹结构:

api
-- test
    -- test_api.py
    -- __init__.py
-- api
    -- api.py
    -- __init__.py
    -- sub
        -- sub.py
        -- __init__.py

sub.py:

Base = 'base'

api.py:

from sub.sub import Base

def stuff_to_test(): 通过

test_api.py:

from api.api import stuff_to_test

def test_stuff_to_test():
    stuff_to_test()

我在目录api 中。 我跑pytest

==================================== ERRORS ====================================
______________________ ERROR collecting tests/test_api.py ______________________
ImportError while importing test module '/<somepath>/api/tests/test_api.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
tests/test_api.py:1: in <module>
    from ..api.api import stuff_to_test
api/__init__.py:1: in <module>
    from . import api
api/api.py:1: in <module>
    from sub.sub import Base
E   ImportError: No module named 'sub'
!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!
=========================== 1 error in 0.08 seconds ============================

如果我运行 python 解释器并从 test_api.py 导入内容,也会发生同样的情况:

>>> from tests.test_api import *
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/<somepath>/api/tests/test_api.py", line 1, in <module>
    from api.api import stuff_to_test
  File "/<somepath>/api/api/__init__.py", line 1, in <module>
    from . import api
  File "/<somepath>/api/api/api.py", line 1, in <module>
    from sub.sub import Base
ImportError: No module named 'sub'

我的第一个想法是在api.py relative 中进行导入:

from .sub.sub import Base

这样测试运行良好。 但是如果我运行 python api/api.py 我会得到这个错误:

Traceback (most recent call last):
  File "api/api.py", line 1, in <module>
    from .sub.sub import Base
SystemError: Parent module '' not loaded, cannot perform relative import

我怎样才能让它运行测试和应用程序运行?

【问题讨论】:

    标签: python pytest


    【解决方案1】:

    我通过将以下内容添加到 test.__init__.py 解决了它

    project_path = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
    api_path= os.path.join(project_path, 'api')
    sys.path.append(api_path)
    

    【讨论】:

    • 对于子模块,我建议在 api.py 中使用from .sub.sub import Base 或至少使用绝对的from api.sub.sub import Base
    【解决方案2】:

    在 python 中,有两种方法可以导入模块,使用相对路径或使用绝对路径。 当您编写 from sub.sub import Base 时,您正在执行绝对路径导入,对于相对路径导入,请编写 from .sub.sub import Base

    绝对路径导入在 PYTHONPATH 中查找以找到导入的起点,因此您应该写 from api.sub.sub import Base

    欲了解更多信息:Absolute vs. explicit relative import of Python module

    【讨论】:

    • 没有回答问题,抱歉
    猜你喜欢
    • 1970-01-01
    • 2011-06-13
    • 2011-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-30
    • 2020-10-14
    相关资源
    最近更新 更多