pytest не може імпортувати модуль, поки python може


115

Я працюю над пакетом в Python. Я використовую virtualenv. Я встановив шлях до кореня модуля в .pth шляху у своєму virtualenv, щоб я міг імпортувати модулі пакета під час розробки коду та робити тестування (Питання 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)? Я googled і переповнював стек помилкою "ImportError: не можна імпортувати" для PyTest, але отримані звернення стосувалися відсутнього шляху до пітону та виправлення цього, що, здається, тут не є проблемою. Будь-які пропозиції?

Відповіді:


118

Знайшов відповідь:

НЕ кладіть __init__.pyфайл у папку, що містить TESTS, якщо ви плануєте використовувати pytest. У мене був один такий файл, видалення його вирішило проблему.

Це насправді було поховано у коментарях до другої відповіді на питання PATH з pytest 'ImportError: Немає модуля з іменем YadaYadaYada', тому я його не бачив, сподіваюсь, що він отримає тут більше видимості.


44
Смішно. У мене була така ж проблема, і мені довелося додати init .py до своєї тестової папки.
Єв.

5
Так, це не загальне рішення (навіть якщо це було у вашому випадку), щоб зрозуміти , чому це повинно бути прочитано: docs.pytest.org/en/latest/goodpractices.html#test-package-name
хуан

1
Ця інформація помилкова та оманлива! Після додавання init .py до тестової папки все працювало нормально
Леонардо Остан

1
@LeonardoOstan це може бути неправильно для вас, але це не означає, що ця інформація взагалі неправильна. У моєму випадку це питання вирішило.
Desprit

80

Я не можу сказати, що я розумію, чому це працює, але у мене була така ж проблема, і тести працюють добре, якщо я запускаю 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.
Небулосар

12
одна з причин може полягати в тому, що python -m pytest [...]"також додасть поточний каталог у sys.path".
мінус

Так само було в Windows 10, і запущений python -m pytest вирішив це
Duccio

Це спрацювало і в моєму віртуальному середовищі, з яким я мав працюватиpython3 -m pytest
Ріші Радж

На основі коментаря @minusf, який я використовую PYTHONPATH=.:./src pytestв якості цілі.
Ян Грот

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 буде в / тести не корінь
Аарон Макміллін

Отримання файлу conftest.py до кореневого каталогу також виправило його. Не майте файлу init .py у каталозі тестів
оновіть

2
Це рішення працювало для мене, але хтось знає, що це призведе до помилки імпорту?
Aldo Okware

19

У мене була така ж проблема, але з іншої причини, ніж згадані:

У мене був встановлений py.test у всьому світі, тоді як пакети були встановлені у віртуальному середовищі.

Рішенням було встановлення pytestу віртуальному середовищі. (У випадку, якщо ваша оболонка має виконавчі файли, як це робить Bash, використовуйте hash -rабо використовуйте повний шлях до py.test)


2
Щойно зрозумів, що у мене таке ж підступне питання, що використовує анаконда. Я забув додати pytestу virtualenv, створений conda, але pytestвін доступний у кореневому середовищі анаконди. Тому можна знайти pytest , але не будь-який пакет, встановлений у середовищі.
Overdrivr

1
У мене було те саме питання. pytest був встановлений у всьому світі, а не у virtualenv. pip3 install pytestвсередині virtualenv виправлено це питання.
Анкіт Сінгх

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. При запуску інтерпретатора python він знайшов би оновлений код, але pytest продовжував би знаходити код таким, який був під час першого встановлення бібліотеки. Запуск pip install ./ --upgradeоновив встановлену версію lib з останнім кодом і дозволив pytest знайти і цю останню версію.
FaustoW

4

У моєму випадку помилка імпорту сталася через те, що пакет вказує на інший пакет / каталог з тим самим іменем, і його шлях знаходиться на один рівень вище папки, яку я насправді хотів. Я думаю, це також пояснює, чому деяким людям потрібно видалити _ init _.py, а іншим потрібно додати назад.

Я просто ставлю print(the_root_package.__path__)(після import the_root_package) і в pythonконсоль, і в pytestсценарії, щоб порівняти різницю

LOT BOTTOM: Коли ви працюєте python, пакет, який ви імпортуєте, може відрізнятися від пакета під час запуску pytest.


3

Встановіть пакети у своє віртуальне середовище.
Потім знову запустіть нову оболонку та створіть своє віртуальне середовище


1
Це була моя проблема: свіжа установка без перезавантаження вентиляції
заморожена

2

Відповідь вище не працює для мене. Я просто вирішив це, додавши абсолютний шлях модуля, який не знайдений до sys.pathвершини test_xxx.py(ваш тестовий модуль), наприклад:

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

1
Замість того, щоб ставити ці рядки у верхній частині мого test_main.py, я помістив його conftest.pyу свій тестовий каталог, і він спрацював. Дякуємо за надання програмного рішення замість файлу.
Камерон Хадсон

2

Якщо він пов'язаний з кодом python, який був спочатку розроблений в python 2.7 і тепер мігрував у python 3.x, проблема, ймовірно, пов'язана з проблемою імпорту.

наприклад, при імпорті об'єкта з файлу: 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

Сподіваюся, що це допомагає!


Дякую за нагадування, мені довелося скористатися фокусом у минулому, і це в документації пістетів.
Джейсон Р Стівенс CFA

1

Ще один особливий випадок:

У мене виникли проблеми з використанням токсину. Таким чином, моя програма пройшла нормально, але unittests через токси продовжували скаржитися. Після встановлення пакетів (необхідних для програми) вам потрібно додатково вказати пакети, які використовуються в тестових одиницях, в токси.ini

[testenv]
deps =
    package1
    package2 
...

1

Я отримував це за допомогою VSCode. У мене є кондиція. Я не думаю, що розширення 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.
Дерек

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, у тестовому провіднику під Windows у конденсаційному середовищі, Python 3.8.

Я повинен працювати:

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

У рамках цієї установки працює intellisense, а також тестове виявлення.

Зауважте, що я спочатку спробував наступне, як тут рекомендовано .

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

Я не міг знайти спосіб працювати з VS Code, оскільки ця srcпапка просто підірвала розум системи імпорту. Я можу уявити, що існує спосіб змусити це працювати з командного рядка. Як відносно нове перетворення в програмування Python, це дає мені ностальгічне відчуття роботи з COM, але бути трохи менш цікавим.


1

Мої 2 копійки на це: pytest вийде з ладу випадково, якщо ви не використовуєте віртуальні середовища. Іноді це просто спрацює, іноді ні.

Тому рішення таке:

  • видалити pytest за допомогою видалення pip
  • створіть свій венв
  • активуйте свій вену
  • pip встановіть ваш проектний шлях у редагованому режимі, тому пірест буде розглядатися як модуль (інакше 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"

Приклад setup.py для установки pip -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

Я не погоджуюся з публікаціями, які стверджують, що ви повинні видалити будь-які __init__.pyфайли. Замість цього потрібно змінити sys.path.

Запустіть експеримент, де ви друкуєте, sys.pathколи нормально запускаєте код. Потім друкуйте sys.pathпід час запуску коду через 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 та каталог тестів. У файлі нічого не було. Зараз пітест не скаржиться.

Результат без файлу

$ 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файл у каталог тестів


0

Можливо, Pytest не читає пакунок як модуль Python, поки Python є (ймовірно, через проблеми із шляхами). Спробуйте змінити каталог сценарію pytest або додати модуль явно у ваш PYTHONPATH.

Або може бути, що у вас на машині встановлені дві версії Python. Перевірте джерело Python на наявність pytest та наявну оболонку python. Якщо вони різні (тобто Python 2 проти 3), source activateпереконайтеся, що ви запускаєте pytest, встановлений для того самого python, у якому встановлений модуль.


0

Для всіх, хто намагався все, і все ще отримує помилку, у мене є робота.

У папці, де встановлено pytest , перейдіть до папки pytest-env .

Відкрийте файл pyvenv.cfg .

У зміну файлу включаються-system-site-пакети від false до true .

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

Сподіваюся, що це працює. Не забудьте проголосувати.


0

Якщо у вас вже є .pyc файли, спробуйте видалити їх.

Сьогодні я стикаюся з цією проблемою, ось що відбувається:

спочатку я запускаю pytest в mac (це генерує файли pyc), потім я запускаю контейнер docker (ОС альпійський), з встановленим dir проектом, а потім, коли я намагаюся запустити pytest в контейнер, відбувається ImportError. після очищення всіх файлів Pyc більше не виникає помилок.

Сподіваюсь, це може бути корисним.


0

якщо вам потрібен файл init .py у своїй папці, скопіюйте папку та видаліть init .py у цій тесті, щоб запустити свої тести, вона працює для місцевих проектів. Якщо вам потрібно запустити тест регулярно побачити , якщо ви можете перемістити ініціалізації .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

Я розмістив усі свої тести в тестовій папці і отримав ту саму помилку. Я вирішив це, додавши 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.