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

pytanie utworzone w Fri, May 25, 2018 12:00 AM

Co robi 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))
    
5111
28 odpowiedzi                              28                         

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

  • ustawia kilka specjalnych zmiennych, takich jak __name__, a następnie

  • wykonuje cały kod znaleziony w pliku.

Zobaczmy, jak to działa i jak odnosi się to do pytania dotyczącego czeków __name__, które zawsze widzimy w skryptach Pythona.

Przykład kodu

Użyjmy nieco innej próbki kodu, aby zbadać, jak działają import i skrypty. Załóżmy, że poniższy plik znajduje się w pliku o nazwie 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")

Zmienne specjalne

Gdy interpeter Pythona odczytuje plik źródłowy, najpierw definiuje kilka specjalnych zmiennych. W tym przypadku zależy nam na zmiennej __name__.

Kiedy Twój moduł jest głównym programem

Jeśli używasz modułu (pliku źródłowego) jako programu głównego, np.

python foo.py

tłumacz przypisze kodowany ciąg "__main__" do zmiennej __name__, tj.

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

Kiedy moduł jest importowany przez inny

Z drugiej strony załóżmy, że głównym modułem jest inny moduł, który importuje twój moduł. Oznacza to, że w głównym programie lub w innym module importowanym przez główny program znajduje się takie polecenie:

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

W tym przypadku interpreter przejrzy nazwę pliku modułu foo.py, usunie .py i przypisze ten ciąg do zmiennej __name__ modułu, tzn.

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

Wykonywanie kodu modułu

Po skonfigurowaniu specjalnych zmiennych interpreter wykonuje cały kod w module, jedno polecenie na raz. Możesz otworzyć kolejne okno z przykładowym kodem, abyś mógł śledzić to wyjaśnienie.

Ale zawsze

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

  2. Ładuje moduł math i przypisuje go do zmiennej o nazwie math. Jest to równoznaczne z zastąpieniem import math następującym kodem (pamiętaj, że __import__ jest funkcją niskiego poziomu w Pythonie, która pobiera ciąg i uruchamia 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 blok def, 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 blok def, tworząc inny obiekt funkcji, a następnie przypisując go do zmiennej o nazwie functionB.

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

Tylko gdy Twój moduł jest głównym programem

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

Tylko wtedy, gdy Twój moduł zostanie zaimportowany przez inny

  1. ( zamiast ) Jeśli moduł nie jest programem głównym, ale został zaimportowany przez inny, __name__ będzie "foo", a nie "__main__", a pominie treść if.

Ale 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ś by tego chciał. Czasami chcesz napisać plik .py, który może być używany przez inne programy i /lub moduły jako moduł, a także może być uruchamiany jako program główny.Przykłady:

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

  • Twój moduł jest używany tylko jako program główny, ale ma kilka testów jednostkowych, a framework testujący działa poprzez importowanie plików .py, takich jak Twój 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 również przyjazny dla programistów interfejs API dla zaawansowanych użytkowników.

Poza tymi przykładami, to jest eleganckie, że uruchamianie skryptu w Pythonie polega po prostu na ustawieniu kilku zmiennych magicznych i zaimportowaniu skryptu. „Uruchomienie” skryptu jest efektem ubocznym importu modułu skryptu.

Żywność dla myśli

  • Pytanie: Czy mogę mieć wiele bloków sprawdzających __name__? Odpowiedź: dziwnie to robić, ale język Cię nie powstrzyma.

  • Przypuśćmy, że następujące dane to foo2.py. Co się stanie, jeśli powiesz python foo2.py w wierszu polecenia? 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 sprawdź, 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")
    
5471
2019-06-24 03: 21: 09Z
  1. Z ciekawości: Co się stanie, jeśli uruchomię subprocess.run('foo_bar.py') w skrypcie Pythona? Przypuszczam, że foo_bar zostanie uruchomione z __name__ = '__main__' tak samo, jak ręcznie tipe foo_bar.py w cmd. Czy tak jest? Biorąc pod uwagę odpowiedź @MrFooz ', nie powinno być problemu z zrobieniem tego i posiadaniem jak największej liczby „głównych” modułów na raz. Nawet zmiana wartości __name__ lub posiadanie kilku niezależnie tworzonych instancji (lub instancji, które utworzyły się nawzajem przez subprocess) współdziałają ze sobą w Pythonie. Czy czegoś brakuje?
    2019-02-18 16: 09: 14Z
  2. @ hajef Masz rację co do sposobu działania subprocess.run. Ogólnie rzecz biorąc, lepszym sposobem udostępniania kodu między skryptami jest tworzenie modułów i wywoływanie skryptów wspólne moduły zamiast wywoływać się nawzajem jako skrypty. Trudno jest debugować wywołania subprocess.run, ponieważ większość debuggerów nie przeskakuje granic procesu, może dodać nietrywialne obciążenie systemu, aby utworzyć i zniszczyć dodatkowe procesy itp.
    2019-02-19 16: 16: 03Z
  3. mam wątpliwości w przykładzie foo2.py w sekcji food for thought.what co z funkcji importu foo2.py B? Moim zdaniem po prostu importuje foo2.py z functionB
    2019-02-24 13: 47: 03Z
  4. @ MrFooz Nigdy nie miałem zamiaru robić czegoś takiego jak ten xD Po prostu przyszło mi do głowy i zdałem sobie sprawę, że to dziwne, że mogę pomóc ppl. owijając ich umysły wokół tego rodzaju rzeczy. @ user471651 Dlaczego from foo2 import functionB ma importować foo2 z funkcjiB? To wykrzywienie semantyczne. from module import method importuje metodę z modułu.
    2019-02-25 15: 51: 16Z
  5. czy jesteś bogiem Pythona? ładne wyjaśnienie: D
    2019-06-18 03: 20: 56Z

Gdy skrypt jest uruchamiany przez przekazanie go jako polecenia do interpretera Pythona,

python myscript.py

cały kod znajdujący się na poziomie wcięcia 0 zostaje wykonany. Funkcje i klasy, które są zdefiniowane, są dobrze zdefiniowane, ale żaden z ich kodu nie jest uruchamiany. W przeciwieństwie do innych języków nie ma funkcji main() uruchamianej automatycznie - funkcja main() jest niejawnie całym kodem na najwyższym poziomie.

W tym przypadku kod najwyższego poziomu to blok if. __name__jest wbudowaną zmienną, która ocenia nazwę bieżącego modułu. Jeśli jednak moduł jest uruchamiany bezpośrednio (jak w myscript.py powyżej), zamiast tego __name__ jest ustawiany na ciąg "__main__". W związku z tym można przetestować, czy skrypt jest uruchamiany bezpośrednio lub jest importowany przez coś innego przez testowanie

if __name__ == "__main__":
    ...

Jeśli 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 powyższym tekście klauzuli if nie zostanie uruchomiony ponieważ warunek nie jest spełniony. 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łujesz interpreter jako

python one.py

Wyjście będzie

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

Jeśli zamiast tego uruchomisz two.py:

python two.py

Otrzymujesz

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

Tak więc po załadowaniu modułu one jego __name__ jest równe "one" zamiast "__main__".

    
1640
2018-01-31 13: 28: 16Z

Najprostszym wyjaśnieniem dla zmiennej __name__ (imho) jest:

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__

Uruchamianie ich da ci to wyjście:

$ python a.py
Hello World from b!

Jak widać, po zaimportowaniu modułu Python ustawia globals()['__name__'] w tym module na nazwę modułu. Ponadto po zaimportowaniu cały kod w module jest uruchamiany. Ponieważ instrukcja if ocenia na False, ta część nie jest wykonywana.

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

Jak widać, podczas wykonywania pliku Python ustawia globals()['__name__'] w tym pliku na "__main__". Tym razem instrukcja if ocenia na True i jest uruchamiana.

    
653
2018-12-18 09: 25: 19Z
  

Co robi if __name__ == "__main__":?

Aby zarysować podstawy:

  • Zmienna globalna, __name__, w module, który jest punktem wejścia do twojego programu, to '__main__'. W przeciwnym razie jest to nazwa, którą importujesz moduł.

  • Tak więc kod pod blokiem if zostanie uruchomiony tylko wtedy, gdy moduł jest punktem wejścia do twojego programu.

  • Umożliwia importowanie kodu w module przez inne moduły, bez wykonywania poniższego bloku kodu podczas importu.


Dlaczego tego potrzebujemy?

Opracowywanie i testowanie kodu

Powiedzmy, że piszesz skrypt Pythona przeznaczony do użycia jako moduł:

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

Możesz przetestować moduł, dodając to wywołanie funkcji do dołu:

do_important()

i uruchomienie go (w wierszu polecenia) z czymś w rodzaju:

~$ python important.py

Problem

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

import important

Przy imporcie zostanie wywołana funkcja do_important, więc prawdopodobnie skomentujesz swoją funkcję, do_important(), u dołu.

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

A potem będziesz musiał pamiętać, czy skomentowałeś wywołanie funkcji testowej. I ta dodatkowa złożoność oznaczałaby, że prawdopodobnie zapomnisz, co sprawi, że proces rozwoju stanie się bardziej kłopotliwy.

Lepsza droga

Zmienna __name__ wskazuje przestrzeń nazw, w której aktualnie znajduje się interpreter Pythona.

W zaimportowanym module jest to nazwa tego modułu.

Ale w głównym module (lub w interaktywnej sesji Pythona, tj. w czytniku interpretera, Eval, Print Loop lub REPL) uruchamiasz wszystko od "__main__".

Więc jeśli sprawdzisz przed wykonaniem:

if __name__ == "__main__":
    do_important()

W związku z powyższym kod zostanie wykonany tylko wtedy, gdy zostanie uruchomiony jako moduł podstawowy (lub celowo wywołany z innego skryptu).

Jeszcze lepszy sposób

Istnieje Pythonic sposób na poprawęna to jednak.

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

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

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 końcową funkcję na końcu naszego modułu, która zostanie uruchomiona, jeśli uruchomimy moduł jako moduł podstawowy.

Umożliwi importowanie modułu i jego funkcji oraz klas do innych skryptów bez uruchamiania funkcji main, a także umożliwi wywoływanie modułu (oraz jego funkcji i klas) podczas uruchamiania z innego modułu '__main__', tj.

import important
important.main()

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

  

Ten moduł reprezentuje zakres (inaczej anonimowy), w którym   główny program interpretera wykonuje - polecenia odczytywane z   standardowe wejście, z pliku skryptu lub z interaktywnego monitu. To   jest to środowisko, w którym zwrotka „warunkowego skryptu”   powoduje uruchomienie skryptu:

if __name__ == '__main__':
    main()
    
470
2018-03-27 02: 27: 47Z

if __name__ == "__main__" to część uruchamiana, gdy skrypt jest uruchamiany z (na przykład) wiersza poleceń za pomocą polecenia takiego jak python myscript.py.

    
110
2015-07-10 15: 49: 13Z
  

Co robi if __name__ == "__main__":?

__name__ jest zmienną globalną (w Pythonie globalny oznacza na poziomie modułu ), który istnieje we wszystkich przestrzeniach nazw. Zwykle jest to nazwa modułu (jako typ str).

Jako jedyny przypadek specjalny w każdym uruchomionym procesie Pythona, jak w mycode.py:

python mycode.py

do anonimowej globalnej przestrzeni nazw przypisywana jest wartość '__main__' do jej __name__.

Tak więc, włączając ostatnie linie

if __name__ == '__main__':
    main()
  • na końcu skryptu mycode.py,
  • gdy jest to podstawowy moduł wejścia, który jest uruchamiany przez proces Pythona,

spowoduje uruchomienie unikatowo zdefiniowanej funkcji main skryptu.

Kolejna korzyść z używania tej konstrukcji: możesz również zaimportować swój kod jako moduł do innego skryptu, a następnie uruchomić główną funkcję, jeśli i kiedy program zdecyduje:

import mycode
# ... any amount of other code
mycode.main()
    
71
2017-01-10 17: 35: 04Z

Jest tu wiele różnych mechanizmów dotyczących omawianego kodu, „How”, ale dla mnie nic z tego nie miało sensu, dopóki nie zrozumiałem „Why”. Powinno to być szczególnie przydatne 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?

Po uruchomieniu xy.py, użytkownik import ab. Instrukcja importu uruchamia moduł natychmiast po zaimportowaniu, więc operacje ab zostaną wykonane przed resztą xy. Po zakończeniu ab, kontynuacja następuje xy.

Interpreter śledzi, które skrypty działają z __name__. Po uruchomieniu skryptu - bez względu na to, jak go nazwałeś - interpreter nazywa go "__main__", czyniąc go głównym lub „domowym” skryptem, który wraca do późniejszego uruchomienie zewnętrznego skryptu.

Każdy inny skrypt, który jest wywoływany z tego skryptu "__main__", otrzymuje nazwę pliku jako __name__ (np. __name__ == "ab.py"). Stąd linia if __name__ == "__main__": jest testem interpretera w celu określenia, czy interpretuje /analizuje skrypt „domowy”, który został pierwotnie wykonany, lub czy tymczasowo zagląda do innego (zewnętrznego) skryptu. Daje to programistom elastyczność, aby skrypt zachowywał się inaczej, jeśli jest wykonywany bezpośrednio, a wywoływany zewnętrznie.

Przejdźmy do powyższego kodu, aby zrozumieć, co się dzieje, skupiając się najpierw na nieulepionych liniach i kolejności, w jakiej pojawiają się w skryptach. Pamiętaj o tej funkcji - lub def - bloki nic nie robią same, dopóki nie zostaną wywołane. To, co tłumacz może powiedzieć, gdyby wymamrotał do siebie:

  • Otwórz xy.py jako plik „domowy”; nazwij to "__main__" w zmiennej __name__.
  • Importuj i otwieraj plik __name__ == "ab.py".
  • Och, funkcja. Pamiętam to.
  • OK, funkcja a(); Właśnie się tego dowiedziałem. Drukowanie ' Funkcja w pliku ab '.
  • Koniec pliku; powrót do "__main__"!
  • Och, funkcja. Pamiętam to.
  • Kolejny.
  • Funkcja x(); ok, drukowanie ' zadanie peryferyjne: może być przydatne w innych projektach '.
  • Co to jest? if oświadczenie. Cóż, warunek został spełniony (zmienna __name__ została ustawiona na "__main__"), więc wprowadzę funkcję main() i wydrukuję „ główną funkcję: jest to miejsce, gdzie akcja jest ”.

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

  

Po co to implementować?

Pamiętasz, co powiedziałem wcześniej o instrukcjach importu? Kiedy importujesz moduł, nie tylko go „rozpoznaje” i czeka na dalsze instrukcje - faktycznie uruchamia wszystkie wykonywalne operacje zawarte w skrypcie. Tak więc umieszczenie mięsa w skrypcie w funkcji main() skutecznie go poddaje kwarantannie, umieszczając w izolacji, tak aby nie uruchamiało się natychmiast po zaimportowaniu przez inny skrypt.

Znowu będą wyjątki, ale powszechną praktyką jest to, że main() zwykle nie jest wywoływane zewnętrznie. Być może zastanawiasz się jeszcze nad jedną rzeczą: jeśli nie dzwonimy pod numer main(), dlaczego w ogóle dzwonimy do skryptu? Jest tak, ponieważ wiele osób konstruuje swoje skrypty za pomocą samodzielnych funkcji, które są zbudowane tak, aby działały niezależnie od reszty kodu w pliku. Są później wywoływane gdzieś indziej w treści skryptu. Co mnie do tego prowadzi:

  

Ale kod działa bez niego

Tak, tak. Te oddzielne funkcje mogą być wywoływane ze skryptu wbudowanego, który nie jest zawarty w funkcji main(). Jeśli jesteś przyzwyczajony (tak jak ja, w moich wczesnych etapach programowania) do budowania skryptów in-line, które robią dokładnie to, czego potrzebujesz, a spróbujesz to zrozumieć ponownie, jeśli kiedykolwiek będziesz potrzebował tej operacji ponownie. . cóż, nie jesteś przyzwyczajony do tego rodzaju wewnętrznej struktury kodu, ponieważ kompilacja jest bardziej skomplikowana i nie jest tak intuicyjna w czytaniu.

Ale to jest 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 będzie ściśle powiązany ze starym, co spowoduje pojawienie się sprzecznych zmiennych.

Rozdzielając niezależne funkcje, zyskujesz możliwość ponownego wykorzystania poprzedniej pracy, wywołując je w innym skrypcie. Na przykład „example.py” może importować „xy.py” i wywoływać x(), korzystając z funkcji „x” z „xy.py”. (Może to jest pisanie wielkimi literami trzeciego słowa danego ciągu tekstowego; tworzenie tablicy NumPy z listy liczb i kwadraturowanie ich lub zmniejszanie powierzchni 3D. Możliwości są nieograniczone.)

(Na marginesie, to pytanie zawiera odpowiedź @kindall, która w końcu pomógł mi zrozumieć - dlaczego, a nie jak. Niestety, został oznaczony jako duplikat ten , który uważam za błąd.)

    
62
2018-05-23 22: 29: 32Z

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

Domyślnie (gdy moduł działa jako główny, nie zaimportowany) zmienna __name__ jest ustawiona na "__main__", a gdy zostanie zaimportowana, zmienna __name__ otrzyma inną wartość, prawdopodobnie nazwę modułu ('M') . Jest to pomocne w łączeniu różnych wariantów modułów i oddzielaniu ich konkretnych danych wejściowych i amp; instrukcje wyjściowe, a także jeśli są jakieś przypadki testowe.

W skrócie , użyj tego bloku „if __name__ == "main"”, aby zapobiec uruchomieniu (określonego) kodu podczas importowania modułu.

    
45
2018-05-23 22: 07: 29Z

Przyjrzyjmy się odpowiedzi 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 uruchamiamy „x.py”.

Ale tylko blok A (a nie B) jest uruchamiany, gdy uruchamiamy inny moduł, na przykład „y.py”, w którym xy jest importowany i kod jest uruchamiany stamtąd (np. gdy funkcja w „x. py „jest wywoływane z y.py).

    
35
2015-03-04 20: 31: 20Z

Mówiąc prościej, __name__ jest zmienną zdefiniowaną dla każdego skryptu, który określa, czy skrypt jest uruchamiany jako moduł główny, czy też 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__)

Wyjście z wykonywania script1 jest

Script 1's name: __main__

A wyjście z wykonania script2 to:

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

Jak widać, __name__ informuje nas, który kod jest modułem „głównym”. To wspaniałe, ponieważ możesz po prostu napisać kod i nie martwić się o problemy strukturalne, takie jak w C /C ++, gdzie, jeśli plik nie implementuje funkcji „main”, nie można go skompilować jako pliku wykonywalnego, a jeśli tak, to nie może być wtedy używany jako biblioteka.

Powiedzmy, że piszesz skrypt Pythona, który robi coś wspaniałego i implementujesz ładunek funkcji, które są przydatne do innych celów. Jeśli chcę z nich korzystać, mogę po prostu zaimportować skrypt i korzystać z nich bez uruchamiania programu (ponieważ kod działa tylko w kontekście if __name__ == "__main__":). Podczas gdy w C /C ++ musiałbyś rozdzielić te kawałki na oddzielny moduł, który następnie zawiera plik. Obraz sytuacji poniżej;

 Skomplikowane importowanie w C

Strzałki są łączami importu. W przypadku trzech modułów, z których każdy próbuje dołączyć kod poprzednich modułów, jest sześć plików (dziewięć, licząc pliki implementacyjne) i pięć łączy. Utrudnia to dołączenie innego kodu do projektu C, chyba że zostanie skompilowany specjalnie jako biblioteka. Teraz zrób to dla Pythona:

 Elegancki import w Pythonie

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

    
35
2018-05-23 22: 28: 19Z
  1. Ilustracja C /C ++ jest błędna: 3 razy ta sama nazwa jednostki ( plik1 ).
    2018-01-11 12: 59: 53Z

Po interaktywnym uruchomieniu Pythona lokalnej zmiennej __name__ przypisywana jest wartość __main__. Podobnie, gdy wykonujesz moduł Pythona ze strony command, zamiast importować go do innego modułu, jego atrybut __name__ ma przypisaną wartość __main__, a nie rzeczywistą nazwę modułu. W ten sposób moduły mogą patrzeć na własną wartość __name__, aby samodzielnie określić, w jaki sposób są używane, czy to jako wsparcie dla innego programu, czy jako główna aplikacja wykonywana z linii poleceń. Dlatego w modułach Pythona dość często występuje następujący idiom:

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.
    
32
2013-12-11 11: 23: 53Z

Rozważ:

if __name__ == "__main__":
    main()

Sprawdza, czy atrybut __name__ skryptu Pythona to "__main__". Innymi słowy, jeśli sam program jest wykonywany, atrybutem będzie __main__, więc program zostanie wykonany (w tym przypadku funkcja main()). p>

Jeśli jednak skrypt Pythona jest używany przez moduł, zostanie wykonany dowolny kod poza instrukcją if, tak więc if \__name__ == "\__main__" jest używany tylko do sprawdzenia, czy program jest używany jako moduł, a zatem decyduje, czy uruchomić kod.

    
29
2018-05-23 22: 31: 42Z

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

  

Co to jest __name__?

__name__ to DunderAlias ​​ - może być traktowany jako zmienna globalna (dostępna z modułów) i działa w podobny sposób jak global .

Jest to łańcuch (globalny, jak wspomniano powyżej) wskazany przez type(__name__) (uzyskując <class 'str'>) i jest wbudowanym standardem dla obu Python 3 i Python 2 wersje.

  

Gdzie :

Nie można go używać tylko w skryptach, ale można go znaleźć zarówno w interpreterze, jak iw modułach /pakietach.

Interpreter :

>>> print(__name__)
__main__
>>>

plik_testowy.py :

print(__name__)

Wynik __main__

Moduł lub pakiet:

somefile.py:

def somefunction():
    print(__name__)

test_file.py:

import somefile
somefile.somefunction()

Wynik somefile

Zwróć uwagę, że __name__ w pakiecie lub module pobiera nazwę pliku. Ścieżka rzeczywistego modułu lub ścieżki pakietu nie jest podana, ale ma swój własny DunderAlias ​​__file__, który na to pozwala.

Powinieneś to zobaczyć, gdzie __name__, gdzie jest to główny plik (lub program), zawsze zwraca __main__, a jeśli jest to moduł /pakiet lub cokolwiek innego, Skrypt Pythona zwróci nazwę pliku, z którego pochodzi.

  

Praktja :

Bycie zmienną oznacza, że ​​jej wartość może zostać zastąpiona („może” nie oznacza „powinien”), 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 zakłada się, że wartość __name__ to __main__ lub nazwa pliku. Po raz kolejny zmiana tej wartości domyślnej spowoduje większe zamieszanie, że zrobi to dobrze, powodując problemy w dalszej części linii.

example:

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

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

  

Teraz odpowiedzieć if __name__ == '__main__':

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

An if to instrukcja kontroli przepływu, która zawiera blok kodu, który zostanie wykonany, jeśli podana wartość jest prawdziwa. Widzieliśmy, że __name__ może przyjąć albo __main__ lub nazwa 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 być uruchomiony (lub jest to interpreter), a nie moduł lub pakiet zaimportowany do skryptu.

Jeśli rzeczywiście __name__ przyjmuje wartość __main__, to cokolwiek znajduje się w tym bloku kodu, zostanie wykonane.

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

  

Moduły :

__name__ można również użyć w modułach do zdefiniowania nazwy modułu

  

Warianty:

Możliwe jest również wykonywanie innych, mniej popularnych, ale przydatnych rzeczy za pomocą __name__, niektóre pokażę tutaj:

Wykonywanie tylko wtedy, gdy plik jest modułem lub pakietem:

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

Uruchamianie jednego warunku, jeśli plik jest głównym i innym, jeśli nie jest:

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

Możesz także użyć go, aby udostępnić funkcje /narzędzia pomocnicze runnable na pakietach i modułach bez skomplikowanego korzystania z bibliotek.

Pozwala również na uruchamianie modułów z linii poleceń jako główne skrypty, co może być również bardzo przydatne.

    
25
2018-05-23 22: 39: 09Z

Myślę, że najlepiej jest przełamać odpowiedź 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, Python ma także punkt wejścia do wykonywania, tj. główny. '__main__' to nazwa zakresu, w którym wykonywany jest kod najwyższego poziomu . Zasadniczo masz dwa sposoby korzystania z modułu Pythona: Uruchom go bezpośrednio jako skrypt lub zaimportuj. Gdy moduł jest uruchamiany jako skrypt, jego __name__ jest ustawione na __main__.

Tak więc wartość atrybutu __name__ jest ustawiona na __main__, gdy moduł jest uruchamiany jako program główny. W przeciwnym razie wartość __name__ będzie zawierać nazwę modułu.

    
22
2018-05-23 22: 30: 36Z

Jest to specjalny przypadek, gdy plik Pythona jest wywoływany z wiersza poleceń. Jest to zazwyczaj używane do wywoływania funkcji „main ()” lub wykonywania innego odpowiedniego kodu startowego, na przykład do 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 mówię, że powinieneś używać tego w kodzie produkcyjnym, ale służy on do zilustrowania, że ​​nie ma nic „magicznego” około if __name__ == '__main__'. Jest to dobra konwencja do wywoływania głównej funkcji w plikach Pythona.

    
20
2018-09-03 07: 05: 11Z
  1. Uważam, że ta zła forma jest 1) polegająca na efektach ubocznych i 2) nadużywaniu and. and służy do sprawdzania, czy obie wyrażenia boolowskie są prawdziwe. Ponieważ nie interesuje Cię wynik and, oświadczenie if bardziej wyraźnie informuje o twoich zamiarach.
    2013-12-26 18: 07: 26Z
  2. Pomijając pytanie, czy wykorzystanie zwarciowych operatorów boolowskich jako mechanizmu kontroli przepływu jest kiepskie, czy nie, większym problemem jest to, że w ogóle nie odpowiada na pytanie .
    2015-07-10 15: 33: 06Z

Istnieje wiele zmiennych, które system (interpreter Pythona) udostępnia pliki źródłowe (moduły). 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 znaleziony w nim kod. (Zauważ, że nie wywołuje wszystkich metod i funkcji zdefiniowanych w pliku, ale je definiuje.)

Zanim interpreter wykona plik kodu źródłowego, definiuje kilka specjalnych zmiennych dla tego pliku; __name__ to jedna z tych 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 (tzn. uruchamiany plik), ustawia specjalną zmienną __name__ dla tego pliku na wartość „__main__” .

Jeśli to jest importowane z innego modułu, __name__ zostanie ustawione na nazwę tego modułu.

Więc w twoim przykładzie w części:

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 wykonane tylko wtedy, gdy uruchomisz moduł bezpośrednio; blok kodu nie zostanie wykonany, jeśli inny moduł wywoła go /importuje, ponieważ wartość __name__ nie będzie równa się „ głównej ” w tej konkretnej instancji.

Mam nadzieję, że to pomoże.

    
19
2016-07-20 09: 30: 24Z

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

'__main__' to nazwa zakresu, w którym wykonywany jest kod najwyższego poziomu. __name__ modułu ma wartość '__main__', gdy jest odczytywany ze standardowego wejścia, skryptu lub interaktywnego monitu.

if __name__ == "__main__":
    # Execute only if run as a script
    main()
    
16
2018-05-23 22: 14: 07Z

Powód

if __name__ == "__main__":
    main()

to przede wszystkim unikanie blokady importu problemy wynikające z posiadania kodu bezpośrednio zaimportowanego . Chcesz, aby main() działał, jeśli plik został bezpośrednio wywołany (to jest przypadek __name__ == "__main__"), ale jeśli kod został zaimportowany, importer musi wprowadzić kod z prawdziwego modułu głównego, aby uniknąć problemów z blokowaniem importu.

Efektem ubocznym jest automatyczne wpisanie się do metodologii obsługującej wiele punktów wejścia. Możesz uruchomić swój program przy użyciu main() jako punktu wejścia, , ale nie musisz . Podczas gdy setup.py oczekuje main(), inne narzędzia używają alternatywnych punktów wejścia. Na przykład, aby uruchomić plik jako proces gunicorn, należy zdefiniować funkcję app() zamiast main(). Podobnie jak w przypadku setup.py, gunicorn importuje kod, więc nie chce, aby robił cokolwiek podczas importowania (z powodu importu) problem z blokadą).

    
14
2018-04-18 21: 05: 59Z
  1. Dobrze poznać blokadę importu . Czy mógłbyś wyjaśnić podpisz się do metodologii, która [...] trochę się rozstaje?
    2018-01-11 13: 06: 38Z
  2. @ Wolf: Sure. Dodałem kilka zdań na temat metodologii wielu punktów wejścia.
    2018-04-14 00: 26: 20Z

Czytałem tak dużo 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.

Aby być krótkim, musisz znać kilka punktów:

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

  2. Ze względu na punkt 1 możesz nie chcieć, aby wszystko było uruchamiane „a” podczas importowania

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

  4. __name__ jest niejawną zmienną we wszystkich modułach .py; po zaimportowaniu pliku a.py wartość __name__ modułu a.py jest ustawiana na nazwę pliku „a”; gdy a.py jest uruchamiane bezpośrednio przy użyciu „python a.py”, co oznacza, że ​​a.py jest punktem wejścia, to wartość __name__ modułu a.py jest ustawiona na ciąg __main__

  5. Na podstawie mechanizmu, w jaki python ustawia zmienną __name__ dla każdego modułu, czy wiesz, jak osiągnąć punkt 3? Odpowiedź jest dość prosta, prawda? Umieść warunek, jeśli: if __name__ == "__main__": ...; możesz nawet umieścić, jeśli __name__ == "a" w zależności od potrzeb funkcjonalnych

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

    
13
2018-06-24 15: 48: 36Z
  1. Tak, punkt 1 jest niezbędny do zrozumienia. Na tej podstawie potrzeba wyjaśnienia tego mechanizmu.
    2019-03-24 21: 16: 18Z

Rozważ:

print __name__

Wyjściem 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, to nie drukuje „metody bezpośredniej” , ponieważ podczas importowania ustawi ona __name__ equal to "first model name".

    
13
2019-02-06 23: 16: 06Z
  

Możesz użyć pliku jako skryptu oraz modułu importowanego .

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

    
12
2017-03-13 21: 44: 26Z

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

  1. Wywołaj klasę z innych plików. Wystarczy zaimportować go do programu wywołującego.

  2. Uruchom samodzielną klasę w celach testowych.

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

    
8
2018-10-18 03: 09: 32Z

Jeśli ten plik .py jest importowany przez inne pliki .py, kod pod „instrukcja if” nie zostanie wykonany.

Jeśli to .py są uruchamiane pod python this_py.py pod powłoką lub podwójnie kliknięte w systemie Windows. kod pod „the if statement” zostanie wykonany.

Zazwyczaj jest napisany do testowania.

    
5
2018-06-19 11: 44: 29Z

Utwórz plik, a.py :

print(__name__) # It will print out __main__

__name__ jest zawsze równe __main__, gdy plik jest uruchamiany bezpośrednio , pokazując, że jest to plik główny.

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

import a  # Prints a

Uruchom go. Zostanie wydrukowany a , to znaczy nazwa pliku, który jest importowany .

Aby pokazać dwa różne zachowania tego samego pliku , jest to powszechnie stosowana sztuczka:

# Code to be run when imported into another python file

if __name__ == '__main__':
    # Code to be run only when run directly
    
4
2018-05-23 22: 34: 14Z

jeśli nazwa == ' główna ”:

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

Sprawdza, czy moduł jest importowany, czy nie.

Innymi słowy, kod w bloku if zostanie wykonany tylko wtedy, gdy kod zostanie uruchomiony bezpośrednio. Tutaj directly oznacza not 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__
    
3
2018-05-23 22: 36: 51Z

Wszystkie odpowiedzi dość dokładnie wyjaśniają funkcjonalność. Ale podam jeden przykład jego użycia, który może pomóc w dalszym wyjaśnianiu koncepcji.

Załóżmy, że masz dwa pliki Pythona, a.py i b.py. Teraz a.py importuje b.py. Uruchamiamy plik a.py, gdzie najpierw wykonywany jest kod „import b.py”. Zanim reszta kodu a.py zostanie uruchomiona, kod w pliku b.py musi działać całkowicie.

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

To jest właśnie ta linia sprawdzania kodu. Jeśli jest to główny plik (tj. B.py) uruchamiający kod, który w tym przypadku nie jest (a.py jest głównym plikiem uruchomionym), wtedy wykonywany jest tylko kod.

    
3
2018-05-23 22: 38: 56Z

Po prostu jest to punkt wejścia do uruchomienia pliku, np. main w języku programowania C .

    
2
2019-02-06 23: 13: 57Z
  1. Ta odpowiedź zakłada, że ​​OP (lub dowolny użytkownik o podobnym pytaniu) obaj znają C i wiem, jaki jest punkt wejścia.
    2019-02-22 12: 44: 37Z
  2. Ta odpowiedź zakłada również, że przed blokiem if __name__ == "__main__" nie ma żadnego kodu (innego niż definicje bez skutków ubocznych). Technicznie górna część wykonywanego skryptu jest punktem wejścia programu.
    2019-04-09 21: 35: 39Z

Każdy moduł w pythonie ma atrybut nazywany nazwą . Wartość atrybutu nazwa to „ główny ”, gdy moduł jest uruchomiony bezpośrednio. W przeciwnym razie wartość nazwy to nazwa modułu.

Mały przykład na krótkie wyjaśnienie.

#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 wykonać to bezpośrednio jako

python test.py  

Wyjście

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

Po wykonaniu tego

python external_calling.py

Wyjście

42
I am inside hello_world
test

Powyższe jest oczywiste, że gdy wywołasz test z innego skryptu, jeśli pętla name w pliku test.py nie zostanie wykonana.

    
1
2019-06-12 09: 28: 39Z
źródło umieszczone tutaj