Mam katalog pełen skryptów (powiedzmy project/bin
). Mam również bibliotekę znajdującą się w project/lib
i chcę, aby skrypty automatycznie ją ładowały. Oto, czego zwykle używam u góry każdego skryptu:
#!/usr/bin/python
from os.path import dirname, realpath, sep, pardir
import sys
sys.path.append(dirname(realpath(__file__)) + sep + pardir + sep + "lib")
# ... now the real code
import mylib
Jest to trochę kłopotliwe, brzydkie i trzeba je wkleić na początku każdego pliku. Czy jest lepszy sposób, aby to zrobić?
Naprawdę liczę na coś tak gładkiego, jak to:
#!/usr/bin/python
import sys.path
from os.path import pardir, sep
sys.path.append_relative(pardir + sep + "lib")
import mylib
Lub jeszcze lepiej, coś, co nie zepsuje się, gdy mój redaktor (lub ktoś inny, kto ma dostęp do zatwierdzania) zdecyduje się zmienić kolejność importu w ramach procesu czyszczenia:
#!/usr/bin/python --relpath_append ../lib
import mylib
To nie przenosi się bezpośrednio na platformy inne niż POSIX, ale utrzymałoby wszystko w czystości.
python
python-import
James Harr
źródło
źródło
Odpowiedzi:
Jeśli nie chcesz edytować każdego pliku
lub
PYTHONPATH
na swójlib
lub jeśli chcesz dodać jedną linię do każdego pliku, dodaj u góry instrukcję importu, np
import import_my_lib
zachowaj
import_my_lib.py
w bin iimport_my_lib
możesz poprawnie ustawić ścieżkę Pythona na cokolwieklib
chceszźródło
Oto czego używam:
import os, sys sys.path.append(os.path.join(os.path.dirname(__file__), "lib"))
źródło
__file__
jest względną nazwą pliku względem bieżącego katalogu roboczego (np.setup.py
), Toos.path.dirname(__file__)
będzie to pusty ciąg. Z tego i podobnych problemów podniesiony przez Jana Jiang , ekhumoro „s więcej rozwiązaniem ogólnego przeznaczenia jest wysoce korzystne.Używam:
import sys,os sys.path.append(os.getcwd())
źródło
sys.path.append('.')
__file__
Zamiast tego po prostu odwołaj się, jak każdy quasi-rozsądny programista.Utwórz moduł opakowujący
project/bin/lib
, który zawiera:import sys, os sys.path.insert(0, os.path.join( os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'lib')) import mylib del sys.path[0], sys, os
Następnie możesz zamienić wszystkie cruft na górze swoich skryptów na:
#!/usr/bin/python from lib import mylib
źródło
Jeśli nie chcesz w żaden sposób zmieniać zawartości skryptu, dołącz bieżący katalog roboczy
.
do $ PYTHONPATH (patrz przykład poniżej)PYTHONPATH=.:$PYTHONPATH alembic revision --autogenerate -m "First revision"
I nazwij to dniem!
źródło
Korzystanie z Pythona 3.4+
Zakaz używania cx_freeze lub używania w IDLE. 😃
import sys from pathlib import Path sys.path.append(Path(__file__).parent / "lib")
źródło
Możesz uruchomić skrypt z
python -m
odpowiedniego katalogu głównego. I przekaż „ścieżkę modułów” jako argument.Przykład:
$ python -m module.sub_module.main # Notice there is no '.py' at the end.
Inny przykład:
$ tree # Given this file structure . ├── bar │ ├── __init__.py │ └── mod.py └── foo ├── __init__.py └── main.py $ cat foo/main.py from bar.mod import print1 print1() $ cat bar/mod.py def print1(): print('In bar/mod.py') $ python foo/main.py # This gives an error Traceback (most recent call last): File "foo/main.py", line 1, in <module> from bar.mod import print1 ImportError: No module named bar.mod $ python -m foo.main # But this succeeds In bar/mod.py
źródło
Z każdą podaną odpowiedzią występuje problem, który można podsumować słowami „po prostu dodaj to magiczne zaklęcie na początku swojego skryptu. Zobacz, co możesz zrobić, używając tylko jednego lub dwóch wierszy kodu”. Nie sprawdzą się w każdej możliwej sytuacji!
Na przykład jedno takie magiczne zaklęcie używa pliku . Niestety, jeśli spakujesz swój skrypt za pomocą cx_Freeze lub używasz IDLE, spowoduje to wyjątek.
Kolejne takie magiczne zaklęcie używa os.getcwd (). To zadziała tylko wtedy, gdy uruchamiasz skrypt z wiersza poleceń, a katalog zawierający skrypt jest bieżącym katalogiem roboczym (to znaczy, że przed uruchomieniem skryptu użyto polecenia cd, aby przejść do katalogu). Ech bogowie! Mam nadzieję, że nie muszę wyjaśniać, dlaczego to nie zadziała, jeśli twój skrypt Pythona jest gdzieś w PATH i uruchomiłeś go, po prostu wpisując nazwę swojego pliku skryptu.
Na szczęście istnieje magiczna inkantacja, która zadziała we wszystkich testowanych przeze mnie przypadkach. Niestety, magiczne zaklęcie to coś więcej niż tylko jedna lub dwie linijki kodu.
import inspect import os import sys # Add script directory to sys.path. # This is complicated due to the fact that __file__ is not always defined. def GetScriptDirectory(): if hasattr(GetScriptDirectory, "dir"): return GetScriptDirectory.dir module_path = "" try: # The easy way. Just use __file__. # Unfortunately, __file__ is not available when cx_freeze is used or in IDLE. module_path = __file__ except NameError: if len(sys.argv) > 0 and len(sys.argv[0]) > 0 and os.path.isabs(sys.argv[0]): module_path = sys.argv[0] else: module_path = os.path.abspath(inspect.getfile(GetScriptDirectory)) if not os.path.exists(module_path): # If cx_freeze is used the value of the module_path variable at this point is in the following format. # {PathToExeFile}\{NameOfPythonSourceFile}. This makes it necessary to strip off the file name to get the correct # path. module_path = os.path.dirname(module_path) GetScriptDirectory.dir = os.path.dirname(module_path) return GetScriptDirectory.dir sys.path.append(os.path.join(GetScriptDirectory(), "lib")) print(GetScriptDirectory()) print(sys.path)
Jak widać, nie jest to łatwe zadanie!
źródło
Ten działa najlepiej dla mnie. Posługiwać się:
os.path.abspath('')
Na Macu powinien wydrukować coś takiego:
'/Users/<your username>/<path_to_where_you_at>'
Aby uzyskać ścieżkę abs do bieżącego wd, ten jest lepszy, ponieważ teraz możesz przejść w górę, jeśli chcesz, na przykład:
os.path.abspath('../')
I teraz:
'/Users/<your username>/'
Więc jeśli chcesz zaimportować
utils
z tego miejsca'/Users/<your username>/'
, pozostało Ci tylko:
import sys sys.path.append(os.path.abspath('../'))
źródło
W twoim przykładzie widzę shebang. Jeśli uruchamiasz skrypty bin jako
./bin/foo.py
zamiastpython ./bin/foo.py
, istnieje opcja użycia shebang do zmiany$PYTHONPATH
zmiennej.Nie możesz jednak zmieniać zmiennych środowiskowych bezpośrednio w shebangs, więc będziesz potrzebować małego skryptu pomocniczego. Umieść to
python.sh
w swoimbin
folderze:#!/usr/bin/env bash export PYTHONPATH=$PWD/lib exec "/usr/bin/python" "$@"
A następnie zmienić shebang twoich
./bin/foo.py
być#!bin/python.sh
źródło
Kiedy próbujemy uruchomić plik Pythona ze ścieżką z terminala.
import sys #For file name file_name=sys.argv[0] #For first argument dir= sys.argv[1] print("File Name: {}, argument dir: {}".format(file_name, dir)
Zapisz plik (test.py).
Działający system.
Otwórz terminal i przejdź do katalogu, w którym jest zapisywany plik. następnie napisz
python test.py "/home/saiful/Desktop/bird.jpg"
Wciśnij Enter
Wynik:
źródło
Używam:
from site import addsitedir
Następnie można użyć dowolnego katalogu względnego!
addsitedir('..\lib')
; dwie kropki oznaczają, że najpierw przenieś (w górę) jeden katalog.Pamiętaj, że wszystko zależy od tego, z jakiego katalogu roboczego zaczynasz. Jeśli C: \ Joe \ Jen \ Becky, a następnie dodaje importitedir ('.. \ lib') do ścieżki C: \ Joe \ Jen \ lib
źródło