Jak naprawić błąd „ImportError: brak modułu o nazwie…” w Pythonie?

115

Jaki jest właściwy sposób naprawienia tego błędu ImportError?

Mam następującą strukturę katalogów:

/home/bodacydo
/home/bodacydo/work
/home/bodacydo/work/project
/home/bodacydo/work/project/programs
/home/bodacydo/work/project/foo

Jestem w katalogu

/home/bodacydo/work/project

Teraz, jeśli napiszę

python ./programs/my_python_program.py

Natychmiast rozumiem

ImportError: No module named foo.tasks

./programs/my_python_program.pyZawiera następujący wiersz:

from foo.tasks import my_function

Nie mogę zrozumieć, dlaczego Python nie znajdzie ./foo/tasks.py- jest.

Jeśli zrobię to z powłoki Pythona, to działa:

python
>>> from foo.tasks import my_function

Nie działa tylko wtedy, gdy wywołuję to za pomocą python ./programs/my_python_program.pyskryptu.

bodacydo
źródło

Odpowiedzi:

121

Python nie dodaje bieżącego katalogu sys.path, ale raczej katalog, w którym znajduje się skrypt. Dodaj /home/bodacydo/work/projectdo albo sys.pathlub $PYTHONPATH.

Ignacio Vazquez-Abrams
źródło
9
Więc jaki jest sens posiadania pliku init .py w folderze głównym? Wydaje się, że nie ma to sensu, jeśli edytujesz sys.path lub pythonpath.
11
@Editor: __init__.pywskazuje, że katalog powinien być traktowany jako pakiet, gdy jego element nadrzędny sys.pathznajduje się w pakiecie lub sam jest pakietem.
Ignacio Vazquez-Abrams
3
Ponadto sprawdź uprawnienia do folderu. To był problem w moim przypadku.
SidJ
15
Aby dodać aktualny export PYTHONPATH=`pwd`
katalog
1
/home/bodacydo/work
Pomogło
33

Czy masz plik o nazwie __init__.pyw katalogu foo? Jeśli nie, to python nie rozpozna foo jako pakietu Pythona.

Zobacz sekcję dotyczącą pakietów w samouczku Pythona, aby uzyskać więcej informacji.

Dave Kirby
źródło
Dzięki i tak, miałem __init__.py. Tym razem był problem $PYTHONPATH. Rozwiązanie Ignacio zadziałało.
bodacydo
1
W startowych pliki .py są wymagane, aby Python traktować jak katalogi zawierające pakiety; ma to na celu zapobieganie przypadkowemu ukryciu prawidłowych modułów, które pojawiają się później na ścieżce wyszukiwania modułów, przez katalogi o wspólnej nazwie, takiej jak łańcuch. W najprostszym przypadku init .py może być po prostu pustym plikiem
panofish
Dzięki, że mnie kiedyś uratowałeś.
cpu_meltdown
9

Oto rozwiązanie krok po kroku:

  1. Dodaj skrypt o nazwie run.pyw /home/bodacydo/work/projecti edytować go tak:

    import programs.my_python_program
    programs.my_python_program.main()
    

    (zastąp main()swoją równoważną metodą w my_python_program.)

  2. Iść do /home/bodacydo/work/project
  3. Biegać run.py

Objaśnienie: Ponieważ python dołącza do PYTHONPATH ścieżkę do skryptu, z którego jest uruchamiany , uruchomiony run.pyzostanie dołączony /home/bodacydo/work/project. I voila , import foo.taskszostanie znalezione.

cyborg
źródło
8

Przykładowe rozwiązanie dodawania biblioteki do PYTHONPATH.

  1. Dodaj następujący wiersz do swojego ~ / .bashrc lub po prostu uruchom go bezpośrednio:

    export PYTHONPATH="$PYTHONPATH:$HOME/.python"
  2. Następnie połącz wymaganą bibliotekę z folderem ~ / .python, np

    ln -s /home/user/work/project/foo ~/.python/
kenorb
źródło
6

Lepiej naprawić niż ustawienie PYTHONPATHjest użyciepython -m module.path

To będzie poprawnie ustawione sys.path[0]i będzie bardziej niezawodnym sposobem wykonywania modułów.

Mam krótki opis tego problemu, ponieważ inni respondenci wspomnieli, że przyczyna tego jest python path/to/file.pyumieszczona path/tona początku PYTHONPATH( sys.path).

Anthony Sottile
źródło
2

Myślę, że muszę wziąć pod uwagę, że foofolder jest samodzielną biblioteką. Mogę rozważyć przeniesienie go do Lib\site-packagesfolderu w instalacji Pythona. Mogę rozważyć dodanie tam foo.pthpliku.

Wiem, że to biblioteka, ponieważ ./programs/my_python_program.pyzawiera następujący wiersz:

from foo.tasks import my_function

Więc nie ma znaczenia, że ./programsjest to folder rodzeństwa ./foo. To fakt, że my_python_program.pyjest uruchamiany jako taki skrypt:

python ./programs/my_python_program.py

quamrana
źródło
0

Jeśli masz ten problem podczas korzystania z zainstalowanej wersji, setup.pyupewnij się, że moduł jest zawarty w środkupackages

setup(name='Your program',
    version='0.7.0',
    description='Your desccription',
    packages=['foo', 'foo.bar'], # add `foo.bar` here
Danon
źródło