To może wydawać się pytaniem dla początkujących, ale tak nie jest. Niektóre typowe podejścia nie działają we wszystkich przypadkach:
sys.argv [0]
Oznacza to używanie path = os.path.abspath(os.path.dirname(sys.argv[0]))
, ale to nie działa, jeśli uruchamiasz z innego skryptu Python w innym katalogu, co może się zdarzyć w prawdziwym życiu.
__plik__
Oznacza to używanie path = os.path.abspath(os.path.dirname(__file__))
, ale stwierdziłem, że to nie działa:
py2exe
nie ma__file__
atrybutu, ale istnieje obejście- Po uruchomieniu z IDLE
execute()
bez__file__
atrybutu - OS X 10.6, gdzie dostaję
NameError: global name '__file__' is not defined
Powiązane pytania z niepełnymi odpowiedziami:
- Python - Znajdź ścieżkę do uruchamianego pliku
- Ścieżka do bieżącego pliku zależy od tego, jak wykonam program
- Jak poznać ścieżkę działającego skryptu w Pythonie?
- Zmień katalog na katalog skryptu Python
Szukam ogólnego rozwiązania , które działałoby we wszystkich powyższych przypadkach użycia.
Aktualizacja
Oto wynik przypadku testowego:
Dane wyjściowe Python a.py (w systemie Windows)
a.py: __file__= a.py
a.py: os.getcwd()= C:\zzz
b.py: sys.argv[0]= a.py
b.py: __file__= a.py
b.py: os.getcwd()= C:\zzz
a.py
#! /usr/bin/env python
import os, sys
print "a.py: sys.argv[0]=", sys.argv[0]
print "a.py: __file__=", __file__
print "a.py: os.getcwd()=", os.getcwd()
print
execfile("subdir/b.py")
subdir / b.py
#! /usr/bin/env python
import os, sys
print "b.py: sys.argv[0]=", sys.argv[0]
print "b.py: __file__=", __file__
print "b.py: os.getcwd()=", os.getcwd()
print
drzewo
C:.
| a.py
\---subdir
b.py
NameError: global name '__file__' is not defined
używam pliku i nie ma go w IDLE. Pomyśl, że__file__
jest zdefiniowane tylko w modułach.__file__
nie miał nic wspólnego z Unicode. Nie wiem, dlaczego__file__
nie został zdefiniowany, ale szukam ogólnego rozwiązania, które zadziała we wszystkich przypadkach.some_path/module_locator.py
?Najpierw musisz zaimportować z
inspect
ios
Następnie, gdziekolwiek chcesz znaleźć plik źródłowy, po prostu użyj
źródło
NameError: global name '__file__' is not defined
(spowodowało to inne rozwiązanie).lambda:_
. To działało dla mnie - nie jestem pewien, czy zawsze będzie działać.lambda:0
prawdopodobnie działa szybciej o niezmiernie małą ilość (a może nie jest tak mały ... może być natychmiastowym obciążeniem lub czymś jeszcze szybszym w0
porównaniu do obciążenia globalnego dla_
?) Dyskusyjne, czy jest to czystsze, łatwiejsze do odczytania, czy nawet bardziej sprytne / niejasne.getsourcefile(lambda:0)
będzie bez znaczenia i po prostu wróci,None
jeśli spróbujesz uruchomić go w interaktywnym monitie (ponieważlambda
nie będzie go w żadnym pliku źródłowym). Jeśli chcesz wiedzieć skąd pochodzi inna funkcja lub obiekt w interaktywnym środowisku, możeabspath(getsourcefile(thatFunctionOrObject))
będzie dla ciebie bardziej pomocny?to rozwiązanie jest niezawodne nawet w plikach wykonywalnych
źródło
entry_point: console_script
, ale żadnej z pozostałych odpowiedzi.Miałem podobny problem i myślę, że to może rozwiązać problem:
Działa dla zwykłych skryptów i bezczynności. Mogę tylko wypróbować to dla innych!
Moje typowe zastosowanie:
Teraz używam __modpath__ zamiast __file__.
źródło
__modpath__
należy zmienić nazwę. Prawdopodobnie też nie potrzebujesz tegoglobal
oświadczenia. W przeciwnym razie +1!module_path()
. tzn.module_path(lambda _: None)
która nie zależy od innej zawartości skryptu, w którym się znajduje.lambda _: None
i korzystałem z niej przez prawie ostatnie dwa lata, ale teraz odkryłem, że mogę ją skondensować do samego końcalambda:0
. Czy jest jakiś konkretny powód, dla którego zasugerowałeś formularz, który zignorowałeś_
zamiast argumentu? Czy jest coś lepszego wNone
prefiksie ze spacją niż tylko0
? Oba są równie tajemnicze, jak sądzę, tylko jedna ma 8 znaków, a druga ma 14 znaków.lambda _:
jest to funkcja, która przyjmuje jeden argument ilambda:
nie przyjmuje żadnego. Nie ma to znaczenia, ponieważ funkcja nigdy nie jest wywoływana. Podobnie nie ma znaczenia, jaka wartość zwracana jest używana. Wydaje mi się, że wybrałem,None
ponieważ wtedy wydawało się, że jest to lepsza funkcja „nic nie rób, nigdy nie można nazywać”. Przestrzeń przed nim jest opcjonalna i znowu tam tylko dla lepszej czytelności (zawsze próba podążania za PEP8 kształtuje nawyki).lambda
, wykorzystywanie go do czegoś, czego nigdy nie zamierzano robić. Jeśli miałbyś podążać za PEP8, myślę, że odpowiednia treść byłabypass
, nieNone
, ale nie jest poprawne umieszczanie instrukcji wlambda
, więc musisz wstawić coś o wartości. Jest kilka ważnych 2-znakowych rzeczy, które możesz umieścić, ale myślę, że jedyne poprawne pojedyncze znaki, które możesz wstawić, to 0-9 (lub nazwa zmiennej pojedynczego znaku przypisana pozalambda
.). Moim zdaniem0
najlepiej wskazuje na nicość 0- 9Krótka odpowiedź jest taka, że nie ma gwarantowanego sposobu na uzyskanie potrzebnych informacji , jednak istnieją heurystyki, które działają prawie zawsze w praktyce. Możesz spojrzeć na Jak znaleźć lokalizację pliku wykonywalnego w C? . Omawia problem z punktu widzenia C, ale proponowane rozwiązania można łatwo przepisać na język Python.
źródło
Zobacz moją odpowiedź na pytanie Importowanie modułów z folderu nadrzędnego w celu uzyskania powiązanych informacji, w tym dlaczego moja odpowiedź nie używa nierzetelnej
__file__
zmiennej. To proste rozwiązanie powinno być kompatybilne krzyżowo z różnymi systemami operacyjnymi jako modułamios
iinspect
być częścią Pythona.Najpierw musisz zaimportować części modułów inspekcji i systemu operacyjnego .
Następnie użyj następującego wiersza w dowolnym innym miejscu w kodzie Python:
Jak to działa:
Z wbudowanego modułu
os
(opis poniżej)abspath
narzędzie jest importowane.Następnie
getsourcefile
(opis poniżej) jest importowany z wbudowanego modułuinspect
.abspath(path)
zwraca bezwzględną / pełną wersję ścieżki do plikugetsourcefile(lambda:0)
w jakiś sposób pobiera wewnętrzny plik źródłowy obiektu funkcji lambda, więc zwraca'<pyshell#nn>'
w powłoce Pythona lub zwraca ścieżkę pliku aktualnie wykonywanego kodu Python.Użycie
abspath
wynikugetsourcefile(lambda:0)
powinno upewnić się, że wygenerowana ścieżka do pliku jest pełną ścieżką do pliku Python.To wyjaśnione rozwiązanie zostało pierwotnie oparte na kodzie z odpowiedzi na pytanie Jak uzyskać ścieżkę do aktualnie wykonywanego pliku w Pythonie? .
źródło
Po prostu zadzwoniłeś:
zamiast:
abspath()
podaje bezwzględną ścieżkęsys.argv[0]
(nazwa pliku, w którym znajduje się kod) idirname()
zwraca ścieżkę katalogu bez nazwy pliku.źródło
Powinno to załatwić sprawę na wiele platform (o ile nie używasz interpretera lub czegoś takiego):
sys.path[0]
to katalog, w którym znajduje się skrypt wywołujący (pierwsze miejsce, w którym szuka modułów do użycia przez ten skrypt). Możemy usunąć nazwę samego pliku z końcasys.argv[0]
(i właśnie to zrobiłemos.path.basename
).os.path.join
po prostu łączy je ze sobą na wiele platform.os.path.realpath
upewnia się tylko, czy otrzymamy jakieś dowiązania symboliczne o innych nazwach niż sam skrypt, że nadal otrzymujemy prawdziwą nazwę skryptu.Nie mam komputera Mac; więc nie przetestowałem tego na jednym. Daj mi znać, czy to działa, jak się wydaje. Testowałem to w systemie Linux (Xubuntu) w Pythonie 3.4. Zwróć uwagę, że wiele rozwiązań tego problemu nie działa na komputerach Mac (ponieważ słyszałem, że
__file__
nie występuje na komputerach Mac).Zauważ, że jeśli twój skrypt jest dowiązaniem symbolicznym, poda ci ścieżkę do pliku, do którego prowadzi (a nie ścieżkę dowiązania symbolicznego).
źródło
Możesz użyć
Path
zpathlib
modułu:Możesz użyć połączenia,
parent
aby przejść dalej:źródło
__file__
zmienną, która może być zawodna (nie zawsze pełna ścieżka pliku, nie działa w każdym systemie operacyjnym itp.), Jak często wspominali użytkownicy StackOverflow. Zmiana odpowiedzi na nieuwzględniającą spowoduje mniej problemów i będzie bardziej kompatybilna krzyżowo. Aby uzyskać więcej informacji, zobacz stackoverflow.com/a/33532002/3787376 .Jeśli kod pochodzi z pliku, możesz uzyskać jego pełną nazwę
Możesz także pobrać nazwę funkcji jako
f_code.co_name
źródło
Po prostu dodaj:
Lub:
źródło
Moje rozwiązanie to:
źródło
źródło
'__file__'
nie powinien być ciągiem, po drugie, jeśli tak__file__
, działałoby to tylko dla pliku, w którym znajduje się ten wiersz kodu, a nie dla pliku, który jest wykonywany?