pytest 的 PATH 问题‘ImportError: 没有名为...的模块’

2024-12-12 08:40:00
admin
原创
91
摘要:问题描述:我使用easy_install在 Mac 上安装了pytest,并开始为项目编写测试,其文件结构如下:repo/ |--app.py |--settings.py |--models.py |--tests/ |--test_app.py py.test在...

问题描述:

我使用easy_install在 Mac 上安装了pytest,并开始为项目编写测试,其文件结构如下:

repo/
   |--app.py
   |--settings.py
   |--models.py
   |--tests/
          |--test_app.py

py.testrepo目录中运行,一切都会按照您预期的方式运行。

但是,当我在 Linux 或 Windows 上尝试执行相同的操作时(两者都安装了 pytest 2.2.3),只要它第一次从我的应用程序路径导入某些内容,它就会发出警报。例如,from app import some_def_in_app

我是否需要编辑我的PATH才能在这些系统上运行py.test ?


解决方案 1:

推荐方法pytest>=7:使用pythonpath设置

最近,pytest添加了一个新的核心插件,支持sys.path通过pythonpath配置值进行修改。因此,解决方案现在变得更加简单,不再需要任何变通方法:

pyproject.toml例子:

[tool.pytest.ini_options]
pythonpath = [
  "."
]

pytest.ini例子:

[pytest]
pythonpath = .

路径条目是相对于 rootdir 计算的,因此在这种情况下.会添加repo目录sys.path

还允许多个路径条目:对于布局

repo/
├── src/
|   └── lib.py
├── app.py
└── tests
     ├── test_app.py
     └── test_lib.py

配置

[tool.pytest.ini_options]
pythonpath = [
  ".", "src",
]

或者

[pytest]
pythonpath = . src

将添加applib模块到sys.path,因此

import app
import lib

都可以。

原始答案(不推荐用于最近的 pytest 版本;仅用于pytest<7):conftest解决方案

侵入性最小的解决方案是conftest.pyrepo/目录中添加一个名为的空文件:

$ touch repo/conftest.py

就是这样。无需编写自定义代码来破坏sys.path或记住拖动PYTHONPATH,或将__init__.py其放入不属于的目录中(不过,python -m pytest按照Apteryx的答案中的建议使用是一个很好的解决方案!)。

之后的项目目录:

repo
├── conftest.py
├── app.py
├── settings.py
├── models.py
└── tests
     └── test_app.py

解释

pytest在测试集合中查找conftest模块来收集自定义钩子和装置,并且为了从它们导入自定义对象,pytest将其父目录添加conftest.pysys.path(在本例中为repo目录)。

其他项目结构

如果您有其他项目结构,请将 放在conftest.py包根目录(包含包但本身不是包,因此不包含__init__.py,例如:

repo
├── conftest.py
├── spam
│   ├── __init__.py
│   ├── bacon.py
│   └── egg.py
├── eggs
│   ├── __init__.py
│   └── sausage.py
└── tests
     ├── test_bacon.py
     └── test_egg.py

src布局

虽然这种方法可以与布局一起使用src(放置conftest.py在目录中src):

repo
├── src
│   ├── conftest.py
│   ├── spam
│   │   ├── __init__.py
│   │   ├── bacon.py
│   │   └── egg.py
│   └── eggs 
│       ├── __init__.py
│       └── sausage.py
└── tests
     ├── test_bacon.py
     └── test_egg.py

请注意,添加srcPYTHONPATH削弱布局的意义和好处src!您最终会测试存储库中的代码,而不是已安装的软件包。如果您需要这样做,也许您src根本不需要目录。

下一步该怎么做

当然,conftest模块不仅仅是一些帮助源代码发现的文件;它是框架的所有项目特定增强功能pytest和测试套件定制发生的地方。在其文档pytest中散布着大量有关conftest模块的信息;从以下开始:本地每个目录插件conftest.py

此外,SO 有一个关于conftest模块的很好的问题:在 py.test 中,conftest.py 文件有什么用?

解决方案 2:

我不确定为什么 py.test 没有在 PYTHONPATH 本身中添加当前目录,但这里有一个解决方法(从存储库的根目录执行):

python -m pytest tests/

它之所以有效是因为 Python 在 PYTHONPATH 中为您添加了当前目录。

解决方案 3:

我也遇到了同样的问题。我通过在目录__init__.py中添加一个空文件解决了这个问题tests

解决方案 4:

cd是的,如果你进入测试目录,源文件夹就不在 Python 的路径中。

您有两个选择:

  1. 手动将路径添加到测试文件。如下所示:

 import sys, os
 myPath = os.path.dirname(os.path.abspath(__file__))
 sys.path.insert(0, myPath + '/../')
  1. 使用环境变量运行测试PYTHONPATH=../

解决方案 5:

pytest以模块形式
运行:python -m pytest tests

例如,当项目层次结构为package/src package/tests并且在测试中从src导入时,就会发生这种情况。作为模块执行将把导入视为绝对的,而不是相对于执行位置的。

解决方案 6:

您可以在项目根目录中使用 PYTHONPATH 运行

PYTHONPATH=. py.test

或者使用 pip install 作为可编辑导入

pip install -e .   # install package using setup.py in editable mode

解决方案 7:

我在 Flask 中遇到了同样的问题。

当我添加:

__init__.py

测试文件夹,问题就消失了:)

应用程序可能无法将文件夹测试识别为模块。

解决方案 8:

我创建这个是为了回答你的问题和我自己的困惑。希望它能有所帮助。注意 py.test 命令行和 tox.ini 中的 PYTHONPATH。

https://github.com/jeffmacdonald/pytest_test

具体来说:您必须告诉 py.test 和 tox 在哪里找到您要包含的模块。

使用 py.test 您可以执行以下操作:

PYTHONPATH=. py.test

使用 tox,将其添加到您的 tox.ini 中:

[testenv]
deps= -r{toxinidir}/requirements.txt
commands=py.test
setenv =
    PYTHONPATH = {toxinidir}

解决方案 9:

__init__.py我通过删除源的父文件夹中的顶层来修复此问题。

解决方案 10:

ConftestImportFailure: ImportError('No module named ...当我意外地将__init__.py文件添加到我的 src 目录(它不应该是一个 Python 包,而只是一个所有源的容器)时,我开始收到奇怪的错误。

解决方案 11:

遗憾的是,这是 Python 中的一个问题...但在我看来,只需添加这个环境变量就是最舒服的方式:

export PYTHONPATH=$PYTHONPATH:.

您可以将此行放入.zshrc或.bashrc文件中。

解决方案 12:

我在学习 Flask 教程时遇到了同样的问题,并在官方 Pytest 文档中找到了答案。这与我(我想还有很多其他人)习惯做事的方式有点不同。

您必须setup.py在项目的根目录中创建一个文件,其中至少包含以下两行:

from setuptools import setup, find_packages
setup(name="PACKAGENAME", packages=find_packages())

其中 PACKAGENAME 是你的应用程序的名称。然后你必须使用 pip 安装它:

pip install -e .

-e标志告诉pip以可编辑或“开发”模式安装软件包。因此下次运行时,pytest它应该会在标准中找到您的应用程序PYTHONPATH

解决方案 13:

我之所以出现此错误,是因为我错误地使用了相对导入。在 OP 示例中,test_app.py 应使用例如导入函数

from repo.app import *

然而,__init__.py 文件大量地分散在文件结构中,这是行不通的,并且会产生 ImportError 错误,除非这些文件和测试文件位于同一目录中。

from app import *

下面是我在我的一个项目中所做的事情的一个例子:

这是我的项目结构:

microbit/
microbit/activity_indicator/activity_indicator.py
microbit/tests/test_activity_indicator.py

为了能够从 test_activity_indicator.py 访问 activity_indicator.py 我需要:

  • 使用正确的相对导入启动 test_activity_indicatory.py:

    from microbit.activity_indicator.activity_indicator import *
  • 将 __init__.py 文件放入整个项目结构中:

    microbit/
    microbit/__init__.py
    microbit/activity_indicator/__init__.py
    microbit/activity_indicator/activity_indicator.py
    microbit/tests/__init__.py
    microbit/tests/test_activity_indicator.py

解决方案 14:

我遇到了类似的问题。pytest无法识别在我工作环境中安装的模块。

我也通过安装pytest到同一个环境中解决了这个问题。

解决方案 15:

此外,如果您pytest在虚拟环境中运行,请确保pytest模块已安装在虚拟环境中。激活虚拟环境并运行pip install pytest

解决方案 16:

对我来说,问题是tests.py由 Django 和tests目录一起产生的。删除tests.py解决了这个问题。

解决方案 17:

根据Dirk Avery 在 Medium 上发表的一篇文章(并得到我的个人经验的支持),如果您在项目中使用虚拟环境,那么您不能使用系统范围的 pytest 安装;您必须在虚拟环境中安装它并使用该安装。

具体来说,如果您在两个地方都安装了它,那么简单地运行pytest命令将不起作用,因为它将使用系统安装。正如其他答案所描述的那样,一个简单的解决方案是运行python -m pytest而不是pytest;这有效,因为它使用环境版本的 pytest。或者,您可以卸载系统版本的 pytest;重新激活虚拟环境后,该pytest命令应该可以工作。

解决方案 18:

我遇到此错误的原因甚至更简单(您甚至可以说微不足道)。我没有安装模块pytest。所以一个简单的操作apt install python-pytest就帮我解决了。

'pytest' 将在 setup.py 中列为测试依赖项。请确保您也安装了测试要求。

解决方案 19:

由于没有人建议这样做,您也可以将路径传递给pytest.ini文件中的测试:

[pytest]
...
testpaths = repo/tests

查看文档:https ://docs.pytest.org/en/6.2.x/customize.html#pytest-ini

Visual Studio Code的副作用:它应该在 UI 中选取单元测试。

解决方案 20:

我的设置

  1. venv在 vs-code 中有一个设置。

  2. vs-code 指向正确的可执行文件。

  3. 甚至pytest.ini设置为:

[pytest]
pythonpath = .
  1. 尝试导出PYTHONPATH但在虚拟环境中却无法工作。

  2. 我的树看起来像:

root
 venv
 __init__.py
 actions
    actions.py
    __init__.py
 tests
    test_actions.py
 pytest.ini
  1. 我在test_actions.py做:

from actions.actions import ActionFetch
  1. 但正在No action module found exception

  2. 虚拟环境也很活跃。

解决方案:我使用以下方法简单运行了测试:

pytest tests --import-mode=append

请参阅https://docs.pytest.org/en/7.1.x/explanation/pythonpath.html#:~:text=%2D%2Dimport%2Dmode%3Dappend

解决方案 21:

我们通过添加以下环境变量解决了该问题。

PYTHONPATH=${PYTHONPATH}:${PWD}/src:${PWD}/test

解决方案 22:

我的解决方案:

conftest.py在目录中创建test包含以下内容的文件:

import os
import sys
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + "/relative/path/to/code/")

这会将感兴趣的文件夹添加到 Python 解释器路径,而无需修改每个测试文件、设置环境变量或弄乱绝对/相对路径。

解决方案 23:

正如Luiz Lezcano Arialdi指出的那样,正确的解决方案是将您的包安装为可编辑包。

由于我正在使用Pipenv,我考虑在他的回答中逐步添加如何使用 Pipenv 将当前路径安装为可食用路径,从而无需任何修改代码或丢失文件即可运行 pytest。

您将需要具有以下最小文件夹结构(文档):

package/
    package/
        __init__.py
        module.py
    tests/
        module_test.py
    setup.py

setup.py主要包含以下最少代码(文档):

import setuptools

setuptools.setup(name='package', # Change to your package name
                 packages=setuptools.find_packages())

然后您只需运行pipenv install --dev -e .,Pipenv 就会将当前路径安装为可编辑包(--dev 标志是可选的)(文档)。

现在您应该可以pytest顺利运行了。

解决方案 24:

如果这个 pytest 错误不是针对您自己的包出现的,而是针对您包的 requirements.txt 中 Git 安装的包出现的,则解决方案是切换到可编辑安装模式。

例如,假设您的包的 requirements.txt 有以下行:

git+https://github.com/foo/bar.git

您可以使用以下内容替换它:

-e git+https://github.com/foo/bar.git#egg=bar

解决方案 25:

如果什么都不起作用,请确保您的 test_module.py 列在正确的 src 目录下。有时它不会ModuleNotFoundError因为模块放错位置或export PYTHONPATH="${PWD}:${PYTHONPATH}"不起作用而给出,而是因为 test_module.py 被放置在 tests 文件夹下的错误目录中。

它应该是一对一的映射关系,递归的,而不是根文件夹应该命名为“tests”,包含测试代码的文件的名称应该以“test_”开头,例如,

./nlu_service/models/transformers.py

./测试/模型/test_transformers.py


这是我的经历。

解决方案 26:

如果您尝试通过 VSCode 的测试运行器运行,除了通过您选择的方法设置 PYTHONPATH 环境之外,还可以尝试settings.json

{
  "python.testing.cwd": "${workspaceFolder}",
  // or an appropriate path to your cwd
}

解决方案 27:

最近,我遇到了一种情况,由于导入错误,src(被测目标代码)中的本地导入会失败。

我们都知道文件根本就找不到。所以我的策略是将包含源的文件夹放在夹具中的sys.path中。

我的文件夹结构如下:

main_folder
--- target_file.py
--- utils.py
--- sub_utils.py
--- tests
   --- test_target.py
   --- conftest.py

当我运行测试时,我的 target_file 中的导入(它们看起来像 from utils.py import some_function) 。此外,utils.py从sub_utils.py导入函数。总之,一片混乱。

对我有用的是:

在我的conftest.py中,我使用了如下的装置:

@pytest.fixture(scope="module")
def import_target_file():
    from pathlib import Path
    import sys

    sys.path.append(str(Path(__file__).parent.parent))
    get_target_file = importlib.import_module("main_folder.target_file")
    yield get_target_file 

我的测试文件是什么样的:

class TestGetAppointments:
    def test_valid_event(self, import_target_file):
        """Test to verify correct response when valid event is provided."""
        test_event = {
            "pathParameters": {
                "start": "1",
                "end": "1",
            }
        }
        response = import_target_file.some_function(test_event)

解决方案 28:

测试经常因为无法导入模块而中断。

经过研究,我发现系统在错误的位置查看文件,我们可以通过将包含模块的文件复制到所述同一文件夹中来轻松解决问题,以便正确导入。

另一个解决方案建议是更改导入的声明并向 MutPy 显示单元的正确路径。但是,由于多个单元可能具有这种依赖关系,这意味着我们也需要在它们的声明中提交更改,因此我们更愿意将单元移动到文件夹中。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1043  
  IPD(Integrated Product Development,集成产品开发)是一种系统化的产品开发方法论,旨在通过跨职能团队的协作,优化产品开发的效率和质量。IPD流程强调从市场需求出发,通过并行工程、跨部门协作和阶段性评审,确保产品从概念到上市的每个环节都高效且可控。随着敏捷开发方法的普及,越来越多的企业开始...
华为IPD流程   41  
  随着企业产品开发复杂度的提升以及市场需求的快速变化,传统的产品开发模式逐渐显现出局限性。集成产品开发(IPD)流程与敏捷开发(Agile Development)作为两种主流的开发方法论,分别从系统化管理和快速响应需求的角度为企业提供了解决方案。然而,单独使用其中一种方法往往无法完全满足企业在效率、质量和创新上的多重需...
华为IPD流程   35  
  华为IPD(Integrated Product Development,集成产品开发)流程是华为公司成功的关键因素之一。它不仅帮助华为在技术上实现了快速创新,还通过市场导向确保了产品的商业成功。IPD流程通过整合技术与市场双驱动,实现了从需求定义到产品交付的全生命周期管理。这种模式不仅提高了产品的开发效率,还降低了市...
IPD流程中PDCP是什么意思   32  
  在研发领域,集成产品开发(IPD)流程已经成为企业提升创新效率和市场竞争力的重要手段。然而,资源分配的不合理往往是制约IPD流程效率的关键因素之一。无论是人力资源、财务资源还是技术资源,如何高效分配直接关系到项目的成功与否。优化资源分配不仅能够缩短产品开发周期,还能降低研发成本,提升产品的市场竞争力。因此,掌握资源分配...
IPD流程中CDCP   34  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用