pytest non può importare il modulo mentre python può farlo


115

Sto lavorando a un pacchetto in Python. Uso virtualenv. Ho impostato il percorso alla radice del modulo in un percorso .pth nel mio virtualenv, in modo da poter importare i moduli del pacchetto durante lo sviluppo del codice ed eseguire i test (Domanda 1: è un buon modo per farlo?). Funziona bene (ecco un esempio, questo è il comportamento che voglio):

(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

Tuttavia, se provo a utilizzare PyTest, ricevo alcuni messaggi di errore di importazione:

(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

Sono un po 'perplesso, sembra che questo indichi un errore di importazione, ma Python va bene, quindi perché c'è un problema specifico con PyTest? Qualche suggerimento sul motivo / rimedio (Domanda 2)? Ho cercato su Google e ho superato lo stack dell'errore "ImportError: impossibile importare" per PyTest, ma i riscontri che ho ricevuto erano correlati al percorso di Python mancante e rimedio a questo, che non sembra essere il problema qui. Eventuali suggerimenti?

Risposte:


118

Trovato la risposta:

NON mettere un __init__.pyfile in una cartella contenente TEST se prevedi di utilizzare pytest. Avevo uno di questi file, eliminandolo ha risolto il problema.

Questo è stato effettivamente sepolto nei commenti alla seconda risposta del problema PATH con pytest 'ImportError: Nessun modulo denominato YadaYadaYada', quindi non l'ho visto, spero che abbia più visibilità qui.


45
Divertente. Ho avuto lo stesso problema e ho dovuto aggiungere init .py alla mia cartella dei test.
Ev.

5
Sì, questa non è una soluzione generale (anche se lo era nel tuo caso), per capire perché dovrebbe essere letta: docs.pytest.org/en/latest/goodpractices.html#test-package-name
juan

1
Questa informazione è SBAGLIATA e fuorviante! Dopo aver aggiunto init .py nella cartella di test, tutto ha funzionato bene
Leonardo Ostan

1
@LeonardoOstan potrebbe essere sbagliato per te, ma non significa che questa informazione sia sbagliata in generale. Nel mio caso ha risolto il problema.
Desprit

80

Non posso dire di capire perché funziona, ma ho avuto lo stesso problema ei test funzionano bene se corro python -m pytest.

Sono in un virtualenv, con pytest disponibile anche a livello globale:

(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
Inoltre ha fatto il lavoro per me, il fatto è che viene eseguito dalla versione di python definita invece della tua v.env.
Nebulosar

12
una ragione potrebbe essere che python -m pytest [...]"aggiungerà anche la directory corrente a sys.path".
meno il

Aveva lo stesso in Windows 10 e l'esecuzione di python -m pytest lo ha risolto
Duccio

Questo ha funzionato anche all'interno del mio ambiente virtuale che dovevo eseguirepython3 -m pytest
Rishi Raj il

Basato sul commento di @minusf che sto usando PYTHONPATH=.:./src pytestcome target di make.
jan groth,

29

Ho appena risolto questo problema rimuovendo __init__.py nella radice del mio progetto:

.
├── __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
La risposta accettata __init__.py file in a folder containing TESTSnon ha risolto il mio problema. Questo ha funzionato. Immagino sia a causa della gerarchia dei file.
smido

Ho rimosso il __init__.pyfile. Stavo ancora affrontando il problema. L'aggiunta del file conftest.py alla directory principale ha funzionato per me.
Vijay Sali,

Mi aspetto che conftest.py sia in / tests non la radice
Aaron McMillin,

Anche il recupero del file conftest.py nella directory principale lo ha risolto per me. Non avere un file init .py nella directory dei test
Aggiorna il

2
Questa soluzione ha funzionato per me, ma qualcuno sa che potrebbe causare un errore di importazione?
Aldo Okware

19

Ho avuto lo stesso problema ma per un altro motivo rispetto a quelli menzionati:

Ho installato py.test globalmente, mentre i pacchetti sono stati installati in un ambiente virtuale.

La soluzione era installare pytestnell'ambiente virtuale. (Nel caso in cui la tua shell abbia hash eseguibili, come fa Bash, usa hash -ro usa il percorso completo per py.test)


2
Mi sono appena reso conto di avere lo stesso problema subdolo, usando anaconda. Ho dimenticato di aggiungere pytestil virtualenv creato da conda, ma pytestè disponibile nell'ambiente root di anaconda. Pertanto è stato possibile trovare pytest , ma nessun pacchetto installato nell'ambiente.
Overdrivr

1
Ho avuto lo stesso problema. pytest è stato installato globalmente e non in virtualenv. pip3 install pytestall'interno di virtualenv ha risolto il problema.
Ankit Singh

7

Questo problema si verificherà se hai un tests.pyfile e una cartella di test con estensione tests/__init__.py.

Durante la raccolta, pytest trova la cartella, ma quando tenta di importare i file di prova dalla cartella, il tests.pyfile causerà il problema di importazione.

Per risolvere è sufficiente rimuovere il tests.pyfile e inserire tutti i test all'interno della tests/cartella.

Per il tuo caso specifico la soluzione sarà precisamente:

  • Rimuovi il file /home/zz/Desktop/GitFolders/rc/tests.py
  • Assicurati che /home/zz/Desktop/GitFolders/rc/tests/__init__.pysia presente

4

Ho avuto un problema simile, identico errore, ma causa diversa. Stavo eseguendo il codice di prova senza problemi, ma su una vecchia versione del modulo. Nella versione precedente del mio codice esisteva una classe, mentre l'altra no. Dopo aver aggiornato il mio codice, avrei dovuto eseguire quanto segue per installarlo.

sudo pip install ./ --upgrade

Dopo aver installato il modulo aggiornato, l'esecuzione di pytest ha prodotto i risultati corretti (perché stavo usando la base di codice corretta).


1
Questo ha funzionato per me! Il mio modulo è stato allo stesso tempo installato come libreria nel container docker che stavo usando per eseguire pytest. Quando si esegue l'interprete python, trova il codice aggiornato, ma pytest continua a trovare il codice com'era quando la libreria è stata installata per la prima volta. Running ha pip install ./ --upgradeaggiornato la versione installata della lib con il codice più recente e ha consentito a pytest di trovare anche quest'ultima versione.
FaustoW

4

Nel mio caso, l'errore di importazione si è verificato perché il pacchetto punta a un altro pacchetto / directory con lo stesso nome e il suo percorso è un livello sopra la cartella che volevo effettivamente. Penso che questo spieghi anche perché alcune persone hanno bisogno di rimuovere _ init _.py mentre altri hanno bisogno di aggiungere di nuovo.

Ho appena messo print(the_root_package.__path__)(dopo import the_root_package) sia nella pythonconsole che negli pytestscript per confrontare la differenza

LINEA INFERIORE: Quando lo fai python, il pacchetto che importi potrebbe essere diverso dal pacchetto quando esegui pytest.


3

Installa i pacchetti nel tuo ambiente virtuale.
Quindi avvia una nuova shell e crea nuovamente il tuo ambiente virtuale.


1
Questo era il mio problema: una nuova installazione senza ricaricare il venv
congelato il

2

La risposta sopra non funziona per me. L'ho appena risolto aggiungendo il percorso assoluto del modulo che non si trovava all'inizio sys.pathdel test_xxx.py(il tuo modulo di test), come:

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

1
Invece di mettere queste righe all'inizio del mio test_main.py, l'ho inserito conftest.pynella mia directory di test e ha funzionato. Grazie per aver fornito una soluzione programmatica, invece di rifiuti di file.
Cameron Hudson

2

Se è correlato al codice python originariamente sviluppato in python 2.7 e ora migrato in python 3.x, probabilmente il problema è correlato a un problema di importazione.

ad esempio, quando si importa un oggetto da un file: baseche si trova nella stessa directory, funzionerà in python 2.x:

from base import MyClass

in python 3.x dovresti sostituire con baseil percorso completo o .base non farlo causerà il problema sopra. allora prova:

from .base import MyClass

2

Oggi stavo riscontrando questo problema e l'ho risolto chiamando python -m pytestdalla radice della directory del mio progetto.

La chiamata pytestdalla stessa posizione causava ancora problemi.

La directory My Project è organizzata come:

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

Il modulo è routesstato importato nel mio test_routes.pycome:from server.routes.routes import Routes

Spero che aiuti!


Grazie per il promemoria, ho dovuto usare il trucco in passato ed è nella documentazione più pytest.
Jason R Stevens CFA

1

Un altro caso speciale:

Ho avuto il problema di usare tox. Quindi il mio programma funzionava bene, ma gli unittest tramite tossicologia continuavano a lamentarsi. Dopo aver installato i pacchetti (necessari per il programma) è necessario specificare ulteriormente i pacchetti utilizzati negli unittest in tox.ini

[testenv]
deps =
    package1
    package2 
...

1

Lo stavo ottenendo usando VSCode. Ho un ambiente conda. Non credo che l'estensione Python VScode possa vedere gli aggiornamenti che stavo facendo.

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:

Ho dovuto correre pip install ./ --upgrade


Quel comando pip restituisce un errore:Directory './' is not installable. Neither 'setup.py' nor 'pyproject.toml' found.
Derek

1

Modifica il tuo conftest.py e aggiungi le seguenti righe di codice:

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

E se provi a eseguire il test case tramite terminale, usa il seguente ex:

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

NameError: name 'file' is not defined- a cosa dovrebbe corrispondere il file?
Koshmaar,

1

Ancora un'altra enorme vittoria per il sistema di importazione di Python. Penso che il motivo per cui non c'è consenso sia che ciò che funziona dipende probabilmente dal tuo ambiente e dagli strumenti che stai utilizzando al di sopra di esso.

Lo sto usando da VS Code, nell'esploratore di test in Windows in un ambiente conda, Python 3.8.

La configurazione che devo lavorare è:

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

In questa configurazione l'intellisense funziona e così fa la scoperta dei test.

Nota che originariamente ho provato quanto segue, come consigliato qui .

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

Non sono riuscito a trovare alcun modo per farlo funzionare da VS Code perché la srccartella ha fatto impazzire il sistema di importazione. Posso immaginare che ci sia un modo per farlo funzionare dalla riga di comando. Essendo un convertito relativamente nuovo alla programmazione Python, mi dà una sensazione nostalgica di lavorare con COM, ma è leggermente meno divertente.


1

I miei 2 centesimi su questo: pytest fallirà se non stai usando ambienti virtuali. A volte funzionerà e basta, a volte no.

Pertanto, la soluzione è:

  • rimuovere pytest con pip disinstallazione
  • crea il tuo venv
  • attiva il tuo venv
  • pip installa il percorso del tuo progetto in modalità modificabile, quindi sarà trattato da pytest come un modulo (altrimenti, pytest non troverà le tue importazioni interne). Avrai bisogno di un file setup.py per questo
  • installa i tuoi pacchetti, incluso pytest
  • infine, esegui i tuoi test

Il codice, utilizzando 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

Poi finalmente

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

Un esempio di setup.py, per pip install -e:

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

Non sono d'accordo con i post che dicono che devi rimuovere tutti i __init__.pyfile. Quello che devi invece fare è modificare il file sys.path.

Esegui un esperimento in cui stampi sys.pathquando esegui il codice normalmente. Quindi stampa sys.pathdurante l'esecuzione del codice tramite pytest. Penso che scoprirai che c'è una differenza tra questi due percorsi, quindi perché il pytest si rompe.

Per risolvere questo problema, inserisci il percorso del primo esperimento all'indice 0 del secondo.

Sia '/usr/exampleUser/Documents/foo'il primo elemento print(sys.path)dell'esperimento 1.

Di seguito è riportato il codice che dovrebbe risolvere il problema:

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

Mettilo all'inizio del file, prima dell'effettiva dichiarazione di importazione.

Fonte: mi stavo occupando di questo da solo e il processo sopra lo ha risolto.


1

Ho mantenuto tutto uguale e ho appena aggiunto un file di prova vuoto nella cartella principale. Risolto

Ecco i risultati, questo problema mi ha davvero infastidito per un po '. La mia struttura di cartelle era

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

e pytest si lamenterebbe con ModuleNotFoundError e darà il SUGGERIMENTO - assicurati che i tuoi moduli / pacchetti di test abbiano nomi Python validi.

Ho introdotto un file di test fittizio allo stesso livello di mathsapp e directory tests. Il file non conteneva nulla. Ora pytest non si lamenta.

Risultato senza il file

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

Risultati con il file

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

questo ha funzionato per me dopo molto tempo con questo problema. sembra che pytest tratti la radice del progetto come ovunque trovi il primo file di prova? sicuramente questo è un bug?
oooyaya

1

Ho risolto il mio problema impostando le PYTHONPATHvariabili d'ambiente per la configurazione specifica con cui sto eseguendo i miei test.

Durante la visualizzazione del file di prova su PyCharm:

  1. Ctrl+ Shift+A
  2. genere Edit Configurations
  3. Imposta il tuo PYTHONPATHin Ambiente> Variabili d'ambiente.

1

Metti semplicemente un conftest.pyfile vuoto nella directory root del progetto, perché quando pytestscopre un conftest.py, modifica sys.path in modo che possa importare cose dal conftestmodulo. Una struttura di directory generale può essere:

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

1

Ho avuto un problema simile e ha funzionato quando ho aggiunto il __init__.pyfile nella directory dei test.


0

Potrebbe essere che Pytest non stia leggendo il pacchetto come un modulo Python mentre Python lo è (probabilmente a causa di problemi di percorso). Prova a cambiare la directory dello script pytest o ad aggiungere il modulo esplicitamente al tuo PYTHONPATH.

Oppure potrebbe essere che sul tuo computer siano installate due versioni di Python. Controlla la tua fonte Python per pytest e per la shell Python che esegui. Se sono diversi (cioè Python 2 vs 3), usa source activateper assicurarti di eseguire il pytest installato per lo stesso python in cui è installato il modulo.


0

Per chiunque abbia provato di tutto e continui a ricevere errori, ho una soluzione.

Nella cartella in cui è installato pytest , vai alla cartella pytest-env .

Apri il file pyvenv.cfg .

Nel file modifica include-system-site-packages da falso a vero .

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

Spero che funzioni. Non dimenticare di votare.


0

Se hai già file .pyc, prova a eliminarli.

Oggi incontro questo problema, ecco cosa è successo:

per prima cosa eseguo pytest in mac (questo genererà file pyc) quindi avvio un container docker (il sistema operativo è alpino), con la directory del progetto montata, e poi quando provo a eseguire pytest nel container, si verifica ImportError. dopo aver pulito tutti i file pyc, nessun errore più.

Spero che questo possa essere utile.


0

se hai bisogno di un file init .py nella tua cartella, fai una copia della cartella ed elimina init .py in quella per eseguire i tuoi test, funziona per i progetti locali. Se hai bisogno di eseguire test regolarmente, vedi se puoi spostare il tuo init .py in un file separato.


0

[Risolto] Prima di saltare direttamente alla soluzione di rimozione / aggiunta __init__.py, potremmo anche voler esaminare come sono state eseguite le importazioni nelle tue classi. In realtà, ho perso una giornata a giocare __init__.pypensando che potesse essere il problema :) Tuttavia, è stato abbastanza istruttivo.

Nel mio caso, era il modo sbagliato di chiamare le classi da una classe python a un'altra classe python che stava lanciando ImportError. Risolto il problema con il modo in cui le classi / i moduli venivano chiamati e funzionava a meraviglia. Spero che questo aiuti anche gli altri.

E sì, per errori simili, potremmo avere soluzioni diverse a seconda di come è scritto il codice. Meglio dedicare più tempo all'auto debug. Lezione appresa :) Buona programmazione !!!


1
Potresti fornire alcuni esempi del modo sbagliato e del modo giusto?
Lurifaxel

0

Nel mio caso sto lavorando in un container e sfortunatamente pytest ha la tendenza a usare python2.7 piuttosto che il mio interprete python3 preferito.

Nel mio caso ha funzionato:

python3 -m pytest

La mia struttura di cartelle

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

-1

Avevo inserito tutti i miei test in una cartella dei test e ricevevo lo stesso errore. Ho risolto questo problema aggiungendo un init .py in quella cartella in questo modo:

.
|-- 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.