pytest nie może zaimportować modułu, podczas gdy Python może

115

Pracuję nad pakietem w Pythonie. Używam virtualenv. Ustawiłem ścieżkę do katalogu głównego modułu w ścieżce .pth w moim virtualenv, aby móc importować moduły pakietu podczas opracowywania kodu i testowania (Pytanie 1: czy to dobry sposób?). To działa dobrze (oto przykład, to jest zachowanie, które chcę):

(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

Jeśli jednak spróbuję użyć PyTest, otrzymuję komunikaty o błędach importu:

(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

Jestem trochę zdziwiony, wygląda na to, że oznacza to błąd importu, ale Python radzi sobie dobrze, więc dlaczego występuje problem konkretnie z PyTestem? Jakieś sugestie co do powodu / rozwiązania (pytanie 2)? Wyszukałem w Google i przepełniłem stos błędu „ImportError: nie można zaimportować” dla PyTest, ale trafienia, które otrzymałem, były związane z brakującą ścieżką do Pythona i rozwiązaniem tego problemu, co nie wydaje się być tutaj problemem. Jakieś sugestie?

Zorglub29
źródło

Odpowiedzi:

118

Znalazłem odpowiedź:

NIE umieszczaj __init__.pypliku w folderze zawierającym TESTY, jeśli planujesz używać pytest. Miałem jeden taki plik, usunięcie go rozwiązało problem.

Zostało to właściwie zakopane w komentarzach do drugiej odpowiedzi w kwestii PATH z pytestem „ImportError: Brak modułu o nazwie YadaYadaYada”, więc nie widziałem tego, mam nadzieję, że tutaj będzie bardziej widoczny.

Zorglub29
źródło
45
Zabawny. Miałem ten sam problem i musiałem dodać init .py do folderu testów.
Ev.
5
Tak, to nie jest rozwiązanie ogólne (chociaż to było w Twoim przypadku), aby zrozumieć, dlaczego ten należy czytać: docs.pytest.org/en/latest/goodpractices.html#test-package-name
juan
1
Ta informacja jest NIEPRAWIDŁOWA i wprowadzająca w błąd! Po dodaniu init .py do folderu testowego wszystko działało dobrze
Leonardo Ostan
1
@LeonardoOstan, może to być złe dla Ciebie, ale nie oznacza to, że te informacje są ogólnie błędne. W moim przypadku to rozwiązało problem.
Desprit
80

Nie mogę powiedzieć, że rozumiem, dlaczego to działa, ale miałem ten sam problem i testy działają dobrze, jeśli uruchomię python -m pytest.

Jestem w virtualenv, pytest jest również dostępny globalnie:

(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
Tomek
źródło
1
Również wykonał pracę za mnie, chodzi o to, że jest uruchamiany przez wersję Pythona zdefiniowaną zamiast twojego v.env.
Nebulosar
12
jednym z powodów może być to, że python -m pytest [...]„doda również bieżący katalog do sys.path”.
minusf
Miałem to samo w Windows 10 i uruchomiłem Pythona -m pytest rozwiązałem
Duccio
To zadziałało również w moim wirtualnym środowisku, które musiałem uruchomićpython3 -m pytest
Rishi Raj
Na podstawie komentarza @minusf używam PYTHONPATH=.:./src pytestjako celu make.
jan groth
29

Właśnie rozwiązałem ten problem, usuwając __init__.py w katalogu głównym mojego projektu:

.
├── __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
źródło
4
Zaakceptowana odpowiedź __init__.py file in a folder containing TESTSnie rozwiązała mojego problemu. Ten działał. Myślę, że to z powodu hierarchii plików.
smido
Usunąłem __init__.pyplik. Nadal miałem problem. Dodanie pliku conftest.py do katalogu głównego zadziałało.
Vijay Sali
Spodziewałbym się, że conftest.py będzie w katalogu / testing, a nie w katalogu głównym
Aaron McMillin
Pobranie pliku conftest.py do katalogu głównego również rozwiązało problem. Nie ma pliku init .py w katalogu
aktualizacja
2
To rozwiązanie działało u mnie, ale czy ktoś wie, że spowodowałoby to błąd importu?
Aldo Okware
19

Miałem ten sam problem, ale z innego powodu niż wymienione:

Miałem py.test zainstalowany globalnie, podczas gdy pakiety były zainstalowane w środowisku wirtualnym.

Rozwiązaniem była instalacja pytestw środowisku wirtualnym. (W przypadku, gdy twoja powłoka haszuje pliki wykonywalne, tak jak robi to Bash, użyj hash -rlub użyj pełnej ścieżki do py.test)

znak
źródło
2
Właśnie zdałem sobie sprawę, że mam ten sam podstępny problem, używając anakondy. Zapomniałem dodać pytestw virtualenv stworzonym przez conda, ale pytestjest dostępny w środowisku root anacondy. Dlatego można znaleźć pytest , ale nie można znaleźć żadnego pakietu zainstalowanego w środowisku.
Overdrivr
1
Miałem ten sam problem. pytest został zainstalowany globalnie, a nie w virtualenv. pip3 install pytestInside virtualenv naprawił problem.
Ankit Singh
7

Ten problem wystąpi, jeśli masz tests.pyplik i folder testów z rozszerzeniem tests/__init__.py.

Podczas zbierania pytest znajduje folder, ale gdy spróbuje zaimportować pliki testowe z folderu, tests.pyplik spowoduje problem z importem.

Aby naprawić, po prostu usuń tests.pyplik i umieść wszystkie testy w tests/folderze.

W Twoim konkretnym przypadku poprawka będzie dokładnie taka:

  • Usuń plik /home/zz/Desktop/GitFolders/rc/tests.py
  • Upewnij się, że /home/zz/Desktop/GitFolders/rc/tests/__init__.pyjest obecny
lucasamaral
źródło
4

Miałem podobny problem, dokładnie ten sam błąd, ale inną przyczynę. Uruchomiłem kod testowy dobrze, ale przeciwko starej wersji modułu. W poprzedniej wersji mojego kodu jedna klasa istniała, a druga nie. Po zaktualizowaniu kodu powinienem był wykonać poniższe czynności, aby go zainstalować.

sudo pip install ./ --upgrade

Po zainstalowaniu zaktualizowanego modułu uruchomienie pytest zwróciło poprawne wyniki (ponieważ używałem poprawnej podstawy kodu).

rustysys-dev
źródło
1
To zadziałało dla mnie! Mój moduł został w tym samym czasie zainstalowany jako biblioteka w kontenerze docker, którego używałem do uruchamiania pytest. Podczas uruchamiania interpretera języka Python znalazłby zaktualizowany kod, ale pytest nadal znajdowałby kod, tak jak podczas pierwszej instalacji biblioteki. Uruchamianie pip install ./ --upgradezaktualizowało zainstalowaną wersję biblioteki najnowszym kodem i włączyło pytest, aby również znaleźć tę najnowszą wersję.
Faustow
4

Zainstaluj pakiety w swoim wirtualnym środowisku.
Następnie uruchom nową powłokę i ponownie uruchom środowisko wirtualne.

Kjeld Flarup
źródło
1
To był mój problem: świeże zainstalować bez przeładowywania venv
zamarznięty
4

W moim przypadku wystąpił błąd importu, ponieważ pakiet wskazuje na inny pakiet / katalog o tej samej nazwie, a jego ścieżka jest o jeden poziom wyżej niż folder, który faktycznie chciałem. Myślę, że to również wyjaśnia, dlaczego niektórzy ludzie muszą usunąć _ init _.py, a inni muszą dodać ponownie.

Po prostu wstawiłem print(the_root_package.__path__)(po import the_root_package) zarówno do pythonkonsoli, jak i pytestdo skryptów, aby porównać różnicę

LINIA DOLNA: Jeśli to zrobisz python, importowany pakiet może różnić się od pakietu po uruchomieniu pytest.

JoeyZhao
źródło
2

Powyższa odpowiedź nie działa dla mnie. Właśnie go rozwiązałem, dołączając bezwzględną ścieżkę modułu, którego nie znaleziono, sys.pathna górze test_xxx.py(twojego modułu testowego), na przykład:

import sys
sys.path.append('path')
ZYX
źródło
1
Zamiast umieszczać te linie na górze mojego test_main.py, umieściłem go w conftest.pykatalogu testowym i zadziałało. Dziękujemy za dostarczenie programowego rozwiązania zamiast zaśmiecania plików.
Cameron Hudson
2

Jeśli jest to związane z kodem Pythona, który został pierwotnie opracowany w Pythonie 2.7, a teraz został przeniesiony do Pythona 3.x, to prawdopodobnie problem jest związany z problemem z importem.

np. podczas importu obiektu z pliku: basektóry znajduje się w tym samym katalogu to zadziała w Pythonie 2.x:

from base import MyClass

w pythonie 3.x powinieneś zamienić na basepełną ścieżkę lub .base nie zrobienie tego spowoduje powyższy problem. więc spróbuj:

from .base import MyClass
Amit Talmor
źródło
2

Doświadczyłem dzisiaj tego problemu i rozwiązałem go, dzwoniąc python -m pytestz katalogu głównego mojego projektu.

Dzwonienie pytestz tej samej lokalizacji nadal powodowało problemy.

Mój projekt jest zorganizowany jako:

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

Moduł routeszostał zaimportowany w moim test_routes.pyjako:from server.routes.routes import Routes

Mam nadzieję, że to pomoże!

matt6frey
źródło
Dzięki za przypomnienie, kiedyś musiałem używać triku i jest w pytest dokumentacji.
Jason R Stevens CFA
1

Inny szczególny przypadek:

Miałem problem z używaniem toksyny. Więc mój program działał dobrze, ale testy przez toksykologię narzekały. Po zainstalowaniu pakietów (potrzebnych dla programu) należy dodatkowo określić pakiety używane w unittestach w tox.ini

[testenv]
deps =
    package1
    package2 
...
martin.zaenker
źródło
1

Otrzymywałem to za pomocą VSCode. Mam środowisko Conda. Nie sądzę, aby rozszerzenie VScode w Pythonie mogło zobaczyć aktualizacje, które robiłem.

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:

Musiałem biec pip install ./ --upgrade

Bryg
źródło
To polecenie pip zwraca błąd:Directory './' is not installable. Neither 'setup.py' nor 'pyproject.toml' found.
Derek
1

Edytuj swój conftest.py i dodaj następujące wiersze kodu:

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

A jeśli próbujesz uruchomić przypadek testowy przez terminal, użyj następującego przykładu:

python -m pytest test_some_step_file_steps.py --html=HTML_step_file_output.html --self-contained-html
Siddharth Singh
źródło
NameError: name 'file' is not defined- czemu plik powinien równać się?
Koshmaar
1

Kolejna ogromna wygrana dla systemu importu Pythona. Myślę, że powodem braku konsensusu jest to, że to, co działa, zależy prawdopodobnie od twojego środowiska i narzędzi, których używasz.

Używam tego z VS Code, w eksploratorze testów pod Windows w środowisku Conda, Python 3.8.

Konfiguracja, którą mam do pracy, to:

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

W tej konfiguracji funkcja Intellisense działa, podobnie jak test wykrywania.

Zauważ, że początkowo próbowałem następujących rozwiązań, zgodnie z zaleceniami tutaj .

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

Nie mogłem znaleźć sposobu, aby to zadziałało z VS Code, ponieważ srcfolder po prostu zepsuł umysł systemu importu. Mogę sobie wyobrazić, że jest sposób, aby to zadziałało z wiersza poleceń. Jako stosunkowo nowy konwerter na programowanie w Pythonie, daje mi to nostalgiczne uczucie pracy z COM, ale jest nieco mniej przyjemne.

satnhak
źródło
1

Moje 2 centy na tym: pytest nie powiedzie się przez przypadek, jeśli nie używasz środowisk wirtualnych. Czasami to po prostu zadziała, czasami nie.

Dlatego rozwiązaniem jest:

  • usuń pytest z pip uninstall
  • stwórz swój venv
  • aktywuj wenv
  • pip zainstaluj ścieżkę projektu w trybie edytowalnym, więc pytest będzie traktowana jako moduł (w przeciwnym razie pytest nie znajdzie wewnętrznych importów). Będziesz potrzebował do tego pliku setup.py
  • zainstaluj swoje pakiety, w tym pytest
  • na koniec przeprowadź testy

Kod przy użyciu programu 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

I wreszcie

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

Przykład setup.py dla 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
źródło
1

Nie zgadzam się z postami mówiącymi, że musisz usunąć wszelkie __init__.pypliki. Zamiast tego musisz zmienić plik sys.path.

Przeprowadź eksperyment, w którym drukujesz sys.pathpodczas normalnego uruchamiania kodu. Następnie wydrukuj sys.pathpodczas uruchamiania kodu przez pytest. Myślę, że przekonasz się, że jest różnica między tymi dwiema ścieżkami, stąd dlaczego pytest przerywa.

Aby to naprawić, wstaw ścieżkę z pierwszego eksperymentu do zerowego indeksu drugiego.

Niech '/usr/exampleUser/Documents/foo'będzie pierwszym elementem print(sys.path)eksperymentu 1.

Poniżej znajduje się kod, który powinien rozwiązać Twój problem:

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

Umieść to na początku pliku, przed faktycznym oświadczeniem o imporcie.

Źródło: sam sobie z tym radziłem i powyższy proces rozwiązał.

th3lourde
źródło
1

Zachowałem wszystko tak samo i po prostu dodałem pusty plik testowy w folderze głównym. Rozwiązany

Oto ustalenia, ten problem naprawdę mnie trapił przez jakiś czas. Moja struktura folderów była

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

i pytest narzekałby na ModuleNotFoundError i dał WSKAZÓWKĘ - upewnij się, że testowe moduły / pakiety mają prawidłowe nazwy w Pythonie.

Wprowadziłem próbny plik testowy na tym samym poziomie co mathsapp i katalog testing. Plik nie zawierał nic. Teraz pytest nie narzeka.

Wynik bez pliku

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

Wyniki z plikiem

$ 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
źródło
to działało dla mnie po długim czasie z tym problemem. wygląda na to, że pytest traktuje katalog główny projektu tak, jakby znalazł pierwszy plik testowy? na pewno jest to błąd?
oooyaya
1

Rozwiązałem problem, ustawiając PYTHONPATHzmienne środowiskowe dla określonej konfiguracji, z którą przeprowadzam testy.

Podczas przeglądania pliku testowego w PyCharm:

  1. Ctrl+ Shift+A
  2. Rodzaj Edit Configurations
  3. Ustaw w PYTHONPATHobszarze Środowisko> Zmienne środowiskowe.
Ece Tavasli
źródło
1

Po prostu umieść pusty conftest.pyplik w katalogu głównym projektu, ponieważ kiedy pytestodkryje conftest.py, modyfikuje sys.path, aby mógł importować rzeczy z conftestmodułu. Ogólna struktura katalogów może być:

Root
├── conftest.py
├── module1
   ├── __init__.py
   └── sample.py
└── tests
    └── test_sample.py
Abdul Rehman
źródło
1

Miałem podobny problem i zadziałało, gdy dodałem __init__.pyplik w katalogu testing.

Chetan G. Bendre
źródło
0

Może się zdarzyć, że Pytest nie czyta pakietu jako modułu Pythona, podczas gdy Python to (prawdopodobnie z powodu problemów ze ścieżką). Spróbuj zmienić katalog skryptu pytest lub jawnie dodaj moduł do pliku PYTHONPATH.

Lub może być tak, że masz dwie wersje Pythona zainstalowane na swoim komputerze. Sprawdź źródło języka Python pod kątem pytest i uruchomionej powłoki języka Python. Jeśli są różne (np. Python 2 vs 3), użyj, source activateaby upewnić się, że uruchamiasz pytest zainstalowany dla tego samego języka Python, w którym jest zainstalowany moduł.

tooty44
źródło
0

Dla każdego, kto próbował wszystkiego i nadal otrzymywał błędy, mam obejście.

W folderze, w którym jest zainstalowany pytest , przejdź do folderu pytest-env .

Otwórz plik pyvenv.cfg .

W pliku zmiana include-system-site-packages z false na true .

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

Mam nadzieję, że to zadziała. Nie zapomnij o głosowaniu.

Charan Reddy
źródło
0

Jeśli masz już pliki .pyc, spróbuj je usunąć.

Dziś napotykam ten problem, oto co się stało:

najpierw uruchamiam pytest w mac (to wygeneruje pliki pyc), potem uruchamiam kontener docker (system operacyjny jest alpine), z zamontowanym katalogiem projektu, a potem, gdy próbuję uruchomić pytest w kontenerze, pojawia się ImportError. po wyczyszczeniu wszystkich plików pyc nie ma już błędów.

Mam nadzieję, że to może być pomocne.

接口 夏季
źródło
0

jeśli potrzebujesz pliku init .py w swoim folderze, wykonaj kopię folderu i usuń z niego plik init .py, aby uruchomić testy, działa on dla projektów lokalnych. Jeśli chcesz regularnie uruchamiać test, sprawdź, czy możesz przenieść swój init .py do oddzielnego pliku.

nchil
źródło
0

[Rozwiązane] Zanim przejdziemy bezpośrednio do rozwiązania usuwania / dodawania __init__.py, możemy również chcieć przyjrzeć się, jak import został wykonany w Twoich klasach. Właściwie straciłem dzień na zabawie __init__.pymyśląc, że to może być problem :) Jednak to było dość pouczające.

W moim przypadku był to niewłaściwy sposób wywoływania klas z jednej klasy Pythona do innej, która była rzucana ImportError. Naprawiono sposób wywoływania klas / modułów i działało to jak urok. Mam nadzieję, że to pomoże również innym.

I tak, dla podobnego błędu możemy mieć różne rozwiązania w zależności od tego, jak kod jest napisany. Lepiej poświęcić więcej czasu na samodzielne debugowanie. Wyciągnięta lekcja :) Miłego kodowania !!!

nullcode
źródło
1
Czy możesz podać przykłady niewłaściwego i właściwego sposobu?
Lurifaxel
0

W moim przypadku pracuję w kontenerze i niestety pytest ma tendencję do używania pythona2.7 zamiast mojego wybranego interpretera python3.

W moim przypadku to zadziałało:

python3 -m pytest

Moja struktura folderów

/
app/
-module1.py
-module2.py
-tests/
--test_module1.py
--test_module2.py
requirements.txt
README.md
Patrick
źródło
-1

Umieściłem wszystkie moje testy w folderze testów i otrzymywałem ten sam błąd. Rozwiązałem to, dodając init .py w tym folderze w następujący sposób:

.
|-- 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
źródło