Rozwiń ścieżkę wyszukiwania Pythona do innego źródła
107
Właśnie dołączyłem do projektu z dość dużą istniejącą bazą kodu. Rozwijamy się w Linuksie i nie używamy i IDE. Przechodzimy przez wiersz poleceń. Próbuję dowiedzieć się, jak sprawić, by Python szukał właściwej ścieżki, gdy uruchamiam moduły projektu. Na przykład, gdy uruchamiam coś takiego:
python someprojectfile.py
dostaję
ImportError: no module named core.'somemodule'
Dostaję to dla wszystkich moich importów do, zakładam, że jest to problem ze ścieżką.
TLDR:
Jak sprawić, by Python przeszukał ~/codez/project/i wszystkie pliki i foldery dla plików * .py podczas importowania instrukcji.
Ustaw zmienną środowiskową PYTHONPATHna listę katalogów oddzielonych dwukropkami, aby wyszukać zaimportowane moduły.
W swoim programie użyj, sys.path.append('/path/to/search')aby dodać nazwy katalogów, których Python ma wyszukiwać zaimportowane moduły. sys.pathto tylko lista katalogów przeszukiwanych przez Pythona za każdym razem, gdy zostanie poproszony o zaimportowanie modułu, i możesz go zmienić w razie potrzeby (chociaż nie polecałbym usuwania żadnego ze standardowych katalogów!). Wszystkie katalogi, które umieścisz w zmiennej środowiskowej, PYTHONPATHzostaną wstawione sys.pathpodczas uruchamiania Pythona.
Służy site.addsitedirdo dodawania katalogu do sys.path. Różnica między tym a zwykłym dołączaniem polega na tym, że kiedy używasz addsitedir, szuka on również .pthplików w tym katalogu i używa ich do ewentualnego dodania dodatkowych katalogów na sys.pathpodstawie zawartości plików. Więcej szczegółów można znaleźć w dokumentacji.
Który z nich chcesz użyć, zależy od Twojej sytuacji. Pamiętaj, że kiedy dystrybuujesz swój projekt do innych użytkowników, zazwyczaj instalują go w taki sposób, że pliki kodu Pythona zostaną automatycznie wykryte przez importera Pythona (tj. Pakiety są zwykle instalowane w site-packageskatalogu), więc jeśli będziesz bałaganić sys.pathw swoim kodzie , może to być niepotrzebne, a nawet może mieć niekorzystne skutki, gdy ten kod zostanie uruchomiony na innym komputerze. Jeśli chodzi o programowanie, zaryzykowałbym przypuszczenie, że ustawienie PYTHONPATHjest zwykle najlepszym sposobem.
Jednak gdy używasz czegoś, co działa tylko na twoim komputerze (lub gdy masz niestandardowe konfiguracje, np. Czasami w ramach aplikacji internetowych), nie jest niczym niezwykłym wykonanie czegoś takiego jak
Więc gdybym miał 15 podkatalogów, musiałbym dodawać każdy z nich indywidualnie?
themaestro
i czy możesz podać przykład argumentu wiersza poleceń do zmiany PYTHONPATH?
themaestro
3
Aby ustawić PYTHONPATH: w .bashrclub jakimkolwiek pliku startowym używanym przez powłokę (jeśli nie jest to Bash), napisz export PYTHONPATH=$PYTHONPATH:$HOME/codez/project. Ale jeśli masz kilka podkatalogów, zrobiłbym .pthplik i użył site.addsitedir. Możesz utworzyć moduł, sitecustomizektóry może wywołać tę funkcję za Ciebie; spróbuj umieścić go w ~/.local/lib/python2.6/sitecustomize.py(zastąp swoją wersję Pythona), aby mieć nadzieję, że zostanie automatycznie zaimportowany.
David Z
Umieściłem następujący w moim pliku .bashrc i nadal nie mam szczęścia z tym importem. Jakieś pomysły? Jak mimo wszystko utworzyłbym plik .pth? export PYTHONPATH = $ PYTHONPATH: $ HOME / adaifotis / codez / export PYTHONPATH = $ PYTHONPATH: $ HOME / adaifotis / codez / project export PYTHONPATH = $ PYTHONPATH: $ HOME / adaifotis / PYTHONPATH = $ PYTHON / projekt HOME / adaifotis / codez / project / proxies export PYTHONPATH = $ PYTHONPATH: $ HOME / adaifotis / codez / project / conf
themaestro
Spróbuj otworzyć terminal i uruchomić echo $PYTHONPATH. Jeśli zmienna środowiskowa została ustawiona poprawnie, powinieneś zobaczyć listę katalogów oddzielonych dwukropkami. Aby uzyskać informacje o .pthplikach, zapoznaj się z dokumentacją sitemodułu, do którego dołączyłem w mojej odpowiedzi. Informuje, jaka powinna być zawartość i jak z niej korzystać.
Z twojego przykładu domyślam się, że naprawdę masz paczkę pod adresem ~/codez/project. Plik __init__.pyw katalogu języka Python mapuje katalog na przestrzeń nazw. Jeśli wszystkie Twoje podkatalogi mają __init__.pyplik, wystarczy dodać katalog podstawowy do pliku PYTHONPATH. Na przykład:
PYTHONPATH = $ PYTHONPATH: $ HOME / adaifotis / project
Oprócz testowania zmiennej środowiskowej PYTHONPATH, jak wyjaśnia David, możesz przetestować ją w Pythonie w następujący sposób:
$ python>>>import project # should work if PYTHONPATH set>>>import sys>>>for line in sys.path:print line # print current python path
Możesz wstawić __init__.pyznaki odwrotne, aby było jasne, że naprawdę masz na myśli __init__.py, w przeciwieństwie do init.py. Tylko po to, aby uniknąć mylących nowicjuszy. :)
antred
4
Wiem, że ten wątek jest trochę stary, ale zajęło mi trochę czasu, zanim dotarłem do jego sedna, więc chciałem się nim podzielić.
W moim projekcie główny skrypt miałem w katalogu nadrzędnym i aby rozróżnić moduły, umieściłem wszystkie moduły pomocnicze w podfolderze o nazwie „moduły”. W moim głównym skrypcie importuję te moduły w następujący sposób (dla modułu o nazwie report.py):
from modules.report import report, reportError
Jeśli zadzwonię do mojego głównego skryptu, to działa. JEDNAK chciałem przetestować każdy moduł, dodając jeden main()do każdego i wywołując każdy bezpośrednio, jako:
python modules/report.py
Teraz Python skarży się, że nie może znaleźć „modułu o nazwie moduły”. Kluczowe jest tutaj to, że Python domyślnie zawiera folder skryptu w swojej ścieżce wyszukiwania, ALE NIE CWD. Tak więc ten błąd mówi tak naprawdę: „Nie mogę znaleźć podfolderu modułów”. Dzieje się tak, ponieważ w katalogu, w którym znajduje się moduł report.py, nie ma podkatalogu „modules”.
Uważam, że najlepszym rozwiązaniem jest dołączenie CWD w ścieżce wyszukiwania Pythona, umieszczając to na górze:
import sys
sys.path.append(".")
Teraz Python przeszukuje CWD (katalog bieżący), znajduje podfolder „modules” i wszystko jest w porządku.
Przeczytałem to pytanie, szukając odpowiedzi, i nie podobało mi się żadne z nich.
Napisałem więc szybkie i brudne rozwiązanie. Po prostu umieść to gdzieś w sys.path, a doda dowolny katalog w folder(z bieżącego katalogu roboczego) lub w abspath:
#using.pyimport sys, os.path
def all_from(folder='', abspath=None):"""add all dirs under `folder` to sys.path if any .py files are found.
Use an abspath if you'd rather do it that way.
Uses the current working directory as the location of using.py.
Keep in mind that os.walk goes *all the way* down the directory tree.
With that, try not to use this on something too close to '/'
"""
add = set(sys.path)if abspath isNone:
cwd = os.path.abspath(os.path.curdir)
abspath = os.path.join(cwd, folder)for root, dirs, files in os.walk(abspath):for f in files:if f[-3:]in'.py':
add.add(root)breakfor i in add: sys.path.append(i)>>>import using, sys, pprint
>>> using.all_from('py')#if in ~, /home/user/py/>>> pprint.pprint(sys.path)[#that was easy]
I podoba mi się to, ponieważ mogę mieć folder dla niektórych losowych narzędzi i nie mogą być częścią pakietów ani czegokolwiek, a mimo to uzyskać dostęp do niektórych (lub wszystkich) z nich w kilku wierszach kodu.
Najłatwiejszym sposobem jest utworzenie pliku „any_name.pth” i umieszczenie go w folderze „\ Lib \ site-packages”. Powinieneś znaleźć ten folder wszędzie tam, gdzie jest zainstalowany Python.
W tym pliku umieść listę katalogów, w których chcesz przechowywać moduły do importu. Na przykład utwórz wiersz w tym pliku w następujący sposób:
C: \ Users \ example ... \ example
Będziesz mógł stwierdzić, że działa, uruchamiając to w Pythonie:
import sys
for line in sys:print line
Zobaczysz swój katalog wydrukowany, między innymi skąd możesz również importować. Teraz możesz zaimportować plik „mymodule.py”, który znajduje się w tym katalogu tak łatwo, jak:
import mymodule
Nie spowoduje to zaimportowania podfolderów. W tym celu można sobie wyobrazić tworzenie skryptu w języku Python w celu utworzenia pliku .pth zawierającego wszystkie podfoldery zdefiniowanego folderu. Być może uruchom go podczas uruchamiania.
Nowa opcja dla starego pytania.
Instalowanie fail2banpakietu na Debianie wygląda na to, że jest zakodowane na stałe do zainstalowania na /usr/lib/python3/dist-packages/fail2banścieżce nie na python3 sys.path.
> python3
Python3.7.3(v3.7.3:ef4ec6ed12,Jun252019,18:51:50)[GCC 6.3.020170516] on linux
Type"help","copyright","credits"or"license"for more information.>>>import sys
>>> sys.path
['','/usr/lib/python37.zip','/usr/lib/python3.7','/usr/lib/python3.7/lib-dynload','/usr/lib/python3.7/site-packages']>>>
więc zamiast tylko kopiować, połączyłem (bash) bibliotekę z nowszymi wersjami. Przyszłe aktualizacje oryginalnej aplikacji będą również automatycznie stosowane w połączonych wersjach.
PYTHONPATH
: w.bashrc
lub jakimkolwiek pliku startowym używanym przez powłokę (jeśli nie jest to Bash), napiszexport PYTHONPATH=$PYTHONPATH:$HOME/codez/project
. Ale jeśli masz kilka podkatalogów, zrobiłbym.pth
plik i użyłsite.addsitedir
. Możesz utworzyć moduł,sitecustomize
który może wywołać tę funkcję za Ciebie; spróbuj umieścić go w~/.local/lib/python2.6/sitecustomize.py
(zastąp swoją wersję Pythona), aby mieć nadzieję, że zostanie automatycznie zaimportowany.echo $PYTHONPATH
. Jeśli zmienna środowiskowa została ustawiona poprawnie, powinieneś zobaczyć listę katalogów oddzielonych dwukropkami. Aby uzyskać informacje o.pth
plikach, zapoznaj się z dokumentacjąsite
modułu, do którego dołączyłem w mojej odpowiedzi. Informuje, jaka powinna być zawartość i jak z niej korzystać.Przeczytaj również o pakietach Pythona tutaj: http://docs.python.org/tutorial/modules.html .
Z twojego przykładu domyślam się, że naprawdę masz paczkę pod adresem
~/codez/project
. Plik__init__.py
w katalogu języka Python mapuje katalog na przestrzeń nazw. Jeśli wszystkie Twoje podkatalogi mają__init__.py
plik, wystarczy dodać katalog podstawowy do plikuPYTHONPATH
. Na przykład:Oprócz testowania zmiennej środowiskowej PYTHONPATH, jak wyjaśnia David, możesz przetestować ją w Pythonie w następujący sposób:
...
źródło
__init__.py
znaki odwrotne, aby było jasne, że naprawdę masz na myśli__init__.py
, w przeciwieństwie doinit.py
. Tylko po to, aby uniknąć mylących nowicjuszy. :)Wiem, że ten wątek jest trochę stary, ale zajęło mi trochę czasu, zanim dotarłem do jego sedna, więc chciałem się nim podzielić.
W moim projekcie główny skrypt miałem w katalogu nadrzędnym i aby rozróżnić moduły, umieściłem wszystkie moduły pomocnicze w podfolderze o nazwie „moduły”. W moim głównym skrypcie importuję te moduły w następujący sposób (dla modułu o nazwie report.py):
Jeśli zadzwonię do mojego głównego skryptu, to działa. JEDNAK chciałem przetestować każdy moduł, dodając jeden
main()
do każdego i wywołując każdy bezpośrednio, jako:Teraz Python skarży się, że nie może znaleźć „modułu o nazwie moduły”. Kluczowe jest tutaj to, że Python domyślnie zawiera folder skryptu w swojej ścieżce wyszukiwania, ALE NIE CWD. Tak więc ten błąd mówi tak naprawdę: „Nie mogę znaleźć podfolderu modułów”. Dzieje się tak, ponieważ w katalogu, w którym znajduje się moduł report.py, nie ma podkatalogu „modules”.
Uważam, że najlepszym rozwiązaniem jest dołączenie CWD w ścieżce wyszukiwania Pythona, umieszczając to na górze:
Teraz Python przeszukuje CWD (katalog bieżący), znajduje podfolder „modules” i wszystko jest w porządku.
źródło
Przeczytałem to pytanie, szukając odpowiedzi, i nie podobało mi się żadne z nich.
Napisałem więc szybkie i brudne rozwiązanie. Po prostu umieść to gdzieś w sys.path, a doda dowolny katalog w
folder
(z bieżącego katalogu roboczego) lub wabspath
:I podoba mi się to, ponieważ mogę mieć folder dla niektórych losowych narzędzi i nie mogą być częścią pakietów ani czegokolwiek, a mimo to uzyskać dostęp do niektórych (lub wszystkich) z nich w kilku wierszach kodu.
źródło
Najłatwiejszym sposobem jest utworzenie pliku „any_name.pth” i umieszczenie go w folderze „\ Lib \ site-packages”. Powinieneś znaleźć ten folder wszędzie tam, gdzie jest zainstalowany Python.
W tym pliku umieść listę katalogów, w których chcesz przechowywać moduły do importu. Na przykład utwórz wiersz w tym pliku w następujący sposób:
C: \ Users \ example ... \ example
Będziesz mógł stwierdzić, że działa, uruchamiając to w Pythonie:
Zobaczysz swój katalog wydrukowany, między innymi skąd możesz również importować. Teraz możesz zaimportować plik „mymodule.py”, który znajduje się w tym katalogu tak łatwo, jak:
Nie spowoduje to zaimportowania podfolderów. W tym celu można sobie wyobrazić tworzenie skryptu w języku Python w celu utworzenia pliku .pth zawierającego wszystkie podfoldery zdefiniowanego folderu. Być może uruchom go podczas uruchamiania.
źródło
Nowa opcja dla starego pytania.
Instalowanie
fail2ban
pakietu na Debianie wygląda na to, że jest zakodowane na stałe do zainstalowania na/usr/lib/python3/dist-packages/fail2ban
ścieżce nie na python3sys.path
.więc zamiast tylko kopiować, połączyłem (bash) bibliotekę z nowszymi wersjami.
Przyszłe aktualizacje oryginalnej aplikacji będą również automatycznie stosowane w połączonych wersjach.
źródło