Odpowiedzi:
Możesz użyć, __file__
aby uzyskać nazwę bieżącego pliku. W przypadku użycia w module głównym jest to nazwa skryptu, który został pierwotnie wywołany.
Jeśli chcesz pominąć część katalogu (która może być obecna), możesz użyć os.path.basename(__file__)
.
__file__
nie jest zdefiniowany w interaktywnym tłumaczu , ponieważ nie ma tam znaczenia. Jest on ustawiany przez implementację importu, więc jeśli użyjesz niestandardowego mechanizmu importu, może on również zostać rozbrojony.
import os
jest wymagany, aby to zadziałało. Dodałbym to do odpowiedzi.
import os
i import os.path
są całkowicie równoważne.
import sys
print sys.argv[0]
Spowoduje to wydrukowanie foo.py
na python foo.py
, dir/foo.py
na python dir/foo.py
, itd. Jest to pierwszy argument python
. (Zauważ, że po py2exe będzie foo.exe
.)
python linkfile.py
, gdzie linkfile.py
jest dowiązanie symboliczne realfile.py
, sys.argv[0]
będzie 'linkfile.py'
, co może lub nie być tym, czego chcesz; z pewnością tego oczekuję . __file__
jest to samo: będzie linkfile.py
. Jeśli chcesz się dowiedzieć 'realfile.py'
od 'linkfile.py'
spróbować os.path.realpath('linkfile.py')
.
__file__
zamiast tego.
Ze względu na kompletność, pomyślałem, że warto podsumować różne możliwe wyniki i podać odniesienia do dokładnego zachowania każdego z nich:
__file__
jest aktualnie wykonywanym plikiem, jak wyszczególniono w oficjalnej dokumentacji :
__file__
jest ścieżką do pliku, z którego moduł został załadowany, jeśli został załadowany z pliku. W__file__
przypadku niektórych typów modułów, takich jak moduły C , które są statycznie połączone z tłumaczem, może brakować atrybutu ; w przypadku modułów rozszerzeń ładowanych dynamicznie z biblioteki współdzielonej jest to ścieżka do pliku biblioteki współdzielonej.
Od Python3.4 roku, za numerze 18416 , __file__
zawsze jest ścieżka bezwzględna, chyba że plik aktualnie wykonywany jest skrypt, który został wykonany bezpośrednio (nie przez tłumacza z -m
opcji wiersza polecenia) przy użyciu ścieżki względnej.
__main__.__file__
(wymaga importu __main__
) po prostu uzyskuje dostęp do wyżej wymienionego __file__
atrybutu modułu głównego , np. skryptu, który został wywołany z wiersza poleceń.
sys.argv[0]
(wymaga importu sys
) to nazwa skryptu, która została wywołana z wiersza poleceń i może być ścieżką bezwzględną, jak opisano w oficjalnej dokumentacji :
argv[0]
to nazwa skryptu (jest to zależne od systemu operacyjnego, czy jest to pełna nazwa ścieżki, czy nie). Jeśli polecenie zostało wykonane przy użyciu-c
opcji wiersza polecenia interpretera,argv[0]
ustawia się na ciąg'-c'
. Jeśli do interpretera języka Python nie przekazano żadnej nazwy skryptu,argv[0]
oznacza to, że jest to pusty ciąg.
Jak wspomniano w innej odpowiedzi na to pytanie , skrypty Pythona, które zostały przekonwertowane na samodzielne programy wykonywalne za pomocą narzędzi takich jak py2exe lub PyInstaller, mogą nie wyświetlać pożądanego wyniku podczas korzystania z tego podejścia (tzn. Zawierająsys.argv[0]
nazwę pliku wykonywalnego zamiast nazwy głównego pliku Pythona w tym pliku wykonywalnym).
Jeśli wydaje się, że żadna z wyżej wymienionych opcji nie działa, prawdopodobnie z powodu nieregularnej operacji importowania, moduł inspekcji może okazać się przydatny. W szczególności, powołując się inspect.getfile(...)
na inspect.currentframe()
może pracować, choć ten ostatni będzie powrócićNone
, gdy uruchomiony w implementacji bez Pythona stos ramki.
Jeśli bieżący skrypt jest dowiązaniem symbolicznym, wszystkie powyższe zwrócą ścieżkę dowiązania symbolicznego, a nie ścieżkę rzeczywistego pliku, i os.path.realpath(...)
należy je wywołać w celu wyodrębnienia tego ostatniego.
os.path.basename(...)
może być wywoływany na dowolnym z powyższych w celu wyodrębnienia rzeczywistej nazwy pliku i os.path.splitext(...)
może być wywoływany na rzeczywistej nazwie pliku w celu obcięcia jego sufiksu, jak w os.path.splitext(os.path.basename(...))
.
Od Pythona 3.4 roku, za PEP 428 The PurePath
klasa z pathlib
modułu mogą być również stosowane na którekolwiek z powyższych. W szczególności pathlib.PurePath(...).name
wyodrębnia rzeczywistą nazwę pliku i pathlib.PurePath(...).stem
wyodrębnia rzeczywistą nazwę pliku bez przyrostka.
Zauważ, że __file__
da plik, w którym znajduje się ten kod, który można importować i różni się od interpretowanego pliku głównego. Aby uzyskać główny plik, można użyć specjalnego modułu __main__ :
import __main__ as main
print(main.__file__)
Zauważ, że __main__.__file__
działa w Pythonie 2.7, ale nie w 3.2, więc użyj składni import-as jak wyżej, aby była przenośna.
rPython
pakietu z R
języka. To musi być wyjątkowy przypadek, który jest po prostu zbyt trudny do opanowania.
__main__
wewnętrznie, do użycia w przekazywaniu zmiennych między R
i python
, więc stosunkowo łatwo byłoby ustawić go __main__.__file__
przed wywołaniem czegokolwiek innego, ale nie jestem nawet pewien, jaka byłaby odpowiednia wartość w tym przypadku.
Powyższe odpowiedzi są dobre. Ale uznałem tę metodę za bardziej wydajną, korzystając z powyższych wyników.
Powoduje to, że rzeczywista nazwa pliku skryptu nie jest ścieżką.
import sys
import os
file_name = os.path.basename(sys.argv[0])
W przypadku nowoczesnych wersji Python (3.4+) Path(__file__).name
powinno być bardziej idiomatyczne. Ponadto, Path(__file__).stem
daje nazwę skryptu bez .py
rozszerzenia.
from pathlib import Path
pierwszy.
pathlib
zostało wprowadzone w Pythonie 3.4, więc powinno działać od Pythona 3.4.
Zakładając, że nazwa pliku to foo.py
poniższy fragment kodu
import sys
print sys.argv[0][:-3]
lub
import sys
print sys.argv[0][::-1][3:][::-1]
Podobnie jak w przypadku innych rozszerzeń z większą liczbą znaków, na przykład nazwa pliku foo.pypy
import sys
print sys.argv[0].split('.')[0]
Jeśli chcesz wyodrębnić z bezwzględnej ścieżki
import sys
print sys.argv[0].split('/')[-1].split('.')[0]
wyjdzie foo
Pierwszym argumentem w sys będzie nazwa bieżącego pliku, więc to zadziała
import sys
print sys.argv[0] # will print the file name
Jeśli wykonujesz nietypowy import (np. Jest to plik opcji), spróbuj:
import inspect
print (inspect.getfile(inspect.currentframe()))
Zauważ, że to zwróci bezwzględną ścieżkę do pliku.
możemy spróbować uzyskać bieżącą nazwę skryptu bez rozszerzenia.
import os
script_name = os.path.splitext(os.path.basename(__file__))[0]
Moje szybkie, brudne rozwiązanie:
__file__.split('/')[-1:][0]
os.path
do dzielenia nazw plików
os.path.abspath(__file__)
da ci absolutną ścieżkę (również relpath()
dostępną).
sys.argv[-1]
da ci względną ścieżkę.
wszystkie te odpowiedzi są świetne, ale mają pewne problemy, których możesz nie zobaczyć na pierwszy rzut oka.
pozwala zdefiniować, co chcemy - chcemy nazwę skryptu, który został wykonany, a nie nazwę bieżącego modułu - więc __file__
będzie działać tylko wtedy, gdy zostanie użyty w wykonanym skrypcie, a nie w zaimportowanym module.
sys.argv
jest również wątpliwe - co jeśli twój program został wywołany przez pytest? czy pydoc runner? lub jeśli został nazwany przez uwsgi?
i - istnieje trzecia metoda uzyskania nazwy skryptu, której nie widziałem w odpowiedziach - Możesz sprawdzić stos.
Innym problemem jest to, że Ty (lub inny program) możesz manipulować sys.argv
i __main__.__file__
- może być obecny, może nie być. Może być poprawny lub nie. Przynajmniej możesz sprawdzić, czy skrypt (pożądany wynik) istnieje!
moja biblioteka bitranox / lib_programname w github robi dokładnie to:
__main__
jest obecny__main__.__file__
jest obecny__main__.__file__
prawidłowy wynik (czy ten skrypt istnieje?)tą drogą, moje rozwiązanie działa do tej pory setup.py test
, uwsgi
, pytest
, pycharm pytest
, pycharm docrunner (doctest)
, dreampie
,eclipse
jest też miły artykuł na blogu o tym problemie autorstwa Dough Hellman, „Określanie nazwy procesu w Pythonie”
Od wersji Python 3.5 możesz po prostu:
from pathlib import Path
Path(__file__).stem
Zobacz więcej tutaj: https://docs.python.org/3.5/library/pathlib.html#pathlib.PurePath.stem
Na przykład mam plik w katalogu użytkownika o nazwie test.py
z tym wewnątrz:
from pathlib import Path
print(Path(__file__).stem)
print(__file__)
uruchamianie tych wyjść:
>>> python3.6 test.py
test
test.py
Exception NameError: NameError("global name '__file__' is not defined",)
”