pytest no puede importar el módulo mientras que python puede

114

Estoy trabajando en un paquete en Python. Yo uso virtualenv. Establezco la ruta a la raíz del módulo en una ruta .pth en mi virtualenv, de modo que puedo importar módulos del paquete mientras desarrollo el código y hago las pruebas (Pregunta 1: ¿es una buena manera de hacerlo?). Esto funciona bien (aquí hay un ejemplo, este es el comportamiento que quiero):

(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

Sin embargo, si intento usar PyTest, recibo algunos mensajes de error de importación:

(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

Estoy un poco desconcertado, parece que esto indica un error de importación, pero Python lo hace bien, entonces, ¿por qué hay un problema específicamente con PyTest? ¿Alguna sugerencia sobre la razón / solución (pregunta 2)? Busqué en Google y desbordé la pila del error 'ImportError: no se puede importar' para PyTest, pero los resultados que obtuve estaban relacionados con la ruta de Python faltante y la solución a esto, que no parece ser el problema aquí. ¿Alguna sugerencia?

Zorglub29
fuente

Respuestas:

117

Encontré la respuesta:

NO coloque un __init__.pyarchivo en una carpeta que contenga PRUEBAS si planea usar pytest. Tenía uno de esos archivos, eliminarlo resolvió el problema.

En realidad, esto fue enterrado en los comentarios a la segunda respuesta del problema PATH con pytest 'ImportError: No module named YadaYadaYada', así que no lo vi, espero que tenga más visibilidad aquí.

Zorglub29
fuente
44
Gracioso. Tuve el mismo problema y tuve que agregar init .py a mi carpeta de pruebas.
Ev.
5
Sí, esta no es una solución general (aunque lo fue en su caso), para entender por qué debería leerse: docs.pytest.org/en/latest/goodpractices.html#test-package-name
juan
1
¡Esta información es INCORRECTA y engañosa! Después de agregar init .py en la carpeta de prueba, todo funcionó bien
Leonardo Ostan
1
@LeonardoOstan puede que sea incorrecta para ti, pero no significa que esta información sea incorrecta en general. En mi caso resolvió el problema.
Desprit
79

No puedo decir que entiendo por qué funciona esto, pero tuve el mismo problema y las pruebas funcionan bien si las ejecuto python -m pytest.

Estoy en un virtualenv, con pytest también disponible a nivel mundial:

(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
Tom
fuente
1
También hizo el trabajo por mí, la cosa es que lo ejecuta la versión de Python definida en lugar de su v.env.
Nebulosar
12
una de las razones podría ser que python -m pytest [...]"también agregará el directorio actual sys.path".
menos el
Python -m PYtest tenido el mismo en Windows 10, y funcionando resuelto
Duccio
Esto funcionó también dentro de mi entorno virtual que tuve que ejecutarpython3 -m pytest
Rishi Raj
Según el comentario de @minusf que estoy usando PYTHONPATH=.:./src pytestcomo objetivo de creación .
jan groth
29

Acabo de resolver esto eliminando __init__.py en la raíz de mi proyecto:

.
├── __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
fuente
4
La respuesta aceptada __init__.py file in a folder containing TESTSno resolvió mi problema. Este funcionó. Supongo que es por la jerarquía de archivos.
smido
He eliminado el __init__.pyarchivo. Todavía estaba enfrentando problemas. Agregar el archivo conftest.py al directorio raíz funcionó para mí.
Vijay Sali
Espero que conftest.py esté en / tests no en la raíz
Aaron McMillin
Obtener el archivo conftest.py en el directorio raíz también lo solucionó para mí. No tiene un archivo init .py en el directorio de pruebas
actualización el
2
Esta solución funcionó para mí, pero ¿alguien sabe que esto causaría un error de importación?
Aldo Okware
19

Tuve el mismo problema pero por una razón diferente a las mencionadas:

Tenía py.test instalado globalmente, mientras que los paquetes se instalaron en un entorno virtual.

La solución fue instalarlo pytesten el entorno virtual. (En caso de que su shell tenga archivos ejecutables, como lo hace Bash, use hash -ro use la ruta completa para py.test)

marca
fuente
2
Me acabo de dar cuenta de que tenía el mismo problema furtivo al usar anaconda. Olvidé agregar pytestel virtualenv creado por conda, pero pytestestá disponible en el entorno raíz de anaconda. Por lo tanto, se pudo encontrar pytest , pero no ningún paquete instalado en el entorno.
Overdrivr
1
Tuve el mismo problema. pytest se instaló globalmente y no en virtualenv. pip3 install pytestdentro de virtualenv solucionó el problema.
Ankit Singh
7

Este problema ocurrirá si tiene un tests.pyarchivo y una carpeta de pruebas con tests/__init__.py.

Durante la recopilación, pytest encuentra la carpeta, pero cuando intenta importar los archivos de prueba desde la carpeta, el tests.pyarchivo causará el problema de importación.

Para solucionarlo, simplemente elimine el tests.pyarchivo y coloque todas sus pruebas dentro de la tests/carpeta.

Para su caso específico, la solución será precisamente:

  • Quitar el archivo /home/zz/Desktop/GitFolders/rc/tests.py
  • Asegúrate de que /home/zz/Desktop/GitFolders/rc/tests/__init__.pyesté presente
lucasamaral
fuente
4

Tuve un problema similar, exactamente el mismo error, pero una causa diferente. Estaba ejecutando el código de prueba bien, pero contra una versión anterior del módulo. En la versión anterior de mi código existía una clase, mientras que la otra no. Después de actualizar mi código, debería haber ejecutado lo siguiente para instalarlo.

sudo pip install ./ --upgrade

Al instalar el módulo actualizado, ejecutar pytest produjo los resultados correctos (porque estaba usando la base de código correcta).

rustysys-dev
fuente
1
¡Esto funcionó para mí! Mi módulo se instaló al mismo tiempo como una biblioteca en el contenedor de la ventana acoplable que estaba usando para ejecutar pytest. Al ejecutar el intérprete de Python, encontraría el código actualizado, pero pytest continuaría encontrando el código como estaba cuando se instaló la biblioteca por primera vez. Running pip install ./ --upgradeactualizó la versión instalada de la lib con el último código y permitió que pytest encontrara también esta última versión.
FaustoW
4

En mi caso, el error de importación se produjo porque el paquete apunta a otro paquete / directorio con el mismo nombre y su ruta está un nivel por encima de la carpeta que realmente quería. Creo que esto también explica por qué algunas personas necesitan eliminar _ init _.py mientras que otras necesitan volver a agregar.

Solo puse print(the_root_package.__path__)(después import the_root_package) tanto en la pythonconsola como en los pytestscripts para comparar la diferencia

LÍNEA INFERIOR: cuando lo hace python, el paquete que importa puede ser diferente del paquete cuando lo ejecuta pytest.

JoeyZhao
fuente
3

Instale los paquetes en su entorno virtual.
Luego inicie un nuevo shell y vuelva a generar su entorno virtual.

Kjeld Flarup
fuente
1
Ese fue mi problema: una instalación nueva sin recargar el venv
congelado el
2

La respuesta anterior no funciona para mí. Simplemente lo resolví agregando la ruta absoluta del módulo que no se encuentra en la sys.pathparte superior de test_xxx.py(su módulo de prueba), como:

import sys
sys.path.append('path')
ZYX
fuente
1
En lugar de poner estas líneas en la parte superior de mi test_main.py, las puse conftest.pyen mi directorio de prueba y funcionó. Gracias por proporcionar una solución programática, en lugar de basura de archivos.
Cameron Hudson
2

Si está relacionado con el código de Python que se desarrolló originalmente en Python 2.7 y ahora se migró a Python 3.x, entonces el problema probablemente esté relacionado con un problema de importación.

por ejemplo, al importar un objeto desde un archivo: baseque se encuentra en el mismo directorio, esto funcionará en python 2.x:

from base import MyClass

en python 3.x debe reemplazar con basela ruta completa o .base no hacerlo causará el problema anterior. así que intenta:

from .base import MyClass
Amit Talmor
fuente
2

Hoy estaba experimentando este problema y lo resolví llamando python -m pytestdesde la raíz del directorio de mi proyecto.

Llamar pytestdesde la misma ubicación aún causaba problemas.

Mi directorio de proyectos está organizado como:

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

El módulo routesfue importado en mi test_routes.pycomo:from server.routes.routes import Routes

¡Espero que ayude!

matt6frey
fuente
Gracias por el recordatorio, tuve que usar el truco en el pasado y está en la documentación de Pytest.
Jason R Stevens CFA
1

Otro caso especial:

Tuve el problema al usar tox. Así que mi programa funcionó bien, pero las pruebas unitarias a través de toxinas seguían quejándose. Después de instalar los paquetes (necesarios para el programa), debe especificar adicionalmente los paquetes utilizados en las pruebas unitarias en el archivo tox.ini

[testenv]
deps =
    package1
    package2 
...
martin.zaenker
fuente
1

Estaba obteniendo esto usando VSCode. Tengo un ambiente de conda. No creo que la extensión de Python de VScode pueda ver las actualizaciones que estaba haciendo.

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:

Tuve que correr pip install ./ --upgrade

Bergantín
fuente
Ese comando pip devuelve un error:Directory './' is not installable. Neither 'setup.py' nor 'pyproject.toml' found.
Derek
1

Edite su conftest.py y agregue las siguientes líneas de código:

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

Y si intenta ejecutar el caso de prueba a través de la terminal, use el siguiente ejemplo:

python -m pytest test_some_step_file_steps.py --html=HTML_step_file_output.html --self-contained-html
Siddharth Singh
fuente
NameError: name 'file' is not defined- ¿A qué debería ser igual el archivo?
Koshmaar
1

Otra gran victoria para el sistema de importación de Python. Creo que la razón por la que no hay consenso es que lo que funciona probablemente depende de su entorno y de las herramientas que esté utilizando.

Estoy usando esto de VS Code, en el explorador de prueba en Windows en un entorno conda, Python 3.8.

La configuración que tengo que trabajar es:

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

Bajo esta configuración, intellisense funciona y también lo hace el descubrimiento de pruebas.

Tenga en cuenta que probé originalmente lo siguiente, como se recomienda aquí .

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

No pude encontrar ninguna manera de hacer que esto funcione desde VS Code porque la srccarpeta simplemente voló la mente del sistema de importación. Puedo imaginar que hay una manera de hacer que esto funcione desde la línea de comandos. Como un converso relativamente nuevo a la programación de Python, me da una sensación nostálgica de trabajar con COM, pero es un poco menos divertido.

satnhak
fuente
1

Mis 2 centavos en esto: pytest fallará por casualidad si no está utilizando entornos virtuales. A veces simplemente funcionará, a veces no.

Por tanto, la solución es:

  • eliminar pytest con desinstalación de pip
  • crea tu venv
  • activa tu venv
  • pip instala la ruta de tu proyecto en modo editable, por lo que pytest lo tratará como un módulo (de lo contrario, pytest no encontrará tus importaciones internas). Necesitará un archivo setup.py para eso
  • instale sus paquetes, incluido pytest
  • finalmente, ejecuta tus pruebas

El código, usando 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

Entonces finalmente

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

Un ejemplo de setup.py, para 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
fuente
1

No estoy de acuerdo con las publicaciones que dicen que debes eliminar cualquier __init__.pyarchivo. En su lugar, lo que debe hacer es modificar el sys.path.

Ejecute un experimento en el que imprima sys.pathcuando ejecuta el código normalmente. Luego imprima sys.pathmientras ejecuta el código a través de pytest. Creo que encontrará que hay una diferencia entre estos dos caminos, de ahí por qué Pytest se rompe.

Para solucionar este problema, inserte la ruta del primer experimento en el índice 0 del segundo.

Sea '/usr/exampleUser/Documents/foo'el primer elemento del print(sys.path)experimento 1.

A continuación se muestra el código que debería solucionar su problema:

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

Ponga esto en la parte superior de su archivo, antes de su declaración de importación real.

Fuente: Estaba lidiando con esto yo mismo y el proceso anterior lo resolvió.

th3lourde
fuente
1

Mantuve todo igual y solo agregué un archivo de prueba en blanco en la carpeta raíz. Resuelto

Aquí están los hallazgos, este problema realmente me molestó por un tiempo. Mi estructura de carpetas era

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

y pytest se quejaría con ModuleNotFoundError y da la SUGERENCIA: asegúrese de que sus módulos / paquetes de prueba tengan nombres de Python válidos.

Presenté un archivo de prueba simulado al mismo nivel que el directorio mathsapp y tests. El archivo no contenía nada. Ahora pytest no se queja.

Resultado sin el archivo

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

Resultados con el archivo

$ 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
fuente
esto funcionó para mí después de mucho tiempo con este problema. parece que pytest está tratando la raíz del proyecto como donde encuentra el primer archivo de prueba? seguramente esto es un error?
oooyaya
1

Resolví mi problema configurando las PYTHONPATHVariables de entorno para la configuración específica con la que estoy ejecutando mis pruebas.

Mientras ve el archivo de prueba en PyCharm:

  1. Ctrl+ Shift+A
  2. Tipo Edit Configurations
  3. Establezca su PYTHONPATHen Entorno> Variables de entorno.
Ece Tavasli
fuente
1

Simplemente coloque un conftest.pyarchivo vacío en el directorio raíz del proyecto, porque cuando pytestdescubre un conftest.py, modifica sys.path para que pueda importar cosas del conftestmódulo. Una estructura de directorio general puede ser:

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

Tuve un problema similar y funcionó cuando agregué un __init__.pyarchivo en el directorio de pruebas.

Chetan G. Bendre
fuente
0

Podría ser que Pytest no esté leyendo el paquete como un módulo de Python mientras que Python sí (probablemente debido a problemas de ruta). Intente cambiar el directorio del script pytest o agregar el módulo explícitamente a su PYTHONPATH.

O podría ser que tenga dos versiones de Python instaladas en su máquina. Verifique su fuente de Python para pytest y para el shell de Python que ejecuta. Si son diferentes (es decir, Python 2 vs 3), utilícelo source activatepara asegurarse de que está ejecutando el pytest instalado para el mismo python en el que está instalado el módulo.

tooty44
fuente
0

Para cualquiera que haya intentado todo y aún obtenga errores, tengo una solución.

En la carpeta donde está instalado pytest , vaya a la carpeta pytest-env .

Abra el archivo pyvenv.cfg .

En el archivo, cambie include-system-site-packages de falso a verdadero .

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

Espero que funcione. No olvides votar.

Charan Reddy
fuente
0

Si ya tiene archivos .pyc, intente eliminarlos.

Hoy, me encuentro con este problema, esto es lo que sucedió:

primero ejecuto pytest en mac (esto generará archivos pyc), luego ejecuto un contenedor docker (el sistema operativo es alpine), con el directorio del proyecto montado, y luego, cuando intento ejecutar pytest en el contenedor, se produce ImportError. después de limpiar todos los archivos pyc, no hay más errores.

Espero que esto pueda ser útil.

接口 夏季
fuente
0

si necesita un archivo init .py en su carpeta, haga una copia de la carpeta y elimine init .py en ese para ejecutar sus pruebas, funciona para proyectos locales. Si necesita ejecutar la prueba con regularidad, vea si puede mover su init .py a un archivo separado.

nchil
fuente
0

[Resuelto] Antes de saltar directamente a la solución de eliminar / agregar __init__.py, es posible que también deseemos ver cómo se realizan las importaciones en sus clases. De hecho, perdí un día jugando con solo __init__.pypensar que ese podría ser el problema :) Sin embargo, eso fue bastante informativo.

En mi caso, era la forma incorrecta de llamar a clases de una clase de Python a otra clase de Python que estaba arrojando ImportError. Se corrigió la forma en que se llamarían las clases / módulos y funcionó a la perfección. Espero que esto ayude a otros también.

Y sí, para un error similar, podríamos tener diferentes soluciones dependiendo de cómo esté escrito el código. Es mejor dedicar más tiempo a la autodepuración. Lección aprendida :) ¡Feliz codificación!

código nulo
fuente
1
¿Podría dar algunos ejemplos de la forma incorrecta y la forma correcta?
Lurifaxel
0

En mi caso, estoy trabajando en un contenedor y, lamentablemente, pytest tiene la tendencia a usar python2.7 en lugar de mi intérprete de python3 de elección.

En mi caso esto funcionó:

python3 -m pytest

Mi estructura de carpetas

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

Había colocado todas mis pruebas en una carpeta de pruebas y recibía el mismo error. Resolví esto agregando un init .py en esa carpeta así:

.
|-- 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
fuente