pytest ne peut pas importer le module alors que python peut

115

Je travaille sur un package en Python. J'utilise virtualenv. J'ai défini le chemin vers la racine du module dans un chemin .pth dans mon virtualenv, afin de pouvoir importer les modules du package tout en développant le code et faire des tests (Question 1: est-ce une bonne façon de faire?). Cela fonctionne bien (voici un exemple, c'est le comportement que je souhaite):

(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

Cependant, si j'essaie d'utiliser PyTest, j'obtiens des messages d'erreur d'importation:

(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

Je suis un peu perplexe, il semble que cela indique une erreur d'importation, mais Python fonctionne bien, alors pourquoi y a-t-il un problème spécifiquement avec PyTest? Une suggestion sur la raison / le remède (question 2)? J'ai cherché sur Google et j'ai débordé la pile de l'erreur `` ImportError: can't import '' pour PyTest, mais les hits que j'ai obtenus étaient liés au chemin python manquant et à y remédier, ce qui ne semble pas être le problème ici. Aucune suggestion?

Zorglub29
la source

Réponses:

118

J'ai trouvé la réponse:

NE placez PAS de __init__.pyfichier dans un dossier contenant TESTS si vous prévoyez d'utiliser pytest. J'avais un tel fichier, sa suppression a résolu le problème.

Cela a en fait été enterré dans les commentaires de la deuxième réponse du problème PATH avec pytest 'ImportError: Aucun module nommé YadaYadaYada' donc je ne l'ai pas vu, j'espère qu'il obtiendra plus de visibilité ici.

Zorglub29
la source
45
Drôle. J'ai eu le même problème et j'ai dû ajouter init .py à mon dossier de tests.
Ev.
5
Oui, ce n'est pas une solution générale (même si c'était dans votre cas), pour comprendre pourquoi cela devrait être lu: docs.pytest.org/en/latest/goodpractices.html#test-package-name
juan
1
Cette information est Fausse et trompeuse! Après avoir ajouté init .py dans le dossier de test, tout a bien fonctionné
Leonardo Ostan
1
@LeonardoOstan cela peut être faux pour vous, mais cela ne signifie pas que cette information est erronée en général. Dans mon cas, cela a résolu le problème.
Desprit le
80

Je ne peux pas dire que je comprends pourquoi cela fonctionne, mais j'ai eu le même problème et les tests fonctionnent bien si je cours python -m pytest.

Je suis dans un virtualenv, avec pytest également disponible dans le monde:

(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
À M
la source
1
J'ai également fait le travail pour moi, le truc est ,, il est exécuté par la version python définie au lieu de votre v.env.
Nebulosar
12
une des raisons pourrait être que python -m pytest [...]«ajoutera également le répertoire courant sys.path».
moins
Avait la même chose dans Windows 10, et l'exécution de python -m pytest l'a résolu
Duccio
Cela fonctionnait aussi bien dans mon environnement virtuel que je devais exécuterpython3 -m pytest
Rishi Raj
Basé sur le commentaire de @minusf que j'utilise PYTHONPATH=.:./src pytestcomme cible de création .
jan groth le
29

Je viens de résoudre ce problème en supprimant le __init__.py dans la racine de mon projet:

.
├── __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
Aaron McMillin
la source
4
La réponse acceptée __init__.py file in a folder containing TESTSn'a pas résolu mon problème. Celui-ci a fonctionné. Je suppose que c'est à cause de la hiérarchie des fichiers.
smido
J'ai supprimé le __init__.pyfichier. J'étais toujours confronté à un problème. L'ajout du fichier conftest.py au répertoire racine a fonctionné pour moi.
Vijay Sali le
Je m'attendrais à ce que conftest.py soit dans / tests pas la racine
Aaron McMillin le
Obtenir le fichier conftest.py dans le répertoire racine l'a également corrigé pour moi. Ne pas avoir de fichier init .py dans le répertoire des tests
Mise à jour du
2
Cette solution a fonctionné pour moi, mais est-ce que quelqu'un sait que cela provoquerait une erreur d'importation?
Aldo Okware
19

J'ai eu le même problème mais pour une autre raison que celles mentionnées:

J'ai installé py.test globalement, tandis que les packages ont été installés dans un environnement virtuel.

La solution consistait à installer pytestdans l'environnement virtuel. (Si votre shell hache les exécutables, comme le fait Bash, utilisez hash -rou utilisez le chemin complet vers py.test)

marque
la source
2
Je viens de réaliser que j'avais le même problème sournois, en utilisant anaconda. J'ai oublié d'ajouter pytestle virtualenv créé par conda, mais pytestil est disponible dans l'environnement racine d'anaconda. Par conséquent, pytest a pu être trouvé, mais aucun package installé dans l'environnement.
Overdrivr
1
J'ai eu le même problème. pytest a été installé globalement et non dans le virtualenv. pip3 install pytestà l'intérieur de virtualenv a résolu le problème.
Ankit Singh
7

Ce problème se produira si vous avez un tests.pyfichier et un dossier de tests avec tests/__init__.py.

Pendant la collecte, pytest trouve le dossier, mais lorsqu'il essaie d'importer les fichiers de test à partir du dossier, le tests.pyfichier provoque le problème d'importation.

Pour réparer, supprimez simplement le tests.pyfichier et mettez tous vos tests dans le tests/dossier.

Pour votre cas spécifique, le correctif sera précisément:

  • Supprimer le fichier /home/zz/Desktop/GitFolders/rc/tests.py
  • Assurez-vous que /home/zz/Desktop/GitFolders/rc/tests/__init__.pyc'est présent
lucasamaral
la source
4

J'ai eu un problème similaire, exactement la même erreur, mais une cause différente. J'exécutais très bien le code de test, mais contre une ancienne version du module. Dans la version précédente de mon code, une classe existait, tandis que l'autre n'existait pas. Après avoir mis à jour mon code, j'aurais dû exécuter ce qui suit pour l'installer.

sudo pip install ./ --upgrade

Lors de l'installation du module mis à jour, l'exécution de pytest a produit les résultats corrects (car j'utilisais la base de code correcte).

rustysys-dev
la source
1
Cela a fonctionné pour moi! Mon module était en même temps installé en tant que bibliothèque dans le conteneur docker que j'utilisais pour exécuter pytest. Lors de l'exécution de l'interpréteur python, il trouverait le code mis à jour, mais pytest continuerait à trouver le code tel qu'il était lors de la première installation de la bibliothèque. Running a pip install ./ --upgrademis à jour la version installée de la bibliothèque avec le dernier code et a activé pytest pour trouver cette dernière version également.
FaustoW
4

Dans mon cas, l'erreur d'importation s'est produite car le package pointe vers un autre package / répertoire avec le même nom et son chemin est un niveau au-dessus du dossier que je voulais réellement. Je pense que cela explique également pourquoi certaines personnes doivent supprimer _ init _.py tandis que d'autres doivent rajouter.

Je viens de mettre print(the_root_package.__path__)(après import the_root_package) à la fois la pythonconsole et les pytestscripts pour comparer la différence

LIGNE INFERIEURE: lorsque vous le faites python, le package que vous importez peut être différent du package lorsque vous exécutez pytest.

JoeyZhao
la source
3

Installez les packages dans votre environnement virtuel.
Ensuite, démarrez un nouveau shell et créez à nouveau votre environnement virtuel.

Kjeld Flarup
la source
1
C'était mon problème: une nouvelle installation sans recharger le venv
gelé
2

La réponse ci-dessus ne fonctionne pas pour moi. Je viens de le résoudre en ajoutant le chemin absolu du module qui ne se trouve pas sys.pathen haut de test_xxx.py(votre module de test), comme:

import sys
sys.path.append('path')
ZYX
la source
1
Au lieu de mettre ces lignes en haut de mon test_main.py, je l'ai mis conftest.pydans mon répertoire de test, et cela a fonctionné. Merci de fournir une solution programmatique, au lieu de la litière de fichiers.
Cameron Hudson
2

S'il est lié au code python initialement développé en python 2.7 et maintenant migré vers python 3.x, le problème est probablement lié à un problème d'importation.

par exemple lors de l'importation d'un objet à partir d'un fichier: basequi se trouve dans le même répertoire, cela fonctionnera en python 2.x:

from base import MyClass

dans python 3.x, vous devez remplacer par basele chemin complet ou .base ne pas le faire causera le problème ci-dessus. alors essayez:

from .base import MyClass
Amit Talmor
la source
2

Je rencontrais ce problème aujourd'hui et je l'ai résolu en appelant à python -m pytestpartir de la racine de mon répertoire de projet.

Appeler pytestdepuis le même endroit posait toujours des problèmes.

Mon répertoire de projet est organisé comme:

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

Le module a routesété importé dans my en test_routes.pytant que:from server.routes.routes import Routes

J'espère que cela pourra aider!

matt6frey
la source
Merci pour le rappel, j'ai dû utiliser l'astuce dans le passé et c'est dans la documentation pytest.
Jason R Stevens CFA le
1

Un autre cas particulier:

J'ai eu le problème en utilisant tox. Donc mon programme a bien fonctionné, mais unittests via tox a continué à se plaindre. Après avoir installé les packages (nécessaires pour le programme), vous devez en plus spécifier les packages utilisés dans les unittests dans le fichier tox.ini

[testenv]
deps =
    package1
    package2 
...
martin.zaenker
la source
1

J'obtenais cela en utilisant VSCode. J'ai un environnement conda. Je ne pense pas que l'extension python VScode puisse voir les mises à jour que je faisais.

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:

Je devais courir pip install ./ --upgrade

Brick
la source
Cette commande pip renvoie une erreur:Directory './' is not installable. Neither 'setup.py' nor 'pyproject.toml' found.
Derek
1

Modifiez votre conftest.py et ajoutez les lignes de code suivantes:

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

Et si vous essayez d'exécuter le scénario de test via le terminal, utilisez l'exemple suivant:

python -m pytest test_some_step_file_steps.py --html=HTML_step_file_output.html --self-contained-html
Siddharth Singh
la source
NameError: name 'file' is not defined- à quoi le fichier doit-il être égal?
Koshmaar le
1

Encore une autre victoire massive pour le système d'importation de Python. Je pense que la raison pour laquelle il n'y a pas de consensus est que ce qui fonctionne dépend probablement de votre environnement et des outils que vous utilisez en plus.

J'utilise ceci à partir de VS Code, dans l'explorateur de tests sous Windows dans un environnement conda, Python 3.8.

La configuration que je dois travailler est:

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

Dans cette configuration, intellisense fonctionne, de même que la découverte de test.

Notez que j'ai initialement essayé ce qui suit, comme recommandé ici .

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

Je ne pouvais trouver aucun moyen de faire fonctionner cela à partir de VS Code parce que le srcdossier a tout simplement époustouflé l'esprit du système d'importation. J'imagine qu'il existe un moyen de faire fonctionner cela à partir de la ligne de commande. En tant que converti relativement nouveau à la programmation Python, cela me donne un sentiment nostalgique de travailler avec COM, mais un peu moins amusant.

satnhak
la source
1

Mes 2 centimes sur ceci: pytest échouera au hasard si vous n'utilisez pas d'environnements virtuels. Parfois, cela fonctionnera, parfois non.

Par conséquent, la solution est:

  • supprimer pytest avec pip uninstall
  • créez votre venv
  • activer votre venv
  • pip installe le chemin de votre projet en mode éditable, il sera donc traité par pytest comme un module (sinon, pytest ne trouvera pas vos importations internes). Vous aurez besoin d'un fichier setup.py pour cela
  • installez vos packages, y compris pytest
  • enfin, lancez vos tests

Le code, à l'aide de 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

Puis finalement

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

Un exemple de setup.py, pour pip install -e:

import setuptools

setuptools.setup(
    name='my_package',
    version='devel',
    author='erickfis',
    author_email='[email protected]',
    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
)
erickfis
la source
1

Je ne suis pas d'accord avec les articles disant que vous devez supprimer tous les __init__.pyfichiers. Ce que vous devez faire à la place est de modifier le fichier sys.path.

Exécutez une expérience où vous imprimez sys.pathlorsque vous exécutez le code normalement. Puis imprimez sys.pathtout en exécutant le code via pytest. Je pense que vous constaterez qu'il y a une différence entre ces deux chemins, d'où la rupture de pytest.

Pour résoudre ce problème, insérez le chemin de la première expérience au 0ème index de la seconde.

Soit '/usr/exampleUser/Documents/foo'le premier élément de print(sys.path)pour l'expérience 1.

Voici le code qui devrait résoudre votre problème:

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

Mettez-le en haut de votre fichier, avant votre déclaration d'importation réelle.

Source: Je m'occupais de cela moi-même et le processus ci-dessus l'a résolu.

th3lourde
la source
1

Tout gardé de la même manière et vient d'ajouter un fichier de test vide dans le dossier racine .. Résolu

Voici les résultats, ce problème m'a vraiment dérangé pendant un certain temps. Ma structure de dossiers était

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

et pytest se plaindrait de ModuleNotFoundError et donne le CONSEIL - assurez-vous que vos modules / packages de test ont des noms Python valides.

J'ai introduit un fichier de test simulé au même niveau que le répertoire mathsapp et tests. Le fichier ne contenait rien. Maintenant, Pytest ne se plaint pas.

Résultat sans le fichier

$ 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 ===============================

Résultats avec le fichier

$ 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 ==============================
Mak2006
la source
cela a fonctionné pour moi après une longue période avec ce problème. semble que pytest traite la racine du projet comme partout où il trouve le premier fichier de test? c'est sûrement un bug?
oooyaya le
1

J'ai résolu mon problème en définissant les PYTHONPATHvariables d'environnement pour la configuration spécifique avec laquelle j'exécute mes tests.

Pendant que vous visualisez le fichier de test sur PyCharm:

  1. Ctrl+ Shift+A
  2. Type Edit Configurations
  3. Définissez votre PYTHONPATHsous Environnement> Variables d'environnement.
Ece Tavasli
la source
1

Mettez simplement un conftest.pyfichier vide dans le répertoire racine du projet, car quand il pytestdécouvre un conftest.py, il modifie sys.path afin qu'il puisse importer des éléments du conftestmodule. Une structure générale de répertoires peut être:

Root
├── conftest.py
├── module1
   ├── __init__.py
   └── sample.py
└── tests
    └── test_sample.py
Abdul Rehman
la source
1

J'ai eu un problème similaire et cela a fonctionné lorsque j'ai ajouté un __init__.pyfichier sous le répertoire de tests.

Chetan G. Bendre
la source
0

Il se peut que Pytest ne lit pas le package en tant que module Python alors que Python le fait (probablement en raison de problèmes de chemin). Essayez de changer le répertoire du script pytest ou d'ajouter le module explicitement à votre PYTHONPATH.

Ou il se peut que vous ayez deux versions de Python installées sur votre machine. Vérifiez votre source Python pour pytest et pour le shell python que vous exécutez. S'ils sont différents (par exemple Python 2 vs 3), utilisez source activatepour vous assurer que vous exécutez le pytest installé pour le même python dans lequel le module est installé.

tooty44
la source
0

Pour tous ceux qui ont tout essayé et qui ont encore des erreurs, j'ai une solution.

Dans le dossier où pytest est installé , accédez au dossier pytest-env .

Ouvrez le fichier pyvenv.cfg .

Dans le fichier, changez include-system-site-packages de false à true .

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

J'espère que ça marche. N'oubliez pas de voter.

Charan Reddy
la source
0

Si vous avez déjà des fichiers .pyc, essayez de les supprimer.

Aujourd'hui, je rencontre ce problème, voici ce qui s'est passé:

Je lance d'abord pytest dans mac (cela générera des fichiers pyc), puis je lance un conteneur docker (l'os est alpin), avec le répertoire du projet monté, puis lorsque j'essaye d'exécuter pytest dans le conteneur, ImportError se produit. après avoir nettoyé tous les fichiers pyc, plus aucune erreur.

J'espère que cela peut être utile.

接口 夏季
la source
0

si vous avez besoin d'un fichier init .py dans votre dossier, faites une copie du dossier et supprimez init .py dans celui-ci pour exécuter vos tests, cela fonctionne pour les projets locaux. Si vous avez besoin d'exécuter des tests régulièrement, voyez si vous pouvez déplacer votre init .py vers un fichier séparé.

nchil
la source
0

[Résolu] Avant de passer directement à la solution de suppression / ajout __init__.py, nous pourrions également vouloir regarder comment les importations sont effectuées dans vos classes. En fait, j'ai perdu une journée à jouer en __init__.pypensant que c'était peut-être le problème :) Cependant, c'était assez instructif.

Dans mon cas, c'était la mauvaise façon d'appeler des classes d'une classe python vers une autre classe python qui lançait ImportError. Correction de la façon dont les classes / modules étaient appelés et cela fonctionnait comme un charme. J'espère que cela aide aussi les autres.

Et oui, pour une erreur similaire, nous pourrions avoir des solutions différentes selon la façon dont le code est écrit. Mieux vaut passer plus de temps sur l'auto-débogage. Leçon apprise :) Bon codage !!!

nullcode
la source
1
Pourriez-vous donner quelques exemples de la mauvaise et de la bonne manière?
Lurifaxel le
0

Dans mon cas, je travaille dans un conteneur et malheureusement pytest a tendance à utiliser python2.7 plutôt que mon interpréteur python3 de choix.

Dans mon cas, cela a fonctionné:

python3 -m pytest

Ma structure de dossiers

/
app/
-module1.py
-module2.py
-tests/
--test_module1.py
--test_module2.py
requirements.txt
README.md
Patrick
la source
-1

J'avais placé tous mes tests dans un dossier de tests et recevais la même erreur. J'ai résolu cela en ajoutant un init .py dans ce dossier comme ceci:

.
|-- 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
Chidiebere
la source