Jak dodać moduł Python do syspath?

69

Mam taką strukturę plików:

Folder
   Common
      foo1.py
   TestFolder
      foo2.py

Chcę zaimportować do foo2.py i foo1.py. Próbowałem, ale nie działa na Ubuntu:

sys.path.append(os.path.abspath('../../'))
from Common import foo1.py
użytkownik 284474
źródło
Czy masz __init__.pyplik w swoim folderze? w ten sposób Python tworzy pakiety i pozwala importować moduły z tego pakietu. guide.python-distribute.org/creation.html
Bryan
Mam plik init.py we wspólnej i w folderze TestFolder
284474
potrzebujesz go w katalogu Folder, a także w podfolderach, jeśli chcesz zaimportować
Bryan
Ten plik inicjujący .py jest pusty?
user284474
1
tak, może być pusty. Chyba że potrzebujesz określonej konfiguracji pakietu, ale powinieneś być w porządku z pustym
Bryan

Odpowiedzi:

115

Jak Python znajduje swoje moduły

Ściśle biorąc, moduł jest pojedynczym plikiem Pythona, podczas gdy pakiet jest folderem zawierającym pliki Pythona, któremu towarzyszy plik (może być pusty) o nazwie __init__.py, który informuje Pythona, że ​​jest to pakiet do importowania modułów. W obu przypadkach moduły wymagają .pyrozszerzenia, ale importowanie odbywa się bez (patrz dalej poniżej).

Domyślnie Python szuka modułów i pakietów w $PYTHONPATH.

Aby dowiedzieć się, co zawiera $ PYTHONPATH, uruchom następujący kod w python (3):

import sys
print(sys.path)

Jak dodać katalog

Sporadycznie

Z poziomu pliku Pythona możesz od czasu do czasu dodawać ścieżki do ścieżki domyślnej, dodając następujące wiersze w sekcji head aplikacji lub skryptu Python:

import sys
sys.path.insert(0, "/path/to/your/package_or_module")

Na przykład:

jeśli mam folder: /home/myname/pythonfilesi chcę zaimportować plik module_1.pyznajdujący się w tym katalogu, dodaję go do sekcji head mojego kodu:

import sys
sys.path.insert(0, "/home/myname/pythonfiles")

I mogę po prostu zaimportować plik module_1.pyprzez:

import module_1

Kiedy tworzę pakiet i chcę zaimportować moduły z pakietu, muszę utworzyć folder $PYTHONPATHzawierający moduły, któremu towarzyszy (może być pusty) plik o nazwie__init__.py

Na przykład:

Importować z pakietu (folderu), zwanego my_packagew /home/myname/pythonfiles, dodać /home/myname/pythonfilesścieżkę do Twojego $PYTHONPATH, jak w przykładzie 1, a następnie zaimportować moduł o nazwie module_2.py(wewnątrz folderu pakietu) po prostu z: `

from <packagename> import module_2

Dodawanie katalogów na $PYTHONPATHstałe:

Dodaj następujący wiersz do ~/.profilepliku.

export PYTHONPATH=$PYTHONPATH:/path/you/want/to/add

Podkatalogi

Z poziomu pakietu podkatalogi nie są tak uwzględnione; musisz „połączyć” katalogi. Aby zaimportować moduł module_3.py, wewnątrz folderu subfolderw folderze packagename:

import packagename.subfolder.module_3

Biorąc pod uwagę fakt, że wszystkie podfoldery w pakiecie zawierają własny __init__.pyplik.

Gdy moduł znajduje się w tym samym katalogu co skrypt lub aplikacja

Nie ma potrzeby wstawiania ścieżki do modułu, gdy znajduje się on w tym samym katalogu co skrypt lub aplikacja, jest on automatycznie dodawany.

Przykład:

Jeśli mam folder zawierający script.pyi module.py, mogę po prostu zaimportować moduł poprzez:

import module
Jacob Vlijm
źródło
Chciałbym również zasugerować przeczytanie python.org/dev/peps/pep-0328 , szczególnie jeśli celujesz w Python 3 (lub planujesz celować w przyszłości)
zaadeh
Dlaczego printenv PYTHONPATHnic
Stevie G,
1
sys.path.append("/path/to/your/package_or_module")dodaje również ścieżkę do wartości domyślnej i jest mniej myląca. W porównaniu z sys.path.insert(0,...)tym ma 0jako pierwszy argument.
Paul Rougieux
1
@PaulRougieux: Problem z dołączaniem do ścieżki polega na tym, że moduł może już istnieć gdzie indziej na ścieżce (na przykład w pliku .egg), a ty wybierzesz wersję modułu zamiast tej z pliku.
snark
6

Prawidłowy sposób użycia importu względnego to:

from ..Common import foo1

I potrzebujesz również __init__.pywe wszystkich swoich folderach.

Sylvain Pineau
źródło
1
Dzięki. Ale jeśli mam moduł składający się z dwóch folderów, w jaki sposób mogę go zaimportować? od .... Folder nie działa
284474
Czy to działa z jednym poziomem?
Sylvain Pineau
Działa z jednym poziomem.
user284474
ok, czy mógłbyś zaakceptować tę odpowiedź? w przypadku wersji wielopoziomowej możesz zadać inne pytanie, ale najpierw zapoznaj się z tym pytaniem i odpowiedzią na najlepszy sposób wywołania modułów w pakiecie
Sylvain Pineau
Czy dotyczy to Pythona 2 lub Pythona 3? Lub obydwa?
alex
2

Uwaga: Ta odpowiedź jest nieaktualna dla najnowszej wersji Pythona 3, ale jest dostępna dla wcześniejszej wersji. Aby uzyskać więcej informacji, przeczytaj komentarze i https://www.python.org/dev/peps/pep-0420/


Zasadniczo każdy folder z kodem python, który chcesz dodać do ścieżki syspath, potrzebuje pliku __init__.py. Te pliki __init__.py mogą być puste.

don.joey
źródło
Rozumiem, że tak już nie jest, katalog staje się teraz „przestrzenią nazw”.
Aaron Hall,
@AaronHall ciekawe, źródło?
don.joey
1
Wypróbuj to jako dowód: python -c "from pathlib import Path; Path('ns').mkdir(); Path('ns/mod.py').write_text('''print('mod.py')'''); import ns.mod; from shutil import rmtree; rmtree('ns')"tutaj jest także odpowiednia dokumentacja, PEP 420, która opisuje dodanie semantyki pakietu przestrzeni nazw
Aaron Hall