Ошибка импорта носа Python

121

Я не могу заставить среду тестирования носа распознавать модули под моим тестовым скриптом в файловой структуре. Я привел простейший пример, демонстрирующий проблему. Я объясню это ниже.

Вот структура файла пакета:

./__init__.py
./foo.py
./tests
   ./__init__.py
   ./test_foo.py

foo.py содержит:

def dumb_true():
    return True

tests / test_foo.py содержит:

import foo

def test_foo():
    assert foo.dumb_true()

Оба файла init .py пусты

Если я запускаю nosetests -vvв основном каталоге (где находится foo.py), я получаю:

Failure: ImportError (No module named foo) ... ERROR

======================================================================
ERROR: Failure: ImportError (No module named foo)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python/site-packages/nose-0.11.1-py2.6.egg/nose/loader.py", line 379, in loadTestsFromName
    addr.filename, addr.module)
  File "/usr/lib/python/site-packages/nose-0.11.1-py2.6.egg/nose/importer.py", line 39, in importFromPath
    return self.importFromDir(dir_path, fqname)
  File "/usr/lib/python/site-packages/nose-0.11.1-py2.6.egg/nose/importer.py", line 86, in importFromDir
    mod = load_module(part_fqname, fh, filename, desc)
  File "/home/user/nose_testing/tests/test_foo.py", line 1, in <module>
    import foo
ImportError: No module named foo

----------------------------------------------------------------------
Ran 1 test in 0.002s

FAILED (errors=1)

Та же ошибка возникает при запуске из каталога tests /. В соответствии с документацией и примером, который я нашел, носитель должен добавлять все родительские пакеты в путь, а также каталог, из которого он вызывается, но в моем случае этого не происходит.

Я запускаю Ubuntu 8.04 с Python 2.6.2. Я собрал и установил нос вручную (не с помощью setup_tools), если это важно.

halfak
источник

Ответы:

226

У вас есть __init__.pyкаталог верхнего уровня. Это делает его пакетом. Если вы удалите его, ваш nosetestsдолжен работать.

Если вы не удалите его, вам придется изменить свой import на import dir.foo, где dirнаходится имя вашего каталога.

ire_and_curses
источник
7
Вот и все. Большое спасибо! Я бы проголосовал за, но, видимо, мне нужно больше репутации.
Halfak
4
Не беспокойся. Добро пожаловать в StackOverflow! Вы можете поставить галочку рядом с зеленой галочкой слева, если ответ решает вашу проблему.
ire_and_curses
2
@halfak: Тогда еще раз проголосуйте за свой вопрос. Ты тоже (на свой ответ), @ire.
Марк Рушаков
1
Понял. Спасибо за подсказку :)
Halfak
5
У меня есть ситуация, когда тесты работают, если init .py в корневом каталоге - однако мне нужно , чтобы этот файл был там, и импортировать модели. <model_name> все еще не найден. Тест находится внутри каталога tests / , а модель, которую я пытаюсь протестировать, находится внутри каталога models / ... любая помощь приветствуется.
Кис Бриггс,
32

Вы в виртуальном мире? В моем случае это nosetestsбыл тот /usr/bin/nosetests, который использовал /usr/bin/python. Пакеты в virtualenv определенно не будут в системном пути. Следующее исправило это:

source myvirtualenv/activate
pip install nose
which nosetests
/home/me/myvirtualenv/bin/nosetests
toppur
источник
2
Тоже мое. Спасибо, сэкономили много времени.
jskulski
3
для меня nosetestsбыл кеширован bashв системный /usr/local/bin(пока which nosetestsдавал правильный результат). Я использовал это, чтобы очистить его.
Раффи
5
Кроме того, мне пришлось деактивировать и активировать мой файл virtualenv.
Bengt
У меня была проблема с PS1 = $ {PS1: -}, установленным при активации virtualenv (для преодоления ошибок на неустановленных переменных). После удаления этого и переключения на set + u у меня больше не было проблем.
Juuso Ohtonen
13

Для тех из вас, кто позже найдет этот вопрос: я получаю сообщение об ошибке импорта, если у меня нет __init__.pyфайла в моем каталоге тестов.

Моя структура каталогов была такой:

./tests/
  ./test_some_random_stuff.py

Если я пробежал носовые тесты:

nosetests -w tests

Это даст то, ImportErrorчто видят все остальные. Если я добавлю пустой __init__.pyфайл, он будет работать нормально:

./tests/
  ./__init__.py
  ./test_some_random_stuff.py
robbrit
источник
10

Другая потенциальная проблема - дефисы / тире в дереве каталогов. Недавно я исправил ошибку ImportError в носу, переименовав каталог с sub-dirв sub_dir.

Арон Ахмадиа
источник
1
@Aman, вы понимаете разницу между идентификаторами переменных и именами файлов?
Nakilon
Да ... У меня всегда есть файл, похожий на FooTests.py, и он по какой-то причине не нравился ... Я переименовал его в Foo_Tests.py, и он работал ... кажется немного привередливым.
Birdman
3

Конечно, это может быть вызвано синтаксической ошибкой в ​​импортируемом модуле. Для меня проблема возникла, когда у меня была резервная копия файла тестов с таким путем, как module / tests.bak.py, в том же каталоге, что и tests.py. Кроме того, чтобы разобраться с init проблемой пакета / модуля в приложении Django, вы можете запустить следующее (в оболочке bash / OSX), чтобы убедиться, что у вас нет никаких файлов init .pyc:

find . -name '*.pyc' -delete
варочные панели
источник
3

Я получил это сообщение об ошибке, потому что запустил nosetests команду из неправильного каталога.

Глупо, но бывает.

Эяль Левин
источник
Не могли бы вы добавить некоторые подробности к своему ответу? Из какого каталога вы его запускали? Почему это неправильно? Какой каталог будет правильным? Запуск nosetestsв каталоге без каких-либо тестов приведет к Ran 0 testsошибке импорта. В нынешнем виде этот ответ бесполезен.
gerrit
2

Я только что столкнулся с еще одной вещью, которая могла вызвать эту проблему: именование тестов в форме testname.test.py. Это лишнее .сбивает с толку и приводит к тому, что он импортирует то, чего не следует. Я полагаю, что может быть очевидно, что использование нетрадиционных соглашений об именах тестов сломает ситуацию, но я подумал, что это стоит отметить.

7yl4r
источник
2

Например, со следующей структурой каталогов, если вы хотите работать nosetestsв m1, m2или m3проверить некоторые функции в n.py, вы должны использовать from m2.m3 import nв test.py.

m1
└── m2
    ├── __init__.py
    └── m3
        ├── __init__.py
        ├── n.py
        └── test
            └── test.py
Че-Сюнь Лю
источник
1

Просто завершу вопрос: если вы боретесь с такой структурой:

project
├── m1
    ├── __init__.py
    ├── foo1.py
    └──m2
       ├── __init__.py
       └── foo2.py

└── test
     ├── __init__.py
     └── test.py

И, возможно, вы хотите запустить тест из пути за пределами проекта, включив путь к проекту в свой PYTHONPATH.

export PYTHONPATH=$PYTHONPATH:$HOME/path/to/project

вставьте его в свой .profile. Если вы находитесь в виртуальной среде, вставьте его в активировать в корень venv.

Rainelz
источник