Więcej
Co robi if __name__ == "__main__":?
Co robi polecenie if __name__ == "__main__":
?
# Threading example
import time, thread
def myfunction(string, sleeptime, lock, *args):
while True:
lock.acquire()
time.sleep(sleeptime)
lock.release()
time.sleep(sleeptime)
if __name__ == "__main__":
lock = thread.allocate_lock()
thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))
5496
3
Kiedy interpreter Pythona wczytuje plik źródłowy, robi dwie rzeczy:
__name__
, a następnieZobaczmy, jak to działa i jak to się ma do Twojego pytania o sprawdzanie
__name__
, które zawsze widzimy w skryptach Pythona. Przykładowy kodUżyjmy nieco innej próbki kodu, aby zbadać, jak działa import i skrypty. Załóżmy, że w pliku o nazwie
foo.py
znajduje się następująca treść.Zmienne specjalne
Kiedy interpreter Pythona wczytuje plik źródłowy, najpierw definiuje kilka zmiennych specjalnych. W tym przypadku zależy nam na zmiennej
__name__
. Gdy Twój moduł jest programem głównym Jeśli uruchamiasz swój moduł (plik źródłowy) jako program główny, np.to interpreter przypisze ciąg
"__main__"
do zmiennej__name__
, tzn.Kiedy twój moduł jest importowany przez inny Z drugiej strony, załóżmy, że jakiś inny moduł jest programem głównym i importuje twój moduł. Oznacza to, że w głównym programie lub w innym module, który importuje główny program, znajduje się taka instrukcja:
W tym przypadku, interpreter spojrzy na nazwę pliku twojego modułu,
foo.py
, usunie.py
i przypisze ten łańcuch do zmiennej__name__
twojego modułu' tzn.Wykonywanie kodu modułu
Po skonfigurowaniu zmiennych specjalnych, interpreter wykonuje cały kod modułu, po jednej instrukcji na raz. Być może zechcesz otworzyć inne okno na stronie z przykładem kodu, aby móc śledzić to wyjaśnienie. Zawsze
"przed importem"
(bez cudzysłowów).math
i przypisuje go do zmiennej o nazwiemath
. Jest to równoważne zastąpieniuimport math
następującym (zauważ, że__import__
jest niskopoziomową funkcją w Pythonie, która pobiera łańcuch i wywołuje rzeczywisty import):"przed funkcjąA"
.def
, tworząc obiekt funkcji, a następnie przypisując ten obiekt funkcji do zmiennej o nazwiefunctionA
."before functionB"
.def
, tworząc kolejny obiekt funkcji, a następnie przypisując go do zmiennej o nazwiefunctionB
."before __name__ guard"
. Tylko wtedy, gdy twój moduł jest programem głównym.__name__
rzeczywiście został ustawiony na"__main__"
i wywoła dwie funkcje, wypisując łańcuchy"Funkcja A"
i"Funkcja B 10.0"
. Tylko wtedy, gdy twój moduł jest importowany przez inny.__name__
będzie"foo"
, a nie"__main__"
, i'pominie ciało instrukcjiif
. Zawsze"po __name__ guard"
w obu sytuacjach. Podsumowanie Podsumowując, oto'co'zostałoby wydrukowane w tych dwóch przypadkach:Dlaczego to działa w ten sposób?
Możesz naturalnie zastanawiać się, dlaczego ktokolwiek chciałby tego. Otóż, czasami chcesz napisać plik
.py
, który może być zarówno używany przez inne programy i/lub moduły jako moduł, jak i może być uruchamiany jako program główny. Przykłady:Twój moduł jest biblioteką, ale chcesz mieć tryb skryptowy, w którym uruchamia on jakieś testy jednostkowe lub demo.
Twój moduł jest używany tylko jako program główny, ale ma kilka testów jednostkowych, a framework testowy działa poprzez importowanie plików
.py
jak twój skrypt i uruchamianie specjalnych funkcji testowych. Nie chcesz, aby próbował on uruchomić skrypt tylko dlatego, że importuje moduł.Twój moduł jest głównie używany jako program główny, ale zapewnia również przyjazne programistom API dla zaawansowanych użytkowników. Poza tymi przykładami, eleganckie jest to, że uruchomienie skryptu w Pythonie polega na ustawieniu kilku magicznych zmiennych i zaimportowaniu skryptu. "Uruchomienie" skryptu jest efektem ubocznym zaimportowania modułu skryptu'. Pokarm do przemyśleń
Pytanie: Czy mogę mieć wiele bloków sprawdzających
__name__
? Odpowiedź: Jest to dziwne, ale język nie będzie cię powstrzymywał.Przypuśćmy, że poniższy tekst znajduje się w pliku
foo2.py
. Co się stanie, jeśli powieszpython foo2.py
w wierszu poleceń? Dlaczego?__name__
wfoo3.py
:Kiedy twój skrypt jest uruchamiany przez przekazanie go jako polecenia do interpretera Pythona,
wykonywany jest cały kod, który znajduje się na poziomie wcięcia 0. Funkcje i klasy, które są zdefiniowane, są, no cóż, zdefiniowane, ale żaden z ich kodu nie zostanie wykonany. W przeciwieństwie do innych języków, nie ma funkcji
main()
, która jest uruchamiana automatycznie - funkcjamain()
jest domyślnie całym kodem na najwyższym poziomie.W tym przypadku, kodem najwyższego poziomu jest blok
if
.name__
jest wbudowaną zmienną, która odpowiada nazwie bieżącego modułu. Jednakże, jeśli moduł jest uruchamiany bezpośrednio (jak wmyscript.py
powyżej), wtedy__name__
jest ustawiane na łańcuch"__main__"
. Tak więc, możesz sprawdzić czy twój skrypt jest uruchamiany bezpośrednio, czy też jest importowany przez coś innego, testującJeśli twój skrypt jest importowany do innego modułu, jego różne definicje funkcji i klas zostaną zaimportowane i jego kod najwyższego poziomu zostanie wykonany, ale kod w then-body powyższej klauzuli
if
nie zostanie uruchomiony, ponieważ warunek nie jest spełniony. Jako podstawowy przykład, rozważmy następujące dwa skrypty:Teraz, jeśli wywołasz interpreter jako
Wyjściem będzie
Jeśli zamiast tego uruchomisz
two.py
:Otrzymasz
Tak więc, kiedy moduł
one
zostaje załadowany, jego__name__
równa się"one"
zamiast"__main__"
.if __name__ == "__main__"
jest częścią, która jest uruchamiana, gdy skrypt jest uruchamiany z (powiedzmy) linii poleceń za pomocą komendy takiej jakpython myscript.py
.