Błąd importu noska Pythona

121

Nie mogę sprawić, by struktura testowa nosa rozpoznawała moduły pod moim skryptem testowym w strukturze plików. Ustawiłem najprostszy przykład, który demonstruje problem. Wyjaśnię to poniżej.

Oto struktura pliku pakietu:

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

foo.py zawiera:

def dumb_true():
    return True

testy / test_foo.py zawiera:

import foo

def test_foo():
    assert foo.dumb_true()

Oba pliki init .py są puste

Jeśli uruchomię nosetests -vvw głównym katalogu (gdzie jest foo.py), otrzymam:

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)

Ten sam błąd pojawia się, gdy uruchamiam z katalogu tests /. Zgodnie z dokumentacją i przykładem, który znalazłem, nos ma dodać wszystkie pakiety nadrzędne do ścieżki, a także katalog, z którego jest wywoływany, ale wydaje się, że w moim przypadku tak się nie dzieje.

Używam Ubuntu 8.04 z Pythonem 2.6.2. Zbudowałem i zainstalowałem nos ręcznie (nie za pomocą setup_tools), jeśli ma to znaczenie.

halfak
źródło

Odpowiedzi:

226

Masz __init__.pyw swoim katalogu najwyższego poziomu. To sprawia, że ​​jest to pakiet. Jeśli go usuniesz, nosetestspowinno działać.

Jeśli go nie usuniesz, musisz zmienić importna import dir.foo, gdzie dirjest nazwa katalogu.

ire_and_curses
źródło
7
To dostało. Dzięki wielkie! Zagłosowałbym, ale najwyraźniej potrzebuję większej reputacji.
halfak
4
Bez obaw. Witamy w StackOverflow! Możesz zaznaczyć zielony znacznik wyboru po lewej stronie, jeśli odpowiedź rozwiąże problem.
ire_and_curses
2
@halfak: W takim razie poproś o kolejny głos za swoje pytanie. Ty też (na twoją odpowiedź), @ire.
Mark Rushakoff
1
Rozumiem. Dzięki za cynk :)
halfak
5
Mam sytuację, w której testy działają, jeśli init .py w katalogu głównym - jednak potrzebuję tego pliku i importu modeli. <model_name> nadal nie jest znaleziony. Test znajduje się w katalogu tests / , a model, który próbuję przetestować, znajduje się w katalogu models / ... każda pomoc byłaby mile widziana.
Kees Briggs
32

Czy jesteś w virtualenv? W moim przypadku nosetestsbył to ten w /usr/bin/nosetests, który używał /usr/bin/python. Pakiety w virtualenv na pewno nie będą w ścieżce systemowej. Naprawiono to:

source myvirtualenv/activate
pip install nose
which nosetests
/home/me/myvirtualenv/bin/nosetests
toppur
źródło
2
Też mój. Dziękuję, zaoszczędziłem dużo czasu.
jskulski
3
dla mnie nosetestszostał zbuforowany przez bashsystem jeden w /usr/local/bin(podczas gdy which nosetestsdawał właściwy wynik). Użyłem tego, aby to wyczyścić.
Raffi
5
Dodatkowo musiałem dezaktywować i aktywować mój virtualenv.
Bengt
Miałem problem z ustawieniem PS1 = $ {PS1: -} podczas aktywacji virtualenv (w celu przezwyciężenia błędów na nieustawionych zmiennych). Po usunięciu tego i przełączeniu na set + u nie miałem już żadnych problemów.
Juuso Ohtonen
13

Do tych z Was, którzy znajdą to pytanie później: Otrzymuję błąd importowania, jeśli nie mam pliku __init__.py pliku w katalogu testów.

Moja struktura katalogów wyglądała następująco:

./tests/
  ./test_some_random_stuff.py

Gdybym przeprowadził testy w nosie:

nosetests -w tests

To dałoby to ImportError, co widzą wszyscy inni. Jeśli dodam pusty __init__.pyplik, to działa dobrze:

./tests/
  ./__init__.py
  ./test_some_random_stuff.py
robbrit
źródło
10

Innym potencjalnym problemem są myślniki / myślniki w drzewie katalogów. Niedawno naprawiłem problem z ImportError nosa, zmieniając nazwę katalogu z sub-dirna sub_dir.

Aron Ahmadia
źródło
1
@Aman, zdajesz sobie sprawę z różnicy między identyfikatorami zmiennych a nazwami plików?
Nakilon
Tak ... zawsze mam plik podobny do FooTests.py iz jakiegoś powodu mu się nie podobał ... Zmieniłem nazwę na Foo_Tests.py i zadziałało ... wydaje się trochę wybredny.
Birdman
3

Oczywiście, jeśli masz błąd składni w importowanym module, to spowoduje to. U mnie problem rozwiał się, gdy miałem kopię zapasową pliku testów ze ścieżką taką jak module / tests.bak.py w tym samym katalogu co tests.py. Ponadto, aby poradzić sobie z problemem z pakietem / modułem init w aplikacji Django, możesz uruchomić następujące (w powłoce bash / OSX), aby upewnić się, że nie masz żadnych plików init .pyc w pobliżu:

find . -name '*.pyc' -delete
płyty
źródło
3

Otrzymałem ten komunikat o błędzie, ponieważ uruchomiłem nosetests polecenie z niewłaściwego katalogu.

Głupie, ale się zdarza.

Eyal Levin
źródło
Czy możesz dodać szczegóły do ​​swojej odpowiedzi? Z jakiego katalogu to uruchomiłeś? Dlaczego jest źle? Jaki byłby właściwy katalog? Uruchomienie nosetestsw katalogu bez żadnych testów spowoduje Ran 0 tests, a nie błąd importu. W obecnej formie ta odpowiedź nie jest przydatna.
gerrit,
2

Właśnie natknąłem się na jeszcze jedną rzecz, która może powodować ten problem: nazewnictwo testów w formularzu testname.test.py. To dodatkowo .dezorientuje nos i prowadzi do importowania rzeczy, których nie powinien. Przypuszczam, że może być oczywiste, że stosowanie niekonwencjonalnych konwencji nazewnictwa testów zepsuje sytuację, ale pomyślałem, że warto to zauważyć.

7yl4r
źródło
2

Na przykład, o następującej strukturze katalogów, jeśli chcesz uruchomić nosetestsw m1, m2lub m3do testowania niektórych funkcji n.py, należy użyć from m2.m3 import nw test.py.

m1
└── m2
    ├── __init__.py
    └── m3
        ├── __init__.py
        ├── n.py
        └── test
            └── test.py
Che-Hsun Liu
źródło
1

Aby odpowiedzieć na pytanie: Jeśli zmagasz się z taką strukturą:

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

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

A może chcesz uruchomić test ze ścieżki spoza projektu, umieść ścieżkę projektu w PYTHONPATH.

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

wklej go w swoim .profile. Jeśli znajdujesz się w środowisku wirtualnym, wklej go do aktywacji w katalogu głównym venv

Rainelz
źródło