pytest无法导入模块,而python可以


114

我正在使用Python开发包。我使用virtualenv。我在virtualenv的.pth路径中将模块的根目录设置为路径,以便在开发代码并进行测试时可以导入软件包的模块(问题1:这是一个好方法吗?)。这工作正常(这是一个示例,这是我想要的行为):

(VEnvTestRc) zz@zz:~/Desktop/GitFolders/rc$ python
Python 2.7.12 (default, Jul  1 2016, 15:12:24) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from rc import ns
>>> exit()
(VEnvTestRc) zz@zz:~/Desktop/GitFolders/rc$ python tests/test_ns.py 
issued command: echo hello
command output: hello

但是,如果我尝试使用PyTest,则会收到一些导入错误消息:

(VEnvTestRc) zz@zz:~/Desktop/GitFolders/rc$ pytest
=========================================== test session starts ============================================
platform linux2 -- Python 2.7.12, pytest-3.0.5, py-1.4.31, pluggy-0.4.0
rootdir: /home/zz/Desktop/GitFolders/rc, inifile: 
collected 0 items / 1 errors 

================================================== ERRORS ==================================================
________________________________ ERROR collecting tests/test_ns.py ________________________________
ImportError while importing test module '/home/zz/Desktop/GitFolders/rc/tests/test_ns.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
tests/test_ns.py:2: in <module>
    from rc import ns
E   ImportError: cannot import name ns
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 errors during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
========================================= 1 error in 0.09 seconds ==========================================
(VEnvTestRc) zz@zz:~/Desktop/GitFolders/rc$ which pytest
/home/zz/Desktop/VirtualEnvs/VEnvTestRc/bin/pytest

我有点疑惑,它看起来像是一个导入错误,但是Python很好,所以为什么PyTest特有问题?对原因/补救措施有什么建议(问题2)?我用谷歌搜索并堆栈溢出了PyTest的“ ImportError:无法导入”错误,但是我得到的结果与缺少python路径有关,并且对此有补救措施,这似乎不是这里的问题。有什么建议?

Answers:


117

找到了答案:

__init__.py如果计划使用pytest,请勿将文件放在包含TESTS的文件夹中。我有一个这样的文件,删除它可以解决问题。

这实际上是在pytest“ ImportError:没有名为YadaYadaYada的模块”PATH问题的第二个答案的注释中掩埋的,所以我没有看到它,希望它在这里能够引起更多的关注。


44
滑稽。我遇到了同样的问题,必须将init .py 添加到我的测试文件夹中。
Ev。

5
是的,这不是一般的解决方案(即使您遇到了这种情况),以了解应阅读以下内容的
juan

1
该信息是错误的并且具有误导性!在将init .py 添加到测试文件夹后,一切正常
Leonardo Ostan

1
@LeonardoOstan,这可能对您来说是错误的,但这并不意味着此信息通常是错误的。就我而言,它解决了这个问题。
鄙视

79

我不能说我理解为什么会这样,但是我遇到了同样的问题,如果运行,测试也可以正常工作python -m pytest

我在virtualenv中,pytest也可以在全球范围内使用:

(proj)tom@neon ~/dev/proj$ type -a python
python is /home/tom/.virtualenvs/proj/bin/python
python is /usr/bin/python

(proj)tom@neon ~/dev/proj$ python -V
Python 3.5.2

(proj)tom@neon ~/dev/proj$ type -a pytest
pytest is /home/tom/.virtualenvs/proj/bin/pytest
pytest is /usr/bin/pytest

(proj)tom@neon ~/dev/proj$ pytest --version
This is pytest version 3.5.0, imported from /home/tom/.virtualenvs/proj/lib/python3.5/site-packages/pytest.py

1
事情也对我有用,事情是,它由定义的python版本而不是v.env运行。
Nebulosar

12
原因之一可能是python -m pytest [...]“还会将当前目录添加到” sys.path
minusf '18

在Windows 10中也是如此,并且运行python -m pytest解决了它
Duccio

这工作了,以及我的虚拟环境中,我不得不跑python3 -m pytest
仙人拉吉

基于@minusf的评论,我将其PYTHONPATH=.:./src pytest用作make目标。
jan groth

29

我只是通过删除项目根目录中的__init__.py来解决此问题:

.
├── __init__.py <--- removed
├── models
   ├── __init__.py
   ├── address.py
   ├── appointment.py
   └── client.py
├── requirements.txt
├── setup.cfg
├── tests
   ├── __init__.py
   ├── models
      ├── __init__.py
      ├── appointment_test.py
      └── client_test.py
   └── other_test.py
└── script.py

4
接受的答案__init__.py file in a folder containing TESTS不能解决我的问题。这个工作了。我猜是因为文件层次结构。
smido

我已删除__init__.py文件。我仍然面临问题。将conftest.py文件添加到根目录对我有用。
维杰萨利

我期望conftest.py是在/测试不是根
亚伦McMillin

将conftest.py文件获取到根目录也为我修复了该问题。tests目录中没有init .py文件
更新

2
这个解决方案对我有用,但是没有人知道这会导致导入错误吗?
Aldo Okware

19

我遇到了同样的问题,但是由于上述原因之外的另一个原因:

我在全局安装了py.test,而软件包则安装在虚拟环境中。

解决方案是pytest在虚拟环境中安装。(如果您的shell像Bash一样哈希可执行文件,请使用hash -r,或使用的完整路径py.test


2
刚意识到我使用anaconda遇到了同样的问题。我忘了添加pytest由创建的virtualenv conda,但pytest在anaconda的根环境中可用。因此可以找到pytest ,但环境中未安装任何软件包。
Overdrivr

1
我遇到过同样的问题。pytest是全局安装的,而不是在virtualenv中安装的。pip3 install pytest在virtualenv内部解决了该问题。
Ankit Singh '18

7

如果您有一个tests.py文件和一个带有的测试文件夹,则会发生此问题tests/__init__.py

在收集过程中,pytest会找到文件夹,但是当尝试从文件夹中导入测试文件时,tests.py文件会导致导入问题。

要解决此问题,只需删除tests.py文件,然后将所有测试放在tests/文件夹中即可。

对于您的特定情况,修复将精确地是:

  • 删除文件 /home/zz/Desktop/GitFolders/rc/tests.py
  • 确保/home/zz/Desktop/GitFolders/rc/tests/__init__.py存在

4

我有一个类似的问题,完全相同的错误,但原因不同。我正在运行测试代码,但是使用的是模块的旧版本。在我的代码的先前版本中,一个类存在,而另一个不存在。更新代码后,我应该运行以下命令进行安装。

sudo pip install ./ --upgrade

安装更新的模块后,运行pytest会产生正确的结果(因为我使用的是正确的代码库)。


1
这对我有用!我的模块同时作为库安装在用于运行pytest的docker容器中。当运行python解释器时,它将找到更新的代码,但是pytest仍会继续查找该库首次安装时的代码。Running pip install ./ --upgrade使用最新代码更新了已安装的lib版本,并启用pytest来查找该最新版本。
FaustoW

4

在我的情况下,发生导入错误是因为程序包指向另一个具有相同名称的程序包/目录,并且其路径在我实际想要的文件夹上方一层。我认为这也解释了为什么有些人需要删除_ init _.py而另一些人需要重新添加。

我只是在控制台和脚本中print(the_root_package.__path__)(在之后import the_root_package)放置以比较差异pythonpytest

底线:执行此操作时python,导入的包可能与运行时的包不同pytest


3

将软件包安装到您的虚拟环境中。
然后启动一个新的Shell并再次获取您的虚拟环境。


1
那是我的问题:无需重新加载venv即可进行全新安装
冻结了

2

上面的答案对我不起作用。我只是通过将未找到的模块的绝对路径附加到(您的测试模块)的sys.path顶部来解决它test_xxx.py,例如:

import sys
sys.path.append('path')

1
我没有将这些行放在我的顶部test_main.py,而是将其conftest.py放在我的测试目录中,并且可以正常工作。感谢您提供程序化解决方案,而不是文件垃圾。
卡梅隆·哈德森

2

如果它与最初在python 2.7中开发,现在迁移到python 3.x的python代码有关,则该问题可能与导入问题有关。

例如,从base同一目录中的文件导入对象时,它将在python 2.x中工作:

from base import MyClass

在python 3.x中,您应该替换为base完整路径,否则.base 将导致上述问题。所以尝试:

from .base import MyClass

2

我今天遇到了这个问题,并通过python -m pytest从项目目录的根目录进行调用来解决了。

pytest从同一位置拨打电话仍然会引起问题。

我的项目目录组织为:

api/
 - server/
  - tests/
      - test_routes.py
  - routes/
      - routes.py
 - app.py

该模块routes以我的test_routes.py身份导入:from server.routes.routes import Routes

希望有帮助!


感谢您的提醒,过去我不得不使用该技巧,它在pytest文档中。
Jason R Stevens CFA

1

另一个特殊情况:

我在使用毒药时遇到了问题。因此,我的程序运行良好,但是通过Tox进行的单元测试一直在抱怨。安装软件包(程序需要)之后,您需要另外在tox.ini中指定单元测试中使用的软件包。

[testenv]
deps =
    package1
    package2 
...

1

我正在使用VSCode来获得它。我有一个conda环境。我不认为VScode python扩展可以看到我所做的更新。

python c:\Users\brig\.vscode\extensions\ms-python.python-2019.9.34911\pythonFiles\testing_tools\run_adapter.py discover pytest -- -s --cache-clear test
Test Discovery failed:

我必须跑步 pip install ./ --upgrade


该pip命令返回错误:Directory './' is not installable. Neither 'setup.py' nor 'pyproject.toml' found.
Derek

1

编辑您的conftest.py并添加以下代码行:

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

如果尝试通过终端运行测试用例,请使用以下示例:

python -m pytest test_some_step_file_steps.py --html=HTML_step_file_output.html --self-contained-html

NameError: name 'file' is not defined-文件应等于什么?
科什马尔

1

Python的导入系统又获得了一次巨大的胜利。我认为,没有达成共识的原因是,有效的方法可能取决于您的环境以及在其上使用的工具。

我正在VS Code中使用它,它是在conda环境下Windows的Python 3.8中的测试资源管理器中使用的。

我要工作的设置是:

mypkg/
    __init__.py
    app.py
    view.py
tests/
    test_app.py
    test_view.py

在这种设置下,智能感知将起作用,测试发现也将起作用。

请注意,我最初试图以下,推荐这里

src/
    mypkg/
        __init__.py
        app.py
        view.py
tests/
    test_app.py
    test_view.py

我找不到从VS Code上src使它起作用的方法,因为该文件夹使导入系统无所适从。我可以想象有一种方法可以从命令行运行它。作为一种相对较新的Python编程转换,它带给我怀旧的使用COM的感觉,但是却没有那么有趣。


1

如果不使用虚拟环境,我为此付出的2美分:pytest会偶然失败。有时它会工作,有时则不会。

因此,解决方案是:

  • 用pip卸载删除pytest
  • 创建您的venv
  • 激活你的venv
  • pip以可编辑模式安装项目路径,因此pytest会将其视为模块(否则,pytest将找不到您的内部导入)。您将需要一个setup.py文件
  • 安装您的软件包,包括pytest
  • 最后,运行测试

使用Windows PowerShell的代码:

pip uninstall pytest
python.exe -m venv my_env
.\my_env\Scripts\activate
(my_env) pip install -e .
(my_env) pip install pytest pytest-html pandas numpy

然后最后

(my_env) pytest --html="my_testing_report.html"

用于pip install -e的setup.py示例:

import setuptools

setuptools.setup(
    name='my_package',
    version='devel',
    author='erickfis',
    author_email='erickfis@gmail.com',
    description='My package',
    long_description='My gooood package',
    packages=setuptools.find_packages(),
    classifiers=[
        'Programming Language :: Python :: 3',
        'Operating System :: OS Independent',
    ],
    include_package_data=True
)

1

我不同意这些帖子,说您必须删除所有__init__.py文件。您必须要做的是更改sys.path

sys.path正常运行代码的情况下,在您进行打印的地方进行实验。然后sys.path在通过pytest运行代码的同时进行打印。我认为您会发现这两条路径之间存在差异,因此pytest为什么会中断。

要解决此问题,请将第一个实验的路径插入第二个实验的第0个索引。

我们'/usr/exampleUser/Documents/foo'是第一个元素print(sys.path)的实验1。

以下是应该解决您问题的代码:

import sys sys.path[0] = '/usr/exampleUser/Documents/foo'

在实际导入语句之前,将此内容放在文件顶部。

资料来源:我本人正在处理,上述过程解决了它。


1

一切都保持相同,只是增加了在根文件夹中的空白测试文件..解决它

这是调查结果,这个问题确实困扰了我一段时间。我的文件夹结构是

mathapp/
    - server.py  
    - configuration.py 
    - __init__.py 
    - static/ 
       - home.html  
tests/            
    - functional 
       - test_errors.py 
    - unit  
       - test_add.py

pytest会抱怨ModuleNotFoundError并给出提示-确保您的测试模块/软件包具有有效的Python名称。

我在与mathsapp和tests目录相同的级别引入了模拟测试文件。该文件不包含任何内容。现在pytest不会抱怨。

没有文件的结果

$ pytest
============================= test session starts =============================
platform win32 -- Python 3.8.2, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\mak2006\workspace\0github\python-rest-app-cont
collected 1 item / 1 error

=================================== ERRORS ====================================
_______________ ERROR collecting tests/functional/test_func.py ________________
ImportError while importing test module 'C:\mainak\workspace\0github\python-rest-app-cont\tests\functional\test_func.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
tests\functional\test_func.py:4: in <module>
    from mathapp.service import sum
E   ModuleNotFoundError: No module named 'mathapp'
=========================== short test summary info ===========================
ERROR tests/functional/test_func.py
!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!
============================== 1 error in 0.24s ===============================

结果与文件

$ pytest
============================= test session starts =============================
platform win32 -- Python 3.8.2, pytest-5.4.2, py-1.8.1, pluggy-0.13.1
rootdir: C:\mak2006\workspace\0github\python-rest-app-cont
collected 2 items

tests\functional\test_func.py .                                          [ 50%]
tests\unit\test_unit.py .                                                [100%]

============================== 2 passed in 0.11s ==============================

在解决这个问题很长时间后,这对我有用。似乎pytest正在将项目根目录视为在哪里找到第一个测试文件?当然这是一个错误吗?
oooyaya

1

我通过PYTHONPATH为运行测试的特定配置设置环境变量解决了我的问题。

在PyCharm上查看测试文件时:

  1. Ctrl+ Shift+A
  2. 类型 Edit Configurations
  3. PYTHONPATH在环境>环境变量下设置。

1

只需将一个空conftest.py文件放在项目根目录中,因为当pytest发现conftest.py时,它将修改sys.path以便可以从conftest模块中导入内容。常规目录结构可以是:

Root
├── conftest.py
├── module1
   ├── __init__.py
   └── sample.py
└── tests
    └── test_sample.py

1

有一个类似的问题,当我__init__.py在tests目录下添加文件时,它可以工作。


0

可能是因为Pytest并未将Python包作为Python模块读取(可能是由于路径问题)。尝试更改pytest脚本的目录或将模块显式添加到PYTHONPATH。

也可能是您的计算机上安装了两个版本的Python。检查您的Python源是否有pytest和您运行的python shell。如果它们不同(例如,Python 2 vs 3),请使用source activate来确保您正在为安装模块的相同python运行pytest。


0

对于任何尝试了一切但仍然出错的人,我都有解决方法。

安装pytest文件夹中,转到pytest-env文件夹。

打开 pyvenv.cfg文件。

在文件中,将include-system-site-packagesfalse更改为true

home = /usr/bin
include-system-site-packages = true
version = 3.6.6

希望它能起作用。不要忘记投票。


0

如果您已经有.pyc文件,请尝试将其删除。

今天,我遇到了这个问题,这是发生了什么:

首先,我在Mac中运行pytest(这将生成pyc文件),然后启动安装了项目目录的docker容器(操作系统为alpine),然后尝试在容器中运行pytest时,发生ImportError。清除所有pyc文件后,再也没有错误。

希望这会有所帮助。


0

如果您的文件夹中需要一个init .py文件,请制作该文件夹的副本,然后删除其中的init .py来运行您的测试,该测试适用于本地项目。如果需要定期运行测试,请查看是否可以将init .py移到单独的文件中。


0

[解决]在直接进入删除/添加的解决方案之前__init__.py,我们可能还想看一下如何在您的类中完成导入。实际上,我只是__init__.py想着这可能是问题的原因,所以迷失了一天。)但是,那确实很有用。

就我而言,这是将类从一个python类调用到另一个正在抛出的python类的错误方式 ImportError。修复了类/模块的调用方式,它就像魅力一样工作。希望这对其他人也有帮助。

是的,对于类似的错误,根据代码的编写方式,我们可能有不同的解决方案。最好花更多时间进行自我调试。获得的经验:)编码愉快!!!


1
您能举一些错误方法和正确方法的例子吗?
Lurifaxel

0

就我而言,我在一个容器中工作,不幸的是pytest倾向于使用python2.7而不是我选择的python3解释器。

就我而言,这可行:

python3 -m pytest

我的文件夹结构

/
app/
-module1.py
-module2.py
-tests/
--test_module1.py
--test_module2.py
requirements.txt
README.md

-1

我已经将所有测试放在一个tests文件夹中,并且得到了相同的错误。我通过在该文件夹中添加init .py 来解决此问题,如下所示:

.
|-- Pipfile
|-- Pipfile.lock
|-- README.md
|-- api
|-- app.py
|-- config.py
|-- migrations
|-- pull_request_template.md
|-- settings.py
`-- tests
    |-- __init__.py <------
    |-- conftest.py
    `-- test_sample.py
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.