Pytanie Co zrobić, jeśli __name__ == "__main__": zrobić?


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

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

4149
2018-01-07 04:11


pochodzenie




Odpowiedzi:


Kiedy interpreter Pythona odczytuje plik źródłowy, wykonuje cały znaleziony w nim kod.

Przed wykonaniem kodu zdefiniuje kilka specjalnych zmiennych. Na przykład, jeśli interpreter Pythona uruchamia ten moduł (plik źródłowy) jako program główny, ustawia specjalny __name__ zmienna, aby mieć wartość "__main__". Jeśli ten plik jest importowany z innego modułu, __name__ zostanie ustawiony na nazwę modułu.

W przypadku twojego skryptu przyjmijmy, że jest on wykonywany jako główna funkcja, np. powiedziałeś coś takiego

python threading_example.py

w linii poleceń. Po ustawieniu zmiennych specjalnych uruchomi się import oświadczenie i załaduj te moduły. Następnie oceni on def blok, tworzenie obiektu funkcji i tworzenie zmiennej o nazwie myfunction który wskazuje obiekt funkcji. Następnie odczyta if oświadczenie i zobacz to __name__ jest równy "__main__", więc wykona pokazany tam blok.

Jednym z powodów tego jest to, że czasami piszesz moduł (a .py plik), gdzie można go wykonać bezpośrednio. Alternatywnie można go również zaimportować i wykorzystać w innym module. Wykonując główną kontrolę, możesz mieć ten kod tylko wykonać, gdy chcesz uruchomić moduł jako program i nie ma go wykonać, gdy ktoś chce zaimportować twój moduł i samodzielnie wywołać funkcje.

Widzieć ta strona dla niektórych dodatkowych szczegółów.


4421
2018-01-07 04:26



Uwaga: Jeśli umieścisz kod przed definicjami funkcji, zostanie wykonany przed głównym. print("This code executes before main.") def functionA(): print("Function A") def functionB(): print("Function B") if __name__ == '__main__': functionA() functionB()  Ten kod powoduje: This code executes before main. Function A Function B - Stainsor


Kiedy twój 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 nich nie jest uruchamiany. W przeciwieństwie do innych języków, nie ma main() funkcja uruchamiana automatycznie - main() funkcja jest niejawnie całym kodem na najwyższym poziomie.

W tym przypadku kod najwyższego poziomu to if blok. __name__ jest wbudowaną zmienną, która ocenia nazwę bieżącego modułu. Jednakże, jeśli moduł jest uruchamiany bezpośrednio (jak w myscript.py powyżej) __name__ zamiast tego jest ustawiony na ciąg "__main__". W ten sposób można sprawdzić, czy skrypt jest uruchamiany bezpośrednio lub czy jest 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 tamtym korpusie if powyższa klauzula nie zostanie uruchomiona, ponieważ warunek nie zostanie 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łasz interpreter jako

python one.py

Wyjście będzie

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

Jeśli biegniesz two.py zamiast:

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

Tak więc, gdy moduł one zostaje załadowany, jego __name__ równa się "one" zamiast "__main__".


1415
2018-01-07 04:28



Doskonałe wyjaśnienie. - Poles


Najprostsze wytłumaczenie dla __name__ zmienna (imho) jest następująca:

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 spowoduje uzyskanie tego wyniku:

$ python a.py
Hello World from b!

Jak widać, po zaimportowaniu modułu ustawia się Python globals()['__name__'] w tym module do nazwy modułu.

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

Jak widać, kiedy plik jest uruchamiany, Python ustawia globals()['__name__'] w tym pliku do "__main__".


562
2018-01-07 11:35





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

Aby opisać podstawy:

  • Zmienna globalna, __name__w module, który jest punktem wejścia do twojego programu, jest '__main__'. W przeciwnym razie jest to nazwa, do której moduł jest importowany.

  • Więc kod pod if blok będzie działał tylko wtedy, gdy moduł jest punktem wejścia do twojego programu.

  • Pozwala to na import kodu z modułu przez inne moduły, bez wykonywania poniższego bloku kodu podczas importu.


Dlaczego tego potrzebujemy?

Opracowywanie i testowanie twojego kodu

Załóżmy, że piszesz skrypt w języku Python, który ma być używany jako moduł:

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

ty mógłby przetestuj moduł, dodając to wywołanie funkcji do dołu:

do_important()

i uruchamianie go (w wierszu polecenia) z czymś takim jak:

~$ python important.py

Problem

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

import important

Podczas importowania do_important funkcja zostanie wywołana, więc prawdopodobnie skomentujesz swoje wywołanie funkcji, do_important(), na dnie.

# 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 zapomnisz, co sprawi, że twój proces rozwoju będzie bardziej kłopotliwy.

Lepsza droga

The __name__ zmienia punkty w przestrzeń nazw, gdziekolwiek aktualnie znajduje się interpreter Pythona.

Wewnątrz importowanego modułu jest to nazwa tego modułu.

Ale w module podstawowym (lub interaktywnej sesji Pythona, tj. Read, Eval, Print Loop lub REPL interpretera) uruchamiasz wszystko od "__main__".

Więc jeśli sprawdzisz przed wykonaniem:

if __name__ == "__main__":
    do_important()

Dzięki powyższemu kod będzie wykonywany tylko wtedy, gdy uruchamiasz go jako moduł podstawowy (lub celowo wywołasz go z innego skryptu).

Jeszcze lepszy sposób

Istnieje jednak Pythoniczny sposób na poprawę tego.

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

Jeśli umieścimy kod, który chcemy wykonać, opracujemy i przetestujemy w funkcji podobnej do tej, a następnie sprawdzimy '__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 funkcję końcową dla naszego modułu, która będzie działać, jeśli uruchomimy moduł jako moduł podstawowy.

Umożliwi to import modułu i jego funkcji oraz klas do innych skryptów bez uruchamiania main funkcja, a także pozwala modułowi (i jego funkcjom i klasom) na wywoływanie podczas uruchamiania z innego '__main__' moduł, tj.

import important
important.main()

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

Ten moduł reprezentuje (w przeciwnym razie anonimowy) zakres, w którym   uruchamia się program główny interpretera - polecenia odczytane z   standardowe wejście, z pliku skryptu lub z interaktywnego monitu. To   jest to środowisko, w którym znajduje się idiomatyczna sekcja "skryptu warunkowego"   powoduje uruchomienie skryptu:

if __name__ == '__main__':
    main()

413
2017-11-23 04:38





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


92
2018-01-07 04:14





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

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

Jednak jako jedyny specjalny przypadek w każdym uruchomionym Pythonie, tak jak w mycode.py:

python mycode.py

w przeciwnym razie anonimowy globalny obszar nazw ma przypisaną wartość '__main__' do tego __name__.

Tak więc, w tym końcowe linie

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

spowoduje wyjątkowe zdefiniowanie twojego skryptu main funkcja do uruchomienia.

Kolejna zaleta korzystania z 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()

57
2017-10-14 20:22





Tutaj jest wiele różnych podejść do mechaniki danego kodu, "Jak", 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 zaimportowaniu, więc aboperacje zostaną wykonane przed pozostałą częścią xy. Po zakończeniu ab, to trwa dalej xy.

Interpreter śledzi, które skrypty są uruchomione __name__. Kiedy uruchamiasz skrypt - bez względu na to, jak go nazwałeś - tłumacz nazywa to "__main__", dzięki czemu jest to skrypt główny lub "domowy", do którego zwracany jest po uruchomieniu zewnętrznego skryptu.

Każdy inny skrypt, który jest wywoływany z tego "__main__" skryptowi przypisano nazwę pliku jako jego __name__ (na przykład., __name__ == "ab.py"). Stąd linia if __name__ == "__main__": jest testem tłumacza, który określa, czy interpretuje / parsuje skrypt "domowy", który został początkowo wykonany, czy też tymczasowo zagląda do innego (zewnętrznego) skryptu. Daje to programistom możliwość elastycznego zachowania się skryptu, jeśli jest on wykonywany bezpośrednio, a wywołany zewnętrznie.

Przejdźmy przez powyższy kod, aby zrozumieć, co się dzieje, skupiając się najpierw na niesprecyzowanych liniach i kolejności, w jakiej pojawiają się w skryptach. Zapamiętaj tę funkcję - lub def - bloki nic nie robią same, dopóki nie zostaną wywołane. Co może powiedzieć tłumacz, jeśli wymamrotał do siebie:

  • Otwórz xy.py jako plik "domowy"; nazwać "__main__" w __name__ zmienna.
  • Importuj i otwieraj plik przy pomocy __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.
  • Funkcjonować x(); ok, drukowanie "zadanie peryferyjne: może być przydatne w innych projektach".
  • Co to jest? Na if komunikat. Cóż, warunek został spełniony (zmienna __name__został ustawiony na "__main__"), więc wejdę do main() funkcja i wydruk "główna funkcja: tu jest akcja".

Dwie dolne linie oznaczają: "Jeśli to jest "__main__" lub skrypt "home", wykonaj funkcję o nazwie main()Dlatego właśnie zobaczysz def main(): block up top, który zawiera główny strumień funkcjonalności skryptu.

Po co to wdrażać?

Pamiętasz, co powiedziałem wcześniej o instrukcjach importowania? Kiedy importujesz moduł, nie tylko go "rozpoznaje" i czeka na dalsze instrukcje - faktycznie uruchamia wszystkie operacje wykonywalne zawarte w skrypcie. Wstawianie mięsa do skryptu main() funkcja skutecznie poddaje ją kwarantannie, umieszczając ją w izolacji, aby nie była uruchamiana natychmiast po zaimportowaniu przez inny skrypt.

Znowu będą wyjątki, ale powszechną praktyką jest to main() zwykle nie jest wywoływany zewnętrznie. Więc możesz się zastanawiać jeszcze jednej rzeczy: jeśli nie dzwonimy main(), dlaczego w ogóle wywołujemy scenariusz? Dzieje się tak, ponieważ wiele osób konstruuje swoje skrypty za pomocą autonomicznych funkcji, które są zbudowane tak, aby działały niezależnie od reszty kodu w pliku. Następnie są one później wywoływane gdzie indziej w treści skryptu. Co prowadzi mnie do tego:

Ale kod działa bez niego

Tak to prawda. Te oddzielne funkcje mogą być wywołanym ze skryptu in-line, który nie jest zawarty w a main() funkcjonować. Jeśli jesteś przyzwyczajony (tak jak ja, na moich wczesnych etapach programowania) do budowania wbudowanych skryptów, które wykonują dokładnie to, czego potrzebujesz, i spróbujesz to odkryć ponownie, jeśli będziesz potrzebować tej operacji ponownie. cóż, nie jesteś przyzwyczajony do tego rodzaju wewnętrznej struktury kodu, ponieważ jest on bardziej skomplikowany w budowaniu i nie jest tak intuicyjny w czytaniu.

Ale jest to skrypt, który prawdopodobnie nie może mieć swoich funkcji nazywanych zewnętrznie, ponieważ gdyby tak się stało, 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 związany ze starym, że będą występowały sprzeczne zmienne.

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 zaimportować "xy.py" i wywołać x(), korzystając z funkcji "x" z "xy.py". (Może kapitalizuje trzecie słowo danego ciągu tekstowego, tworzy tablicę NumPy z listy liczb i wyrównuje je lub odrzuca powierzchnię 3D.) Możliwości są nieograniczone).

(Tak na marginesie, to pytanie zawiera odpowiedź @kindall, która w końcu pomogła mi zrozumieć - dlaczego, a nie w jaki sposób. Niestety został oznaczony jako duplikat ten, co moim zdaniem jest błędem.)


47
2017-09-29 04:33





Kiedy w naszym module znajdują się pewne stwierdzenia (M.py) chcemy zostać wykonany, gdy będzie on działał jako główny (nie importowany), możemy umieścić te instrukcje (test-case, print statement) pod tym ifblok.

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

W skrócie, Użyj tego 'if __name__ == "main" 'Blokuj, aby zapobiec (pewnemu) kodowi, który jest uruchamiany podczas importowania modułu.


39
2018-04-03 14:09





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 uruchamiamy "x.py".

Ale tylko blok A (a nie B) jest uruchamiany, gdy uruchamiamy inny moduł, na przykład "y.py", w którym importujemy xy i uruchamiany jest kod (np. Gdy funkcja w "x.py" jest wywołana z y.py).


32
2018-01-20 17:48





Kiedy uruchamiasz Pythona interaktywnie lokalnie __name__ zmienna ma przypisaną wartość __main__. Podobnie, po uruchomieniu modułu Python z wiersza poleceń, zamiast importowania go do innego modułu, jego __name__ atrybut ma przypisaną wartość __main__, zamiast rzeczywistej nazwy modułu. W ten sposób moduły mogą same wyglądać __name__ wartość, aby samodzielnie określić, w jaki sposób są używane, jako wsparcie dla innego programu lub jako główna aplikacja wykonywana z wiersza poleceń. Tak więc następujący idiom jest dość powszechny w modułach Pythona:

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.

30
2017-12-11 11:23





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 też jest uruchamiany jako importowany moduł.

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 skryptu 1 jest

Script 1's name: __main__

A wyjście z wykonywania skryptu 2 to:

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

Jak widzisz, __name__ mówi nam, który kod jest "głównym" modułem. To jest świetne, ponieważ możesz po prostu napisać kod i nie musisz 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 używać jako biblioteki.

Załóżmy, że napisałeś skrypt w języku Python, który robi coś wspaniałego, i implementujesz mnóstwo funkcji przydatnych do innych celów. Jeśli chcę z nich korzystać, mogę po prostu zaimportować twój skrypt i użyć go bez uruchamiania twojego programu (biorąc pod uwagę, że twój kod wykonuje się tylko wewnątrz if __name__ == "__main__": kontekst). Podczas gdy w C / C ++ musiałbyś podzielić te fragmenty na osobny moduł, który następnie zawiera plik. Wyobraź sobie sytuację poniżej;

Complicated importing in C

Strzałki są linkami importowymi. Dla trzech modułów, z których każdy próbuje dołączyć poprzedni kod modułów, znajduje się sześć plików (dziewięć, licząc pliki implementacji) i pięć linków. To sprawia, że ​​trudno jest dołączyć inny kod do projektu C, chyba że zostanie skompilowany specjalnie jako biblioteka. Teraz wyobraź sobie to dla Pythona:

Elegant importing in Python

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


29
2017-10-15 09:07



Ilustracja C / C ++ jest błędna: 3 razy ta sama nazwa jednostki (plik1). - Wolf