co oznacza zmienna __file__?

177
A = os.path.join(os.path.dirname(__file__), '..')

B = os.path.dirname(os.path.realpath(__file__))

C = os.path.abspath(os.path.dirname(__file__))

Zwykle po prostu łączę je na stałe z rzeczywistą ścieżką. Ale jest powód, dla którego te instrukcje określają ścieżkę w czasie wykonywania i naprawdę chciałbym zrozumieć moduł os.path, aby móc zacząć go używać.

depling
źródło

Odpowiedzi:

162

Gdy moduł jest ładowany z pliku w Pythonie, __file__ustawiany jest na jego ścieżkę. Możesz następnie użyć tego z innymi funkcjami, aby znaleźć katalog, w którym znajduje się plik.

Biorąc swoje przykłady pojedynczo:

A = os.path.join(os.path.dirname(__file__), '..')
# A is the parent directory of the directory where program resides.

B = os.path.dirname(os.path.realpath(__file__))
# B is the canonicalised (?) directory where the program resides.

C = os.path.abspath(os.path.dirname(__file__))
# C is the absolute path of the directory where the program resides.

Możesz zobaczyć różne wartości zwrócone z tych tutaj:

import os
print(__file__)
print(os.path.join(os.path.dirname(__file__), '..'))
print(os.path.dirname(os.path.realpath(__file__)))
print(os.path.abspath(os.path.dirname(__file__)))

i upewnij się, uruchomić go z różnych miejsc (takich jak ./text.py, ~/python/text.pyi tak dalej), aby zobaczyć, co sprawia, że różnica.

paxdiablo
źródło
7
Dobra odpowiedź, ale zobacz inny ważny szczegół z innych odpowiedzi: __file__NIE jest zdefiniowany we wszystkich przypadkach, np. Statycznie połączone moduły C. Nie możemy liczyć na __file__to, że zawsze będziemy dostępni.
Chris Johnson,
5
W tłumaczu powracają wszystkie przykłady name '__file__' is not defined.
user1063287
10
@ user1063287 Spójrz na odpowiedź DemoUsera; __file__to ścieżka do pliku, z którego został załadowany moduł, jeśli został załadowany z pliku. Oznacza to, że __file__będzie działać tylko wtedy, gdy uruchomisz go jako skrypt, a nie w tłumaczu. (Chyba że zaimportujesz go do interpretera ...)
YOUNG
59

Chcę tylko najpierw zająć się pewnym zamieszaniem. __file__nie jest symbolem wieloznacznym, jest atrybutem. Atrybuty i metody podwójnego podkreślenia są na mocy konwencji uważane za „specjalne” i służą specjalnemu celowi.

http://docs.python.org/reference/datamodel.html zawiera wiele specjalnych metod i atrybutów, jeśli nie wszystkie.

W tym przypadku __file__jest to atrybut modułu (obiekt modułu). W Pythonie .pyplik jest modułem. Więc import amodulebędzie miał atrybut, __file__który oznacza różne rzeczy w różnych okolicznościach.

Zaczerpnięte z dokumentów:

__file__to ścieżka do pliku, z którego został załadowany moduł, jeśli został załadowany z pliku. __file__Cecha nie występuje w przypadku modułów C statycznie połączonych w interpreter; w przypadku modułów rozszerzeń ładowanych dynamicznie z biblioteki współdzielonej jest to ścieżka do pliku biblioteki współdzielonej.

W twoim przypadku moduł uzyskuje dostęp do swojego własnego __file__atrybutu w globalnej przestrzeni nazw.

Aby zobaczyć to w akcji, spróbuj:

# file: test.py

print globals()
print __file__

I biegnij:

python test.py

{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__file__':
 'test_print__file__.py', '__doc__': None, '__package__': None}
test_print__file__.py
Derek Litz
źródło
23

Zgodnie z dokumentacją :

__file__to ścieżka do pliku, z którego został załadowany moduł, jeśli został załadowany z pliku. __file__Cecha nie występuje w przypadku modułów C statycznie połączonych w interpreter; w przypadku modułów rozszerzeń ładowanych dynamicznie z biblioteki współdzielonej jest to ścieżka do pliku biblioteki współdzielonej.

a także :

__file__ma być „ścieżką” do pliku, chyba że moduł jest wbudowany (a zatem wymieniony w sys.builtin_module_names), w którym to przypadku atrybut nie jest ustawiony.

Sudhir Bastakoti
źródło
13

Użycie w __file__połączeniu z różnymi os.pathmodułami pozwala, aby wszystkie ścieżki były względne względem lokalizacji katalogu bieżącego modułu. Pozwala to na przenoszenie Twoich modułów / projektów na inne maszyny.

W swoim projekcie robisz:

A = '/Users/myname/Projects/mydevproject/somefile.txt'

a następnie spróbuj wdrożyć go na serwerze za pomocą katalogu wdrożeń, takiego jak /home/web/mydevproject/wtedy, gdy kod nie będzie w stanie poprawnie znaleźć ścieżek.

Sam Dolan
źródło