Co zrobić, jeśli __name__ == „__main__”: zrobić?


6056

Biorąc pod uwagę następujący kod, co to if __name__ == "__main__":robi?

# 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))

Czy if __name__ == "__main__":warunek blokowania jest przestarzały / nieaktualny aż do Pythona 3? Znalazłem informacje, które to potwierdzają.
carloswm85

1
@ carloswm85 To nieprawda.
Giorgos Myrianthous

Odpowiedzi:


6635

Ilekroć interpreter Pythona odczytuje plik źródłowy, robi dwie rzeczy:

  • ustawia kilka specjalnych zmiennych __name__, a następnie

  • wykonuje cały kod znaleziony w pliku.

Zobaczmy, jak to działa i jak odnosi się do twojego pytania na temat __name__kontroli, które zawsze widzimy w skryptach Pythona.

Próbka kodu

Użyjmy nieco innej próbki kodu, aby zbadać działanie importów i skryptów. Załóżmy, że w pliku o nazwie jest następujący foo.py.

# Suppose this is foo.py.

print("before import")
import math

print("before functionA")
def functionA():
    print("Function A")

print("before functionB")
def functionB():
    print("Function B {}".format(math.sqrt(100)))

print("before __name__ guard")
if __name__ == '__main__':
    functionA()
    functionB()
print("after __name__ guard")

Specjalne zmienne

Kiedy interpreter Pythona odczytuje plik źródłowy, najpierw definiuje kilka specjalnych zmiennych. W tym przypadku zależy nam na __name__zmiennej.

Gdy moduł jest programem głównym

Jeśli uruchamiasz moduł (plik źródłowy) jako program główny, np

python foo.py

interpreter przypisze ciąg zakodowany na stałe "__main__"do __name__zmiennej, tj

# It's as if the interpreter inserts this at the top
# of your module when run as the main program.
__name__ = "__main__" 

Gdy Twój moduł jest importowany przez inną osobę

Z drugiej strony załóżmy, że jakiś inny moduł jest programem głównym i importuje go. Oznacza to, że taka instrukcja znajduje się w głównym programie lub w innym module, który importuje główny program:

# Suppose this is in some other main program.
import foo

Interpreter wyszuka Twój foo.pyplik (wraz z kilkoma innymi wariantami), a przed uruchomieniem tego modułu przypisze nazwę "foo"ze instrukcji importu do __name__zmiennej, tj.

# It's as if the interpreter inserts this at the top
# of your module when it's imported from another module.
__name__ = "foo"

Wykonanie kodu modułu

Po skonfigurowaniu zmiennych specjalnych interpreter wykonuje cały kod w module, po jednej instrukcji na raz. Możesz otworzyć inne okno z przykładowym kodem, aby postępować zgodnie z tym wyjaśnieniem.

Zawsze

  1. Drukuje ciąg "before import"(bez cudzysłowów).

  2. Ładuje mathmoduł i przypisuje go do zmiennej o nazwie math. Jest to równoznaczne z zastąpieniem import mathponiższym (zwróć uwagę, że __import__jest to funkcja niskiego poziomu w Pythonie, która pobiera ciąg i wyzwala rzeczywisty import):

# Find and load a module given its string name, "math",
# then assign it to a local variable called math.
math = __import__("math")
  1. Drukuje ciąg "before functionA".

  2. Wykonuje defblok, tworząc obiekt funkcji, a następnie przypisując ten obiekt funkcji do zmiennej o nazwie functionA.

  3. Drukuje ciąg "before functionB".

  4. Wykonuje drugi defblok, tworząc inny obiekt funkcji, a następnie przypisując go do zmiennej o nazwie functionB.

  5. Drukuje ciąg "before __name__ guard".

Tylko wtedy, gdy moduł jest programem głównym

  1. Jeśli twój moduł jest programem głównym, zobaczy, że __name__rzeczywiście został ustawiony na "__main__"i wywołuje dwie funkcje, wypisując ciągi "Function A"i "Function B 10.0".

Tylko wtedy, gdy moduł zostanie zaimportowany przez inną osobę

  1. ( Zamiast ) Jeśli moduł nie jest główny program, ale został sprowadzony przez innego, wtedy __name__będzie "foo", nie "__main__", i będzie to pominąć ciało ifoświadczeniu.

Zawsze

  1. Wydrukuje ciąg "after __name__ guard"w obu sytuacjach.

Podsumowanie

Podsumowując, oto, co zostanie wydrukowane w dwóch przypadkach:

# What gets printed if foo is the main program
before import
before functionA
before functionB
before __name__ guard
Function A
Function B 10.0
after __name__ guard
# What gets printed if foo is imported as a regular module
before import
before functionA
before functionB
before __name__ guard
after __name__ guard

Dlaczego to działa w ten sposób?

Możesz oczywiście zastanawiać się, dlaczego ktoś tego chce. Czasami chcesz napisać .pyplik, który może być używany przez inne programy i / lub moduły jako moduł, a także może być uruchomiony jako sam program główny. Przykłady:

  • Twój moduł jest biblioteką, ale chcesz mieć tryb skryptu, w którym uruchamia on niektóre testy jednostkowe lub demonstrację.

  • Moduł jest używany tylko jako program główny, ale ma pewne testy jednostkowe, a środowisko testowe działa poprzez importowanie .pyplików takich jak skrypt i uruchamianie specjalnych funkcji testowych. Nie chcesz, aby próbował uruchomić skrypt tylko dlatego, że importuje moduł.

  • Twój moduł jest najczęściej używany jako program główny, ale zapewnia także interfejs API przyjazny dla programistów dla zaawansowanych użytkowników.

Poza tymi przykładami elegancko jest, że uruchomienie skryptu w Pythonie to tylko skonfigurowanie kilku magicznych zmiennych i zaimportowanie skryptu. „Uruchomienie” skryptu to efekt uboczny importowania modułu skryptu.

Jedzenie dla przemyślenia

  • Pytanie: Czy mogę mieć wiele __name__bloków sprawdzających? Odpowiedź: to dziwne, ale język cię nie powstrzyma.

  • Załóżmy, że następujące elementy są w foo2.py. Co się stanie, jeśli powiesz python foo2.pyw wierszu poleceń? Dlaczego?

# Suppose this is foo2.py.

def functionA():
    print("a1")
    from foo2 import functionB
    print("a2")
    functionB()
    print("a3")

def functionB():
    print("b")

print("t1")
if __name__ == "__main__":
    print("m1")
    functionA()
    print("m2")
print("t2")
  • Teraz dowiedz się, co się stanie, jeśli usuniesz __name__odprawę foo3.py:
# Suppose this is foo3.py.

def functionA():
    print("a1")
    from foo3 import functionB
    print("a2")
    functionB()
    print("a3")

def functionB():
    print("b")

print("t1")
print("m1")
functionA()
print("m2")
print("t2")
  • Co to zrobi, gdy zostanie użyte jako skrypt? Po zaimportowaniu jako moduł?
# Suppose this is in foo4.py
__name__ = "__main__"

def bar():
    print("bar")

print("before __name__ guard")
if __name__ == "__main__":
    bar()
print("after __name__ guard")

14
Z ciekawości: Co się stanie, jeśli uruchomię subprocess.run('foo_bar.py')skrypt w języku Python? Przypuszczam, że foo_barzacznie się __name__ = '__main__'tak, jak wtedy, gdy foo_bar.pyręcznie przesuwam cmd. Czy tak jest w przypadku? Biorąc pod uwagę odpowiedź @MrFooz, nie powinno być żadnego problemu z robieniem tego i posiadaniem tylu „głównych” modułów na raz, ile chcę. Nawet zmiana __name__wartości lub posiadanie kilku niezależnych instancji (lub instancji, które się utworzyły subprocess) współdziałają ze sobą, powinno być jak zwykle dla Pythona. Czy coś mi umknęło?
hajef

12
@hajef Masz rację co do tego, jak wszystko będzie działać subprocess.run. To powiedziawszy, ogólnie lepszym sposobem współdzielenia kodu między skryptami jest tworzenie modułów i skrypty wywoływały moduły współdzielone zamiast wywoływać się nawzajem jako skrypty. Trudno jest debugować subprocess.runwywołania, ponieważ większość debuggerów nie przeskakuje poza granice procesów, może dodać niebanalny narzut systemu, aby utworzyć i zniszczyć dodatkowe procesy itp.
Mr Fooz

4
mam wątpliwości co do przykładu foo2.py w dziale „żywność do przemyślenia”. co robi funkcja importu B foo2.py? Moim zdaniem po prostu importuje foo2.py z funkcji B
user471651

1
@ MRFooz Nigdy nie zamierzałem robić czegoś takiego xD Właśnie przyszło mi do głowy i zdałem sobie sprawę, że to było wystarczająco dziwne, aby pomóc ppl. owijając swoje myśli wokół tego rodzaju rzeczy. @ user471651 Dlaczego warto from foo2 import functionBimportować foo2 z funkcji B? To semantyczne zniekształcenie. from module import methodimportuje metodę z modułu.
hajef

2
Jednym z modułów, który może importować kod, jest multiprocessingw szczególności konieczność przeprowadzenia tego testu w systemie Windows.
Yann Vernier

1800

Po uruchomieniu skryptu, przekazując go jako polecenie do interpretera języka Python,

python myscript.py

wykonywany jest cały kod na poziomie wcięcia 0. Zdefiniowane funkcje i klasy są dobrze zdefiniowane, ale żaden z ich kodów nie jest uruchamiany. W przeciwieństwie do innych języków, żadna main()funkcja nie jest uruchamiana automatycznie - main()domyślnie jest to cały kod na najwyższym poziomie.

W tym przypadku kodem najwyższego poziomu jest ifblok. __name__jest wbudowaną zmienną, której wynikiem jest nazwa bieżącego modułu. Jeśli jednak moduł jest uruchamiany bezpośrednio (jak myscript.pypowyżej), __name__zamiast tego ustawiany jest ciąg "__main__". W ten sposób możesz przetestować, czy skrypt jest uruchamiany bezpośrednio, czy importowany przez coś innego, testując

if __name__ == "__main__":
    ...

Jeśli twój skrypt jest importowany do innego modułu, jego różne funkcje i definicje klas zostaną zaimportowane, a jego kod najwyższego poziomu zostanie wykonany, ale kod w iftekście powyższej klauzuli nie zostanie uruchomiony, ponieważ warunek jest następujący: nie spełnione Jako podstawowy przykład rozważ następujące dwa skrypty:

# file one.py
def func():
    print("func() in one.py")

print("top-level in one.py")

if __name__ == "__main__":
    print("one.py is being run directly")
else:
    print("one.py is being imported into another module")
# file two.py
import one

print("top-level in two.py")
one.func()

if __name__ == "__main__":
    print("two.py is being run directly")
else:
    print("two.py is being imported into another module")

Teraz, jeśli wywołasz interpretera jako

python one.py

Wyjście będzie

top-level in one.py
one.py is being run directly

Jeśli two.pyzamiast tego uruchomisz :

python two.py

Dostajesz

top-level in one.py
one.py is being imported into another module
top-level in two.py
func() in one.py
two.py is being run directly

Zatem, gdy moduł onezostanie załadowany, jego wartość __name__jest równa "one"zamiast "__main__".


Niesamowita odpowiedź, moim zdaniem była to najczystsza odpowiedź. +1!
TheTechRobo36414519

+1 za taki sposób myślenia: pierwsza linia wcięcia jest uruchamiana tylko na początku, dopóki funkcje pierwszego wiersza nie zostaną uruchomione
Eli TheHuman

719

Najprostsze wyjaśnienie __name__zmiennej (imho) jest następujące:

Utwórz następujące pliki.

# a.py
import b

i

# b.py
print "Hello World from %s!" % __name__

if __name__ == '__main__':
    print "Hello World again from %s!" % __name__

Uruchomienie ich zapewni ci następujące dane wyjściowe:

$ python a.py
Hello World from b!

Jak widać, po zaimportowaniu modułu Python ustawia globals()['__name__']w tym module nazwę modułu. Ponadto po zaimportowaniu cały kod w module jest uruchamiany. Jak ifoświadczenie ocenia, Falseta część nie jest wykonywana.

$ python b.py
Hello World from __main__!
Hello World again from __main__!

Jak widać, po uruchomieniu pliku Python ustawia globals()['__name__']w tym pliku wartość "__main__". Tym razem ifinstrukcja ocenia Truei jest uruchamiana.


513

Czego if __name__ == "__main__":zrobić?

Aby przedstawić podstawy:

  • Zmienna globalna __name__w module będącym punktem wejścia do programu to '__main__'. W przeciwnym razie jest to nazwa, którą importujesz moduł.

  • Tak więc kod pod ifblokiem będzie działał tylko wtedy, gdy moduł będzie punktem wejścia do twojego programu.

  • Umożliwia importowanie kodu z modułu przez inne moduły bez wykonywania bloku kodu poniżej podczas importu.


Dlaczego tego potrzebujemy?

Opracowywanie i testowanie kodu

Załóżmy, że piszesz skrypt w języku Python zaprojektowany jako moduł:

def do_important():
    """This function does something very important"""

Państwo mogli przetestować moduł dodając ten wywołanie funkcji do dołu:

do_important()

i uruchomienie go (w wierszu polecenia) za pomocą czegoś takiego:

~$ python important.py

Problem

Jeśli jednak chcesz zaimportować moduł do innego skryptu:

import important

Podczas importu do_importantfunkcja zostanie wywołana, więc prawdopodobnie skomentujesz swoje wywołanie funkcji do_important()na dole.

# do_important() # I must remember to uncomment to execute this!

A potem będziesz musiał pamiętać, czy skomentowałeś swoje wywołanie funkcji testowej. Ta dodatkowa złożoność oznaczałaby, że prawdopodobnie zapomnisz, co utrudni proces rozwoju.

Lepszy sposób

Te __name__punkty zmienną do nazw gdziekolwiek interpreter Pythona dzieje się w tej chwili.

W zaimportowanym module jest to nazwa tego modułu.

Ale wewnątrz modułu podstawowego (lub interaktywnej sesji Pythona, tj. Read, Eval, Print Loop lub REPL) interpretujesz wszystko z jego poziomu "__main__".

Więc jeśli sprawdzisz przed wykonaniem:

if __name__ == "__main__":
    do_important()

W związku z powyższym kod będzie wykonywany tylko wtedy, gdy zostanie uruchomiony jako moduł podstawowy (lub celowo wywoływany z innego skryptu).

Jeszcze lepszy sposób

Istnieje jednak Pythoniczny sposób, aby to poprawić.

Co jeśli chcemy uruchomić ten proces biznesowy spoza modułu?

Jeśli umieścimy kod, który chcemy ćwiczyć podczas opracowywania i testowania w funkcji takiej jak ta, a następnie sprawdzamy, czy '__main__'natychmiast:

def main():
    """business logic for when running this module as the primary one!"""
    setup()
    foo = do_important()
    bar = do_even_more_important(foo)
    for baz in bar:
        do_super_important(baz)
    teardown()

# Here's our payoff idiom!
if __name__ == '__main__':
    main()

Mamy teraz ostatnią funkcję na końcu naszego modułu, która będzie działać, jeśli uruchomimy moduł jako moduł podstawowy.

Umożliwi to zaimportowanie modułu oraz jego funkcji i klas do innych skryptów bez uruchamiania mainfunkcji, a także pozwoli na wywołanie modułu (i jego funkcji i klas) podczas uruchamiania z innego '__main__'modułu, tj.

import important
important.main()

Ten idiom można również znaleźć w dokumentacji Pythona w objaśnieniu __main__modułu. Ten tekst stanowi:

Moduł reprezentuje (poza tym anonimowy) zakres, w którym wykonuje się główny program tłumacza - polecenia odczytywane ze standardowego wejścia, ze pliku skryptu lub z interaktywnego monitu. Jest to środowisko, w którym idiomatyczna sekcja „skryptu warunkowego” powoduje uruchomienie skryptu:

if __name__ == '__main__':
    main()

125

if __name__ == "__main__"to część, która działa, gdy skrypt jest uruchamiany z (powiedzmy) wiersza poleceń za pomocą polecenia podobnego python myscript.py.


2
Dlaczego plik helloworld.pyz tym plikiem print("hello world")może działać z poleceniem, python helloworld.pynawet jeśli go nie ma if __name__ == "__main__"?
hi15

83

Co ma if __name__ == "__main__":zrobić?

__name__jest zmienną globalną (w Pythonie globalnie oznacza na poziomie modułu ), która istnieje we wszystkich przestrzeniach nazw. Zazwyczaj jest to nazwa modułu (jako strtyp).

Jednak jako jedyny szczególny przypadek w każdym uruchomionym procesie Pythona, jak w mycode.py:

python mycode.py

skądinąd anonimowy nazw globalny jest przypisana wartość '__main__'do ITS __name__.

Zatem łącznie z ostatnimi liniami

if __name__ == '__main__':
    main()
  • na końcu skryptu mycode.py
  • gdy jest to podstawowy moduł punktu wejścia uruchamiany przez proces w języku Python,

spowoduje mainuruchomienie unikatowej funkcji skryptu .

Kolejna zaleta korzystania z tej konstrukcji: możesz również zaimportować kod jako moduł w innym skrypcie, a następnie uruchomić główną funkcję, jeśli i kiedy program zdecyduje:

import mycode
# ... any amount of other code
mycode.main()

72

Istnieje wiele różnych podejść do mechaniki omawianego kodu, „How”, ale dla mnie żadne z nich nie miało sensu, dopóki nie zrozumiałem „Dlaczego”. Powinno to być szczególnie pomocne dla nowych programistów.

Weź plik „ab.py”:

def a():
    print('A function in ab file');
a()

I drugi plik „xy.py”:

import ab
def main():
    print('main function: this is where the action is')
def x():
    print ('peripheral task: might be useful in other projects')
x()
if __name__ == "__main__":
    main()

Co właściwie robi ten kod?

Kiedy wykonujesz xy.py, ty import ab. Instrukcja import uruchamia moduł natychmiast po imporcie, więc aboperacje są wykonywane przed pozostałą częścią xy. Po zakończeniu abkontynuuje się xy.

Tłumacz interpretuje, które skrypty są uruchomione __name__. Po uruchomieniu skryptu - bez względu na to, jak go nazwiesz - interpreter wywołuje go "__main__", co czyni go skryptem głównym lub „domowym”, do którego wraca po uruchomieniu skryptu zewnętrznego.

Każdy inny skrypt, który jest wywoływany z tego "__main__"skryptu, ma przypisaną nazwę pliku jako __name__(np __name__ == "ab.py".). Dlatego linia if __name__ == "__main__":jest testem interpretera w celu ustalenia, czy interpretuje / analizuje skrypt „domowy”, który został początkowo wykonany, czy też tymczasowo zagląda do innego (zewnętrznego) skryptu. Daje to programiście elastyczność, aby skrypt działał inaczej, jeśli jest wykonywany bezpośrednio, a nie wywoływany zewnętrznie.

Przejdźmy przez powyższy kod, aby zrozumieć, co się dzieje, skupiając się najpierw na niezróżnicowanych liniach i kolejności, w jakiej pojawiają się w skryptach. Pamiętaj, że funkcja - lub def- bloki nie robią nic same, dopóki nie zostaną wywołane. Co powiedziałby tłumacz, gdyby wymamrotał do siebie:

  • Otwórz xy.py jako plik „domowy”; nazwij to "__main__"w __name__zmiennej.
  • Zaimportuj i otwórz plik za pomocą __name__ == "ab.py" .
  • Och, funkcja. Będę pamiętać, że.
  • Ok, funkcja a(); Właśnie się tego nauczyłem. Drukowanie „ Funkcja w pliku ab ”.
  • Koniec pliku; wrócić do"__main__" !
  • Och, funkcja. Będę pamiętać, że.
  • Inny.
  • Funkcja x(); ok, drukowanie „ zadania peryferyjnego: może być przydatne w innych projektach ”.
  • Co to jest? ifStwierdzenie. Cóż, warunek został spełniony (zmienna __name__została ustawiona na "__main__"), więc wejdę do main()funkcji i wypiszę „ główną funkcję: tutaj jest akcja ”.

Dwie dolne linie oznaczają: „Jeśli jest to "__main__"skrypt„ domowy ”, wykonaj funkcję o nazwie main()„. Dlatego zobaczysz def main():blok do góry, który zawiera główny przepływ funkcji skryptu.

Po co to wdrażać?

Pamiętasz, co powiedziałem wcześniej o wyciągach z importu? Podczas importowania modułu nie tylko go „rozpoznaje” i czeka na dalsze instrukcje - w rzeczywistości uruchamia wszystkie operacje wykonywalne zawarte w skrypcie. Tak więc umieszczenie mięsa skryptu w main()funkcji skutecznie poddaje go kwarantannie, umieszczając go w izolacji, aby nie uruchomił się natychmiast po zaimportowaniu przez inny skrypt.

Znowu będą wyjątki, ale powszechną praktyką jest to, że main()zwykle nie wywołuje się ich na zewnątrz. Być może zastanawiasz się jeszcze jedną rzecz: jeśli nie dzwonimy main(), dlaczego w ogóle wywołujemy skrypt? Jest tak, ponieważ wiele osób tworzy swoje skrypty przy użyciu samodzielnych funkcji, które są zbudowane tak, aby działały niezależnie od reszty kodu w pliku. Następnie są wywoływani gdzieś indziej w treści skryptu. Co prowadzi mnie do tego:

Ale kod działa bez niego

Tak to prawda. Te osobne funkcje można wywoływać z wbudowanego skryptu, który nie jest zawarty w main()funkcji. Jeśli jesteś przyzwyczajony (tak jak ja, na wczesnych etapach programowania) do tworzenia skryptów online, które robią dokładnie to, czego potrzebujesz, i spróbujesz to rozgryźć, jeśli kiedykolwiek będziesz potrzebować tej operacji. ... cóż, nie jesteś przyzwyczajony do tego rodzaju wewnętrznej struktury kodu, ponieważ jest on bardziej skomplikowany w budowie i nie jest tak intuicyjny w czytaniu.

Jest to jednak skrypt, który prawdopodobnie nie może wywoływać swoich funkcji zewnętrznie, ponieważ gdyby to zrobił, natychmiast zacząłby obliczać i przypisywać zmienne. Są szanse, że jeśli spróbujesz ponownie użyć funkcji, twój nowy skrypt jest wystarczająco blisko powiązany ze starym, że wystąpią sprzeczne zmienne.

Dzieląc niezależne funkcje, zyskujesz możliwość ponownego wykorzystania poprzedniej pracy przez wywołanie ich w innym skrypcie. Na przykład „example.py” może importować „xy.py” i wywoływać x(), wykorzystując funkcję „x” z „xy.py”. (Być może jest to pisanie wielkimi literami trzeciego słowa danego ciągu tekstowego; tworzenie tablicy NumPy z listy liczb i ich kwadratowanie; lub zniechęcanie powierzchni 3D. Możliwości są nieograniczone.)

( Nawiasem mówiąc , to pytanie zawiera odpowiedź @kindall, która w końcu pomogła mi zrozumieć - dlaczego, a nie jak. Niestety oznaczono go jako duplikat tego , co uważam za błąd).


52

Kiedy w naszym module ( M.py) są pewne instrukcje, które chcemy wykonać, gdy będą działać jako główne (nie importowane), możemy umieścić te instrukcje (przypadki testowe, instrukcje drukowania) w tym ifbloku.

Domyślnie (gdy moduł działa jako główny, nie importowany) __name__zmienna jest ustawiona na "__main__", a kiedy zostanie zaimportowana, __name__zmienna otrzyma inną wartość, najprawdopodobniej nazwę modułu ( 'M'). Jest to pomocne w jednoczesnym uruchamianiu różnych wariantów modułów i oddzielaniu ich specyficznych instrukcji wejścia i wyjścia, a także w przypadku wystąpienia przypadków testowych.

Krótko mówiąc , użyj tego if __name__ == "main"bloku, aby zapobiec uruchomieniu (pewnego) kodu podczas importowania modułu.


43

Mówiąc prościej, __name__jest zmienną zdefiniowaną dla każdego skryptu, która określa, czy skrypt jest uruchamiany jako moduł główny, czy jest uruchamiany jako moduł importowany.

Więc jeśli mamy dwa skrypty;

#script1.py
print "Script 1's name: {}".format(__name__)

i

#script2.py
import script1
print "Script 2's name: {}".format(__name__)

Dane wyjściowe z wykonania skryptu 1 to

Script 1's name: __main__

A wynikiem działania script2 jest:

Script1's name is script1
Script 2's name: __main__

Jak widać, __name__mówi nam, który kod jest modułem „głównym”. Jest to świetne, ponieważ możesz po prostu pisać kod i nie martwić się o problemy strukturalne, takie jak w C / C ++, gdzie jeśli plik nie implementuje funkcji „głównej”, to nie można go skompilować jako pliku wykonywalnego, a jeśli tak, nie można go wtedy wykorzystać jako biblioteki.

Załóżmy, że piszesz skrypt w języku Python, który robi coś wspaniałego i implementujesz mnóstwo funkcji przydatnych w innych celach. Jeśli chcę ich użyć, mogę po prostu zaimportować skrypt i użyć go bez uruchamiania programu (biorąc pod uwagę, że kod działa tylko w if __name__ == "__main__":kontekście). Podczas gdy w C / C ++ trzeba by podzielić te elementy na osobny moduł, który następnie zawiera plik. Wyobraź sobie sytuację poniżej;

Skomplikowane importowanie w C.

Strzałki to linki do importu. Dla trzech modułów, z których każdy próbuje dołączyć kod poprzedniego modułu, jest sześć plików (dziewięć, licząc pliki implementacyjne) i pięć linków. Utrudnia to włączenie innego kodu do projektu C, chyba że jest on skompilowany specjalnie jako biblioteka. Teraz wyobraź to dla Pythona:

Elegancki import w Pythonie

Piszesz moduł, a jeśli ktoś chce użyć twojego kodu, po prostu go importuje, a __name__zmienna może pomóc oddzielić wykonalną część programu od części biblioteki.


2
Ilustracja C / C ++ jest niepoprawna: 3 razy ta sama nazwa jednostki ( plik 1 ).
Wolf

40

Spójrzmy na odpowiedź w bardziej abstrakcyjny sposób:

Załóżmy, że mamy ten kod w x.py:

...
<Block A>
if __name__ == '__main__':
    <Block B>
...

Bloki A i B są uruchamiane, gdy działamy x.py.

Ale blok A (a nie B) jest uruchamiany, gdy uruchamiamy inny moduł, y.pyna przykład, w którym x.pyjest importowany, a kod jest uruchamiany stamtąd (na przykład, gdy x.pywywoływana jest funkcja in y.py).


1
Nie mogłem edytować postu (minimum 6 znaków, jeśli wymagana jest zmiana). Linia 14 ma „xy” zamiast „x.py”.
alwaysLearning

35

Podczas interaktywnego uruchamiania Pythona __name__zmiennej lokalnej przypisywana jest wartość __main__. Podobnie, gdy uruchamiasz moduł Python z wiersza poleceń, zamiast importować go do innego modułu, jego __name__atrybutowi przypisywana jest wartość __main__, a nie rzeczywista nazwa modułu. W ten sposób moduły mogą przyjrzeć się własnej __name__wartości, aby samodzielnie ustalić, w jaki sposób są używane, czy to jako wsparcie dla innego programu, czy jako główna aplikacja wykonywana z wiersza poleceń. Dlatego następujący idiom jest dość powszechny w modułach Python:

if __name__ == '__main__':
    # Do something appropriate here, like calling a
    # main() function defined elsewhere in this module.
    main()
else:
    # Do nothing. This module has been imported by another
    # module that wants to make use of the functions,
    # classes and other useful bits it has defined.

34

Rozważać:

if __name__ == "__main__":
    main()

Sprawdza, czy __name__atrybut skryptu Python jest "__main__". Innymi słowy, jeśli sam program zostanie wykonany, atrybut będzie __main__, więc program zostanie wykonany (w tym przypadku main()funkcja).

Jeśli jednak moduł Pythona jest używany przez moduł, ifzostanie wykonany dowolny kod poza instrukcją, więc if \__name__ == "\__main__"służy on tylko do sprawdzenia, czy program jest używany jako moduł, czy nie, i dlatego decyduje, czy uruchomić kod.


Wygląda na to, że minęło zbyt wiele czasu, aby napisać świetlistą odpowiedź +1
SNR

27

Przed wyjaśnieniem czegokolwiek na temat if __name__ == '__main__'ważne jest, aby zrozumieć, co __name__jest i co robi.

Co to jest __name__?

__name__jest DunderAlias - można go traktować jako zmienną globalną (dostępną z modułów) i działa w podobny sposób global.

Jest to ciąg (globalny, jak wspomniano powyżej), jak wskazano przez type(__name__) (ustępowanie <class 'str'>), i jest wbudowanym standardem zarówno dla wersji Python 3, jak i Python 2 .

Gdzie:

Można go używać nie tylko w skryptach, ale można go również znaleźć zarówno w interpreterie, jak i modułach / pakietach.

Interpretator:

>>> print(__name__)
__main__
>>>

Scenariusz:

test_file.py :

print(__name__)

Wynikające z __main__

Moduł lub pakiet:

somefile.py:

def somefunction():
    print(__name__)

test_file.py:

import somefile
somefile.somefunction()

Wynikające z somefile

Zauważ, że gdy jest używany w pakiecie lub module, __name__przyjmuje nazwę pliku. Ścieżka rzeczywistej ścieżki modułu lub pakietu nie jest podana, ale ma własną DunderAlias__file__ , która pozwala na to.

Powinieneś zobaczyć, że gdzie __name__, gdzie jest to główny plik (lub program), zawsze będzie zwracany __main__, a jeśli jest to moduł / pakiet lub cokolwiek, co działa z innym skryptem Pythona, zwróci nazwę pliku, w którym jest pochodzi z.

Ćwiczyć:

Bycie zmienną oznacza, że ​​jej wartość może zostać nadpisana („może” nie oznacza „powinna”), nadpisanie wartości __name__spowoduje brak czytelności. Więc nie rób tego z jakiegokolwiek powodu. Jeśli potrzebujesz zmiennej, zdefiniuj nową zmienną.

Zawsze przyjmuje się, że wartość __name__to __main__lub nazwa pliku. Ponowna zmiana tej wartości domyślnej spowoduje więcej zamieszania, że ​​zrobi to dobrze, powodując problemy w dalszej linii.

przykład:

>>> __name__ = 'Horrify' # Change default from __main__
>>> if __name__ == 'Horrify': print(__name__)
...
>>> else: print('Not Horrify')
...
Horrify
>>>

Ogólnie uważa się za dobrą praktykę włączanie if __name__ == '__main__'skryptów.

Teraz, aby odpowiedzieć if __name__ == '__main__':

Teraz wiemy, że zachowanie się __name__rzeczy staje się wyraźniejsze:

Jest ifto instrukcja kontroli przepływu, która zawiera blok kodu, zostanie wykonana, jeśli podana wartość jest prawdą. Widzieliśmy, że __name__może to zająć albo __main__ nazwę pliku, z którego został zaimportowany.

Oznacza to, że jeśli __name__jest równe, __main__to plik musi być plikiem głównym i musi faktycznie działać (lub jest to interpreter), a nie moduł lub pakiet zaimportowany do skryptu.

Jeśli rzeczywiście __name__przyjmie wartość, __main__to wszystko, co jest w tym bloku kodu, zostanie wykonane.

To mówi nam, że jeśli uruchomiony plik jest plikiem głównym (lub bezpośrednio z interpretera), to warunek ten musi zostać spełniony. Jeśli jest to pakiet, nie powinien, a wartość nie będzie __main__.

Moduły:

__name__ może być również użyty w modułach do zdefiniowania nazwy modułu

Warianty:

Można także robić inne, mniej powszechne, ale przydatne rzeczy __name__, niektóre pokażę tutaj:

Wykonywanie tylko, jeśli plik jest modułem lub pakietem:

if __name__ != '__main__':
    # Do some useful things 

Uruchamianie jednego warunku, jeśli plik jest głównym, a drugiego, jeśli nie jest:

if __name__ == '__main__':
    # Execute something
else:
    # Do some useful things

Można go również użyć do zapewnienia uruchomionych funkcji pomocy / programów narzędziowych na pakietach i modułach bez skomplikowanego korzystania z bibliotek.

Umożliwia także uruchamianie modułów z wiersza poleceń jako głównych skryptów, co może być również bardzo przydatne.


25

Myślę, że najlepiej jest udzielić odpowiedzi dogłębnie i prostymi słowami:

__name__: Każdy moduł w Pythonie ma specjalny atrybut o nazwie __name__. Jest to wbudowana zmienna, która zwraca nazwę modułu.

__main__: Podobnie jak inne języki programowania, również Python ma punkt wejścia wykonania, tj. Main. '__main__' to nazwa zakresu, w którym wykonywany jest kod najwyższego poziomu . Zasadniczo masz dwa sposoby korzystania z modułu Python: Uruchom go bezpośrednio jako skrypt lub zaimportuj. Gdy moduł jest uruchamiany jako skrypt, __name__jest ustawiony na __main__.

W ten sposób wartość __name__atrybutu jest ustawiana, __main__gdy moduł jest uruchamiany jako program główny. W przeciwnym razie wartość __name__ jest ustawiona tak, aby zawierała nazwę modułu.


23

Jest to specjalne, gdy plik Python jest wywoływany z wiersza poleceń. Jest to zwykle używane do wywoływania funkcji „main ()” lub wykonania innego odpowiedniego kodu startowego, na przykład obsługi argumentów wiersza poleceń.

Można to napisać na kilka sposobów. Innym jest:

def some_function_for_instance_main():
    dosomething()


__name__ == '__main__' and some_function_for_instance_main()

Nie twierdzę, że powinieneś używać tego w kodzie produkcyjnym, ale służy to zilustrowaniu, że nie ma w tym nic „magicznego” if __name__ == '__main__'. Jest to dobra konwencja do wywoływania głównej funkcji w plikach Python.


7
Rozważałbym tę złą formę, ponieważ 1) polegasz na skutkach ubocznych i 2) nadużywam and. andsłuży do sprawdzania, czy obie instrukcje boolowskie są prawdziwe. Ponieważ nie jesteś zainteresowany wynikiem and, ifoświadczenie wyraźniej komunikuje twoje intencje.
jpmc26,

8
Pomijając pytanie, czy wykorzystywanie zachowania zwarciowego operatorów logicznych jako mechanizmu kontroli przepływu jest złym stylem, czy nie, tym większym problemem jest to, że w ogóle nie odpowiada na to pytanie .
Mark Amery

@MarkAmery haha, sheesh, teraz to robi. 😊
prof.

19

Istnieje wiele zmiennych, które system (interpreter języka Python) udostępnia dla plików źródłowych (modułów). Możesz uzyskać ich wartości w dowolnym momencie, więc skupmy się na zmiennej / atrybucie __name__ :

Gdy Python ładuje plik kodu źródłowego, wykonuje cały znajdujący się w nim kod. (Pamiętaj, że nie wywołuje wszystkich metod i funkcji zdefiniowanych w pliku, ale je definiuje.)

Jednak zanim interpreter wykona plik kodu źródłowego, definiuje kilka specjalnych zmiennych dla tego pliku; __imię__ jest jedną ze specjalnych zmiennych, które Python automatycznie definiuje dla każdego pliku kodu źródłowego.

Jeśli Python ładuje ten plik kodu źródłowego jako główny program (tj. Plik, który uruchamiasz), wówczas ustawia specjalną zmienną __name__ dla tego pliku na wartość „__main__” .

Jeśli jest importowany z innego modułu, __name__ zostanie ustawiony na nazwę tego modułu.

Tak więc w twoim przykładzie częściowo:

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))

oznacza, że ​​blok kodu:

lock = thread.allocate_lock()
thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))

zostanie wykonany tylko wtedy, gdy moduł zostanie uruchomiony bezpośrednio; blok kodu nie zostanie wykonany, jeśli inny moduł go wywołuje / importuje, ponieważ wartość __name__ nie będzie równa „ main ” w tym konkretnym przypadku.

Mam nadzieję, że to pomaga.


17

if __name__ == "__main__": jest zasadniczo środowiskiem skryptowym najwyższego poziomu i określa interpreter, który („Mam najwyższy priorytet do wykonania jako pierwszy”).

'__main__'to nazwa zakresu, w którym wykonywany jest kod najwyższego poziomu. Moduł __name__jest ustawiony na równy, '__main__'gdy jest czytany ze standardowego wejścia, skryptu lub z interaktywnego monitu.

if __name__ == "__main__":
    # Execute only if run as a script
    main()

17

Tak wiele czytałem w odpowiedziach na tej stronie. Powiedziałbym, że jeśli znasz tę rzecz, na pewno zrozumiesz te odpowiedzi, w przeciwnym razie nadal będziesz zdezorientowany.

Krótko mówiąc, musisz znać kilka punktów:

  1. import a akcja faktycznie uruchamia wszystko, co można uruchomić w „a”

  2. Z powodu punktu 1 możesz nie chcieć, aby wszystko było uruchamiane w „a” podczas importowania

  3. Aby rozwiązać problem w punkcie 2, python pozwala na sprawdzenie warunku

  4. __name__jest zmienną domyślną we wszystkich .pymodułach; gdy a.pyjest importowany, wartość __name__z a.pymodułu jest ustawiony na swoją nazwę pliku " a„; gdy a.pyjest prowadzony bezpośrednio za pomocą „ python a.py”, co oznacza, że a.pyjest punktem wyjścia, wtedy wartość __name__z a.pymodułu jest ustawione na sznurku__main__

  5. __name__Czy wiesz, jak osiągnąć punkt 3 w oparciu o mechanizm, w jaki sposób Python ustawia zmienną dla każdego modułu? Odpowiedź jest dość łatwa, prawda? Umieść jeśli warunek: if __name__ == "__main__": ...; możesz nawet umieścić, jeśli __name__ == "a"zależy to od twoich potrzeb funkcjonalnych

Ważną rzeczą, w której Python jest wyjątkowy, jest punkt 4! Reszta to tylko podstawowa logika.


1
Tak, punkt 1 jest niezbędny do zrozumienia. Z tego wynika potrzeba tego mechanizmu.
Eureka

16

Rozważać:

print __name__

Wynik dla powyższego jest __main__.

if __name__ == "__main__":
  print "direct method"

Powyższe stwierdzenie jest prawdziwe i wypisuje „metodę bezpośrednią” . Załóżmy, że jeśli zaimportowali tę klasę do innej klasy, nie wydrukuje ona „metody bezpośredniej”, ponieważ podczas importowania zostanie ustawiona __name__ equal to "first model name".


14

Możesz sprawić, by plik był użyteczny jako skrypt, a także jako moduł do importowania .

fibo.py (moduł o nazwie fibo)

# Other modules can IMPORT this MODULE to use the function fib
def fib(n):    # write Fibonacci series up to n
    a, b = 0, 1
    while b < n:
        print(b, end=' ')
        a, b = b, a+b
    print()

# This allows the file to be used as a SCRIPT
if __name__ == "__main__":
    import sys
    fib(int(sys.argv[1]))

Odniesienie: https://docs.python.org/3.5/tutorial/modules.html


14

Powód dla

if __name__ == "__main__":
    main()

polega przede wszystkim na uniknięciu problemów z blokadą importu , które powstałyby w wyniku bezpośredniego importowania kodu . Chcesz main()uruchomić, jeśli plik został bezpośrednio wywołany (to jest__name__ == "__main__" przypadku), ale jeśli kod został zaimportowany, wówczas importer musi wprowadzić kod z prawdziwego modułu głównego, aby uniknąć problemów z blokadą importu.

Efektem ubocznym jest automatyczne zalogowanie się do metodologii obsługującej wiele punktów wejścia. Możesz uruchomić swój program, używając main()jako punktu wejścia, ale nie musisz . Podczas gdy setup.pyoczekuje main(), inne narzędzia używają alternatywnych punktów wejścia. Na przykład, aby uruchomić plik jako gunicornproces, należy zdefiniować app()funkcję zamiast main(). Podobnie jak w przypadku setup.py, gunicornimportuj kod, abyś nie chciał nic robić podczas importowania (z powodu problemu z blokadą importu).


3
Dobrze poznać blokadę importu . Czy możesz wyjaśnić wpisanie się w metodologię, która [...] dzieli się nieco bardziej?
Wolf

1
@Wolf: Jasne. Dodałem kilka zdań na temat metodyki wielu punktów wejścia.
personal_cloud

11

Ta odpowiedź jest dla programistów Java uczących się języka Python. Każdy plik Java zazwyczaj zawiera jedną klasę publiczną. Możesz użyć tej klasy na dwa sposoby:

  1. Zadzwoń do klasy z innych plików. Musisz tylko zaimportować go do programu wywołującego.

  2. Uruchom klasę samodzielnie, do celów testowych.

W drugim przypadku klasa powinna zawierać publiczną statyczną metodę void main (). W Pythonie ten cel jest obsługiwany przez globalnie zdefiniowaną etykietę '__main__'.


11

Kod poniżej if __name__ == '__main__': zostanie wykonany tylko wtedy, gdy moduł zostanie wywołany jako skrypt .

Jako przykład rozważ następujący moduł my_test_module.py:

# my_test_module.py

print('This is going to be printed out, no matter what')

if __name__ == '__main__':
    print('This is going to be printed out, only if user invokes the module as a script')

Pierwsza możliwość: import my_test_module.pydo innego modułu

# main.py

import my_test_module

if __name__ == '__main__':
    print('Hello from main.py')

Teraz, jeśli wywołasz main.py:

python main.py 

>> 'This is going to be printed out, no matter what'
>> 'Hello from main.py'

Należy pamiętać, że tylko najwyższego poziomu print()oświadczenie w my_test_modulejest wykonywany.


Druga możliwość: wywołaj my_test_module.pyjako skrypt

Teraz, jeśli działasz my_test_module.pyjako skrypt Pythona, obie print()instrukcje zostaną wykonane:

python my_test_module.py

>>> 'This is going to be printed out, no matter what'
>>> 'This is going to be printed out, only if user invokes the module as a script'

10

Każdy moduł w pythonie ma atrybut o nazwie __name__. Wartość __name__ atrybutu polega __main__ na bezpośrednim uruchomieniu modułu, np python my_module.py. W przeciwnym razie (tak jak mówisz import my_module) wartość__name__ jest nazwa modułu.

Mały przykład do wyjaśnienia w skrócie.

#Script test.py

apple = 42

def hello_world():
    print("I am inside hello_world")

if __name__ == "__main__":
    print("Value of __name__ is: ", __name__)
    print("Going to call hello_world")
    hello_world()

Możemy to wykonać bezpośrednio jako

python test.py  

Wynik

Value of __name__ is: __main__
Going to call hello_world
I am inside hello_world

Załóżmy teraz, że wywołujemy powyższy skrypt z innego skryptu

#script external_calling.py

import test
print(test.apple)
test.hello_world()

print(test.__name__)

Kiedy to wykonasz

python external_calling.py

Wynik

42
I am inside hello_world
test

Tak, powyżej jest wymowne, że po wywołaniu testu z innego skryptu, jeśli pętla __name__w test.pynie wykona.


6

Jeśli ten plik .py zostanie zaimportowany przez inne pliki .py, kod pod „instrukcją if” nie zostanie wykonany.

Jeśli ten plik .py jest uruchamiany python this_py.pypod powłoką lub dwukrotnie kliknięty w systemie Windows. kod pod „instrukcją if” zostanie wykonany.

Zwykle jest napisane do testowania.


6

Jeśli interpreter Pythona uruchamia określony moduł, wówczas __name__zmienna globalna będzie miała wartość"__main__"

  def a():
      print("a")
  def b():
      print("b")

  if __name__ == "__main__": 

          print ("you can see me" )
          a()
  else: 

          print ("You can't see me")
          b()

Kiedy uruchomisz ten skrypt , możesz mnie zobaczyć

za

Jeśli zaimportujesz ten plik, powiedz A do pliku B i uruchom plik B, a następnie if __name__ == "__main__"plik A stanie się fałszem, więc zostanie wydrukowany. Nie widzisz mnie

b


5

Wszystkie odpowiedzi wyjaśniły funkcjonalność. Podam jednak jeden przykład jego użycia, który może pomóc w dalszym dopracowaniu koncepcji.

Załóżmy, że masz dwa pliki Python, a.py i b.py. Teraz a.py importuje b.py. Uruchamiamy plik a.py, w którym kod „import b.py” jest wykonywany jako pierwszy. Przed uruchomieniem reszty kodu a.py kod w pliku b.py musi zostać uruchomiony w całości.

W kodzie b.py jest jakiś kod, który jest wyłączny dla tego pliku b.py i nie chcemy, aby inny plik (inny niż plik b.py), który zaimportował plik b.py, go uruchomił.

Tak właśnie sprawdza ten wiersz kodu. Jeśli jest to główny plik (tj. B.py) z uruchomionym kodem, co w tym przypadku nie jest (a.py jest uruchomionym plikiem głównym), wówczas wykonywany jest tylko kod.


4

Utwórz plik a.py :

print(__name__) # It will print out __main__

__name__jest zawsze równy __main__każdorazowemu uruchomieniu tego pliku, co pokazuje, że jest to plik główny.

Utwórz kolejny plik b.py w tym samym katalogu:

import a  # Prints a

Uruchom. Będzie ona drukować , czyli nazwę pliku, który jest importowany .

Tak więc, aby pokazać dwa różne zachowania tego samego pliku , jest to często stosowana sztuczka:

# Code to be run when imported into another python file

if __name__ == '__main__':
    # Code to be run only when run directly

4

if name == ' main ':

Widzimy czy __name__ == '__main__': dość często.

Sprawdza, czy moduł jest importowany, czy nie.

Innymi słowy, kod w ifbloku zostanie wykonany tylko wtedy, gdy kod zostanie uruchomiony bezpośrednio. Tutaj directlyoznaczanot imported .

Zobaczmy, co robi, używając prostego kodu, który wypisuje nazwę modułu:

# test.py
def test():
   print('test module name=%s' %(__name__))

if __name__ == '__main__':
   print('call test()')
   test()

Jeśli uruchomimy kod bezpośrednio przez python test.py, nazwa modułu to __main__:

call test()
test module name=__main__

4

Po prostu jest to punkt wejściowy do uruchomienia pliku, podobnie jak mainfunkcja w języku programowania C.


8
Ta odpowiedź zakłada, że ​​OP (lub każdy użytkownik z podobnym pytaniem) zna zarówno C i wie, co to jest punkt wejścia.
arredond

1
Ta odpowiedź zakłada również, że przed if __name__ == "__main__"blokiem nie ma kodu (oprócz definicji bez skutków ubocznych) . Technicznie szczytem wykonanego skryptu jest punkt wejścia programu.
Charlie Harding,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.