Mam skrypty wywołujące inne pliki skryptów, ale muszę uzyskać ścieżkę do pliku, który jest aktualnie uruchomiony w procesie.
Załóżmy na przykład, że mam trzy pliki. Za pomocą pliku wykonywalnego :
script_1.py
połączeniascript_2.py
.- Z kolei
script_2.py
połączeniascript_3.py
.
Jak mogę uzyskać nazwę pliku i ścieżkę script_3.py
, z kodu wewnątrzscript_3.py
, bez konieczności przekazywania tych informacji jako argumentów script_2.py
?
(Wykonanie os.getcwd()
zwraca ścieżkę pliku oryginalnego skryptu startowego, a nie bieżący plik.)
__file__
?Odpowiedzi:
p1.py:
p2.py:
źródło
inspect.getabsfile()
i zadziałało we wszystkich przypadkach, które próbowałem.os.path.realpath(__file__)
jak powiedzieli inni. Możesz także użyć os.path.realpath, aby wyeliminować dowiązania symboliczne:
źródło
__file__
zwraca „script_name.py”, a innym razem „script_name.pyc”. Więc wyjście nie jest stabilne."__file__"
w cudzysłowach (jako ciąg) podaje__file__
katalog, z którego uruchamiane jest cmd, ale (bez cudzysłowów ścieżka do pliku źródłowego ... dlaczego tak jestos.path.realpath
funkcja zakłada , że jest todir
część ścieżki.os.path.dirname(os.path.realpath(__file__))
zwraca katalog z plikiem.os.path.dirname(os.path.realpath("__file__"))
zwraca cwd.os.path.dirname(os.path.realpath("here_be_dragons"))
zwraca również cwd.Aktualizacja 28.11.2018:
Oto podsumowanie eksperymentów z Pythonem 2 i 3. Z
main.py - uruchamia foo.py
foo.py - uruchamia lib / bar.py
lib / bar.py - drukuje wyrażenia ścieżki pliku
W przypadku Python 2 przełączenie na pakiety może być łatwiejsze
from lib import bar
- wystarczy dodać puste__init__.py
pliki do dwóch folderów.Dla Pythona 3
execfile
nie istnieje - najbliższa alternatywaexec(open(<filename>).read())
, choć wpływa to na ramki stosu. Jest najprostszy w użyciuimport foo
iimport lib.bar
- nie__init__.py
potrzeba żadnych plików.Zobacz także Różnica między importem a plikiem wykonywalnym
Oryginalna odpowiedź:
Oto eksperyment oparty na odpowiedziach w tym wątku - z Python 2.7.10 w systemie Windows.
Te oparte na stosie są jedynymi, które wydają się dawać wiarygodne wyniki. Dwa ostatnie mają najkrótszą składnię , tj. -
Oto ich dodawanie do sys jako funkcji! Podziękowania dla @Usagi i @pablog
Oparty na następujących trzech plikach i uruchamiający main.py ze swojego folderu z
python main.py
(wypróbował również pliki wykonywalne z bezwzględnymi ścieżkami i wywoływaniem z oddzielnego folderu).C: \ filepaths \ main.py:
execfile('foo.py')
C: \ filepaths \ foo.py:
execfile('lib/bar.py')
C: \ filepaths \ lib \ bar.py:
źródło
Myślę, że to jest czystsze:
i otrzymuje te same informacje, co:
Gdzie [0] to bieżąca ramka na stosie (góra stosu), a [1] to nazwa pliku, zwiększ, aby cofnąć się na stosie, tj.
będzie nazwą pliku skryptu, który wywołał bieżącą ramkę. Ponadto użycie [-1] spowoduje przejście do dolnej części stosu, oryginalnego skryptu wywołującego.
źródło
inspect.getfile()
zwraca__file__
atrybut, jeśli przekazano obiekt modułu.inspect.currentframe()
zwraca moduł. Ergo, to drogi sposób na powiedzenie__file__
.inspect.stack()
jest dość kosztowną funkcją, bardziej niż tylkoinspect.currentframe()
, i także wywołujeinspect.getfile()
obiekt modułu.źródło
__file__
.os.path.dirname
poda względną ścieżkę, z której uruchamiasz skrypt. np będzie , a nie bezwzględna ścieżka do skryptu. Szukałem abspath, ale usunąłem nazwę skryptu. Pierwszy element sys.path najwyraźniej jest odpowiedzią .python ../../test.py
os.path.dirname
../../
sys.path[0]
Wszystkie sugestie oznaczone jako najlepsze są prawdziwe, jeśli skrypt składa się tylko z jednego pliku.
Jeśli chcesz znaleźć nazwę pliku wykonywalnego (tj. Plik główny przekazany do interpretera Pythona dla bieżącego programu) z pliku, który można zaimportować jako moduł, musisz to zrobić (załóżmy, że jest to plik o nazwie foo.py ):
import inspect
print inspect.stack()[-1][1]
Ponieważ ostatnia rzecz (
[-1]
) na stosie jest pierwszą rzeczą, która weszła w nią (stosy to struktury danych LIFO / FILO).Następnie w pliku bar.py, jeśli
import foo
wydrukujesz bar.py , zamiast foo.py , co byłoby wartością wszystkich tych:__file__
inspect.getfile(inspect.currentframe())
inspect.stack()[0][1]
źródło
sys.modules['__main__'].__file__
.da nam to tylko nazwę pliku. tzn. jeśli ścieżka pliku to c: \ abcd \ abc.py, wówczas druga linia wypisze abc.py
źródło
Nie jest do końca jasne, co rozumiesz przez „ścieżkę pliku pliku, który jest obecnie uruchomiony w procesie”.
sys.argv[0]
zwykle zawiera lokalizację skryptu, który został wywołany przez interpreter Pythona. Sprawdź dokumentację sys po więcej szczegółów.Jak zauważyli @Tim i @Pat Notz, atrybut __file__ zapewnia dostęp do
źródło
Mam skrypt, który musi działać w środowisku Windows. Ten fragment kodu został zakończony:
to dość hackerska decyzja. Ale nie wymaga zewnętrznych bibliotek i jest to w moim przypadku najważniejsza rzecz.
źródło
Spróbuj tego,
źródło
Nie ma potrzeby inspekcji ani żadnej innej biblioteki.
Działa to dla mnie, gdy musiałem zaimportować skrypt (z innego katalogu niż wykonany skrypt), który używał pliku konfiguracyjnego znajdującego się w tym samym folderze co importowany skrypt.
źródło
The
__file__
Atrybut działa zarówno pliku zawierającego główny wykonanie kodu, jak i importowanych modułów.Zobacz https://web.archive.org/web/20090918095828/http://pyref.infogami.com/__file__
źródło
spowoduje to wydrukowanie ścieżki aktualnie wykonywanego skryptu
źródło
Myślę, że to po prostu
__file__
wygląda na to, że możesz również chcieć sprawdzić moduł inspekcji .źródło
Możesz użyć
inspect.stack()
źródło
Ponieważ Python 3 jest dość popularny, chciałem podać
pathlib
odpowiedź, ponieważ uważam, że jest to prawdopodobnie lepsze narzędzie do uzyskiwania dostępu do informacji o plikach i ścieżkach.Jeśli szukasz katalogu bieżącego pliku, jest to tak proste, jak dodanie
.parent
doPath()
instrukcji:źródło
źródło
To powinno działać:
źródło
źródło
Aby uzyskać katalog wykonywania skryptu
źródło
Zawsze korzystałem właśnie z funkcji os bieżącego katalogu roboczego lub CWD. Jest to część standardowej biblioteki i jest bardzo łatwa do wdrożenia. Oto przykład:
źródło
python script.py
polecenie w tym samym folderze, w którym już jesteś, podczas gdy w rzeczywistości działa tak samo, jakpwd
w Linuksie.Zastosowałem podejście z __plikiem__,
os.path.abspath(__file__)
ale jest mała sztuczka, zwraca plik .py, gdy kod jest uruchamiany przy pierwszym uruchomieniu, kolejne uruchomienia podają nazwę pliku * .pyc,
więc zostałem z:
inspect.getfile(inspect.currentframe())
lub
sys._getframe().f_code.co_filename
źródło
Napisałem funkcję, która bierze pod uwagę debugger zaćmienia i najbardziej nieprzystosowany . Zwraca folder pierwszego uruchomionego skryptu. Opcjonalnie możesz określić zmienną __plik___ , ale najważniejsze jest to, że nie musisz udostępniać tej zmiennej w całej hierarchii wywołań .
Może poradzisz sobie ze stosami innych przypadków, których nie widziałem, ale dla mnie jest w porządku.
źródło
Aby zachować spójność migracji na różnych platformach (macOS / Windows / Linux), spróbuj:
path = r'%s' % os.getcwd().replace('\\','/')
źródło
Najprostszym sposobem jest:
w script_1.py:
w script_2.py:
PS: Próbowałem
execfile
, ale ponieważ odczytuje skrypt_2.py jako ciąg,sys.argv[0]
zwróciło<string>
.źródło
Oto, czego używam, dzięki czemu mogę bez problemu rzucać kodem w dowolnym miejscu.
__name__
jest zawsze zdefiniowany, ale__file__
jest definiowany tylko wtedy, gdy kod jest uruchamiany jako plik (np. nie w IDLE / iPython).Alternatywnie można to zapisać jako:
źródło
Większość tych odpowiedzi została napisana w Pythonie w wersji 2.x lub wcześniejszej. W Pythonie 3.x zmieniono składnię funkcji drukowania, aby wymagała nawiasów, tj. Print ().
Tak więc, ta wcześniejsza odpowiedź o wysokim wyniku od user13993 w Python 2.x:
Staje się w Pythonie 3.x:
źródło
jeśli chcesz tylko nazwę pliku bez
./
lub.py
możesz spróbowaćfile_name
wypisze testcript, który możesz wygenerować co chcesz, zmieniając indeks wewnątrz []źródło
źródło