Što učiniti ako __name__ == "__main__": učinite?

Što 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)) 
4672
07 янв. Posvećeno 07. siječnja 2009-01-07 07:11 '09 u 7:11 AM 2009-01-07 07:11
ответ 31 odgovor
  • 1
  • 2

Kad god Python interpreter čita izvornu datoteku, ona radi dvije stvari:

  • postavlja nekoliko posebnih varijabli, kao što je __name__ , a zatim

  • izvršava sav kôd koji se nalazi u datoteci.

Pogledajmo kako to funkcionira i kako se odnosi na vaše pitanje o __name__ provjerama koje uvijek vidimo u Python skriptama.

Primjer koda

Iskoristimo malo drugačiji uzorak kako bismo saznali kako rade uvoz i skripte. Pretpostavimo da je sljedeće u datoteci pod nazivom 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") 

Posebne varijable

Kada Python interpreter čita izvornu datoteku, najprije definira nekoliko posebnih varijabli. U ovom slučaju vodimo računa o varijabli __name__ .

Kada je vaš modul glavni program

Ako svoj modul (izvornu datoteku) koristite kao glavni program, na primjer,

 python foo.py 

tumač će dodijeliti hard-kodirani niz "__main__" varijabli __name__ , tj.

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

Kada vaš modul uvozi drugi

S druge strane, pretpostavimo da je neki drugi modul glavni program i uvozi vaš modul. To znači da u glavnom programu ili nekom drugom modulu glavni program uvozi takvog operatora:

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

U tom slučaju, tumač će pogledati naziv datoteke vašeg modula, foo.py , foo.py .py i dodijeliti ovu liniju varijabli __name__ vašeg modula, tj.

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

Izvođenje koda modula

Nakon postavljanja posebnih varijabli, tumač izvršava sav kôd u modulu, jedan po jedan izraz. Možete otvoriti drugi prozor sa strane uzorka koda tako da možete slijediti ovo objašnjenje.

uvijek

Najprije ispisuje niz "before import" (bez navodnika).

Drugo, učitava math modul i dodjeljuje ga varijabli pod nazivom math . To je ekvivalentno zamjeni import math sa sljedećim (imajte na umu da je __import__ funkcija niske razine u Pythonu koja prihvaća niz i započinje stvarni uvoz):

 # Find and load a module given its string name, "math", # then assign it to a local variable called math. math = __import__("math") 

Treće, ispisuje niz "before functionA" .

Četvrto, izvršava def blok, stvarajući funkcionalni objekt, a zatim dodjeljujući ovaj funkcionalni objekt varijabli pod nazivom functionA .

Peto, ispisuje niz "before functionB" .

Šesto, izvršava drugi blok def stvaranjem drugog funkcijskog objekta, a zatim ga dodjeljuje varijabli pod nazivom functionB .

Sedmo, ispisuje niz "before __name__ guard" .

Samo kada je vaš modul glavni program.

Osmo, ako je vaš modul glavni program, vidjet ćete da je __name__ doista postavljen na "__main__" i poziva dvije funkcije upisivanjem linija "Function A" i "Function B 10.0" .

Samo kada vaš modul uvozi drugi.

Osmi (umjesto), ako vaš modul nije glavni program, a drugi je uvezen, onda će __name__ biti "foo" a ne "__main__" , te će preskočiti tijelo if .

uvijek

Deveto, u obje situacije će se ispisati niz "after __name__ guard" .

rezime

Na kraju, to je ono što će biti tiskano u dva slučaja:

 # What gets printed if foo is imported as a regular module before import before functionA before functionB before __name__ guard after __name__ guard 

Zašto ovo radi ovako?

Možete se prirodno zapitati zašto netko to želi. Pa, ponekad želite napisati .py datoteku koju mogu koristiti drugi programi i moduli kao modul i mogu se pokrenuti kao glavni program. primjeri:

  • Vaš modul je knjižnica, ali želite imati skriptni način u kojem izvodi neke testove jedinica ili demonstracije.

  • Vaš se modul koristi samo kao glavni program, ali ima nekoliko testova jedinica, a testna okolina radi tako da uvozi .py datoteke kao što je vaša skripta i izvodi posebne funkcije testiranja. Ne želite da pokuša izvesti skriptu samo zato što uvozi modul.

  • Vaš se modul uglavnom koristi kao glavni program, ali pruža i zgodan API programera za napredne korisnike.

Osim ovih primjera, elegantno je da pokretanje skripte u Pythonu jednostavno postavlja nekoliko čarobnih varijabli i uvozi skriptu. Pokretanje skripte je nuspojava uvoza modula skripte.

Hrana za razmišljanje

  • Pitanje: Mogu li imati nekoliko blokova za provjeru __name__ ? Odgovor: to je čudno, ali jezik vas neće zaustaviti.

  • Pretpostavimo sljedeće u foo2.py Što se događa ako kažete python foo2.py u naredbenom retku? Zašto?

 # 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") 
  • Što će učiniti kada se koristi kao skripta? Kada se uvozi kao modul?
5003
07 янв. odgovor je dat gospodinu Foozu 07. sij 2009-01-07 07:26 '09 u 7:26 AM 2009-01-07 07:26

Kada se vaša skripta pokrene, proslijedite je kao naredbu Python interpreteru,

 python myscript.py 

izvršava se cijeli kôd, koji je na razini uvlake 0. Određene funkcije i klase su definirane, ali nisu definirane, ali niti jedan njihov kod ne počinje. Za razliku od drugih jezika, ne postoji funkcija main() koja se automatski pokreće - funkcija main() implicitno sadrži sav kod na najvišoj razini.

U ovom slučaju, kôd najviše razine je blok if . __name__ je ugrađena varijabla koja procjenjuje ime trenutnog modula. Međutim, ako se modul pokreće izravno (kao gore u myscript.py ), tada se postavlja niz "__main__" umjesto __name__ . Na taj način možete provjeriti izvršava li se vaša skripta izravno ili uvozi nešto drugo testiranjem

 if __name__ == "__main__": ... 

Ako je vaša skripta uvezena u drugi modul, uvozit će se njezine različite definicije funkcija i klasa, a izvršit će se i njezin najviši kôd, ali kôd u istom testu gore if gore dobiven, dobivat će se jer uvjet nije ispunjen. Kao osnovni primjer razmotrite sljedeća dva scenarija:

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

Sada, ako nazovete tumača kao

border=0
 python one.py 

Izlaz će biti

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

Ako pokrenete two.py :

 python two.py 

Dobivate

 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 

Dakle, kada je one modul učitan, njegov __name__ je "one" umjesto "__main__" .

1577
07 янв. odgovor je dao Adam Rosenfield 07 jan. 2009-01-07 07:28 '09 u 7:28 2009-01-07 07:28

Najjednostavnije objašnjenje varijable __name__ ( __name__ ) je sljedeće:

Stvorite sljedeće datoteke.

 # a.py import b 

i također

 # b.py print "Hello World from %s!" % __name__ if __name__ == '__main__': print "Hello World again from %s!" % __name__ 

Pokrećući ih, dobivate sljedeći zaključak:

 $ python a.py Hello World from b! 

Kao što možete vidjeti, kada se modul uvozi, Python postavlja globals()['__name__'] u ovom modulu na naziv modula. Također, pri uvozu, pokreće se sav kôd u modulu. Budući da se if ocjenjuje kao False ovaj dio se ne izvršava.

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

Kao što možete vidjeti, kada se datoteka izvrši, Python instalira globals()['__name__'] u ovu datoteku u "__main__" . Ovaj put, if se ocjenjuje kao True i izvršava se.

615
odgovor je dan pi. 07. \ T 2009-01-07 14:35 '09 u 14:35 2009-01-07 14:35

Što if __name__ == "__main__": :?

Opisati osnove:

  • Globalna varijabla __name__ u modulu, koji je ulazna točka vašeg programa, je '__main__' . U suprotnom, to je ime u koje uvezete modul.

  • Dakle, kôd ispod bloka if bit će pokrenut samo ako je modul ulazna točka vašeg programa.

  • To vam omogućuje da uvezete kod u modul drugim modulima, bez izvođenja bloka koda pod uvozom.


Zašto nam je to potrebno?

Razvoj i testiranje koda

Pretpostavimo da pišete Python skriptu namijenjenu za upotrebu kao modul:

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

Modul možete testirati dodavanjem poziva funkcije na dno:

 do_important() 

i pokretanje (u naredbenom retku) s nečim poput:

 ~$ python important.py 

Problem je

Međutim, ako želite uvesti modul u drugu skriptu:

 import important 

Uvoz će pozvati funkciju do_important , tako da ćete vjerojatno komentirati vaš poziv do funkcije do_important() nastavku.

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

I onda ćete morati zapamtiti ako ste komentirali poziv test funkciji. A ova dodatna složenost znači da ćete vjerojatno zaboraviti što će vaš razvojni proces učiniti težim.

Najbolji način

Varijabla __name__ odnosi se na prostor imena gdje god se Python trenutno nalazi.

Unutar uvezenog modula nalazi se naziv ovog modula.

Ali unutar primarnog modula (ili Python interaktivne sesije, tj. Interpretera Read, Eval, Print loop ili REPL interpretera), pokrećete sve od "__main__" .

Dakle, ako prije toga provjerite:

 if __name__ == "__main__": do_important() 

S gore navedenim, vaš će se kod izvršiti samo ako ga koristite kao glavni modul (ili ga namjerno nazovete iz druge skripte).

Još bolji način

Postoji Pythonov način da ga poboljšamo.

Što ako želimo pokrenuti ovaj poslovni proces izvan modula?

Ako stavimo kod koji želimo implementirati kada razvijemo i testiramo u takvoj funkciji, a zatim '__main__' provjeru '__main__' odmah nakon:

 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 our payoff idiom! if __name__ == '__main__': main() 

Sada imamo završnu funkciju za kraj našeg modula, koja će raditi ako pokrenemo modul kao primarni modul.

To će omogućiti da se modul i njegove funkcije i klase uvoze u druge skripte bez pokretanja main funkcije, a također vam omogućuje da pozovete modul (i njegove funkcije i klase) kada radite s drugim '__main__' , tj.

 import important important.main() 

Ovaj idiom se također može naći u Python dokumentaciji u objašnjenju modula __main__ . Ovaj tekst navodi:

Ovaj modul predstavlja (inače anonimno) područje u kojem je glavni program za tumačenje naredbe koje se mogu čitati ili iz standardnog ulaza, iz datoteke skripte ili iz interaktivne naredbe. To je okruženje u kojem idiomatska strofa "uvjetne skripte" uzrokuje pokretanje skripte:

 if __name__ == '__main__': main() 
451
23 нояб. odgovor je dao Aaron Hall 23. studenog. 2013-11-23 07:38 '13 u 7:38 am 2013-11-23 07:38

if __name__ == "__main__" dio koji se izvršava kada se skripta pokrene iz (recimo) naredbenog retka koristeći naredbu kao što je python myscript.py .

100
07 янв. odgovor dao Harley Holcombe 07. \ t 2009-01-07 07:14 '09 u 7:14 AM 2009-01-07 07:14

Što if __name__ == "__main__": :?

__name__ je globalna varijabla (u Pythonu, globalno zapravo znači na razini razine modula ) koja postoji u svim prostorima imena. Obično je to naziv modula (poput tipa str ).

Međutim, kao jedini posebni slučaj, u bilo kojem pokrenutom Python procesu, kao u mycode.py:

 python mycode.py 

u suprotnom, anonimnom globalnom prostoru naziva dodijeljena je vrijednost '__main__' svoj __name__ .

Dakle, uključujući i završne crte

 if __name__ == '__main__': main() 
  • na kraju skripte mycode.py,
  • kada je to osnovni početni modul koji je pokrenut od strane python procesa,

će dovesti do izvršenja jedinstvene funkcije main skripta.

Još jedna prednost korištenja ovog konstrukta: možete uvesti svoj kôd kao modul u drugu skriptu, a zatim pokrenuti glavnu funkciju ako i kada vaš program odluči:

 import mycode # ... any amount of other code mycode.main() 
66
14 окт. odgovor je dao Aaron Hall 14. listopada. 2014-10-14 23:22 '14 u 23:22 2014-10-14 23:22

Postoji mnogo različitih razmatranja mehanike šifre u pitanju, "Kako", ali za mene to nije imalo smisla dok nisam shvatila "Zašto". To bi trebalo biti osobito korisno za nove programere.

Preuzmite datoteku "ab.py":

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

I druga datoteka "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() 

Što zapravo radi ovaj kôd?

Kada izvršite xy.py , import ab . Izvoz importa pokreće modul odmah nakon uvoza, tako da se ab operacije izvode do ostatka xy . Završivši s ab , nastavit će s xy .

Interpreter prati koje skripte rade s __name__ . Kada pokrenete skriptu - bez obzira na to kako ga zovete, prevoditelj ga naziva "__main__" , što ga čini master ili "home" skriptom, koja se vraća nakon pokretanja vanjske skripte.

Svaka druga skripta nazvana "__main__" iz ove skripte dodjeljuje svoje ime datoteke kao svoj __name__ (na primjer, __name__ == "ab.py" ). Stoga je linija, if __name__ == "__main__": testni tumač kako bi utvrdio da li interpretira / obrađuje "home" skriptu koja je izvorno izvršena ili ako privremeno gleda u drugu (vanjsku) skriptu. To daje fleksibilnost programeru tako da se skripta ponaša drugačije ako je izvršena izravno ili je pozvana izvana.

Dopustite mi da prođem kroz gornji kod kako bih razumio što se događa tako da se prvo usredotočim na neprimjetne linije i redoslijed koji predstavljaju u skriptama. Zapamtite da funkcije - ili def - blokovi sami ne rade ništa dok ih se ne pozove. Što može tumač reći ako promrmlja sebi:

  • Otvorite xy.py datoteku kao "home" datoteku; ime je "__main__" u varijabli __name__ .
  • Uvezite i otvorite datoteku s __name__ == "ab.py" .
  • Oh, funkcija. Sjetit ću se ovoga.
  • Pa, a() ; Upravo sam saznao za to. Ispis "Funkcija u ab datoteci".
  • Kraj datoteke; natrag na "__main__" !
  • Oh, funkcija. Sjetit ću se ovoga.
  • Još jedan.
  • Funkcija x() ; ok, ispis "periferni zadatak: može biti koristan u drugim projektima."
  • Što je ovo? if Pa, uvjet je ispunjen (varijabla __name__ je postavljena na "__main__" ), tako da ću ući u main() funkciju i ispisati "glavnu funkciju: to je mjesto gdje je akcija."

Donja dva retka znače: "Ako je ovo skripta "__main__" ili" home ", izvršite funkciju main() ". Zato ćete vidjeti def main(): blokirati vrh, koji sadrži glavni tok skriptnih funkcija.

Zašto ga provoditi?

Sjećate li se što sam ranije rekao o uvoznim aplikacijama? Prilikom uvoza modula on ne samo da ga "prepoznaje" i čeka daljnje upute - on zapravo izvršava sve izvršne operacije sadržane u skripti. Dakle, dodavanje mesa vaše skripte u funkciju main() učinkovito je stavlja u karantenu, izolirajući je tako da se ne pokrene odmah kada se uvozi pomoću druge skripte.

Opet, bit će iznimaka, ali uobičajena praksa je da se main() obično ne zove eksterno pozvan. Stoga vas može zanimati još jedna stvar: ako ne zovemo main() , zašto uopće zovemo skriptu? To je zato što mnogi ljudi grade svoje skripte s autonomnim funkcijama koje su stvorene da rade neovisno o ostatku koda u datoteci. Zatim se kasnije nazivaju drugdje u tekstu scenarija. To me dovodi do sljedećeg:

Ali kod radi bez njega.

Da, to je točno. Ove pojedinačne funkcije mogu se pozvati iz ugrađene skripte koja nije sadržana u main() funkciji. Ako ste navikli (kao što sam ja, u ranim fazama programiranja) na stvaranje ugrađenih skripti koje rade upravo ono što vam je potrebno, i pokušat ćete ponovno shvatiti ako vam je potrebna ova operacija ponovno. dobro, niste navikli na takvu unutarnju strukturu koda, jer je teže graditi i nije tako lako intuitivno.

Ali ovo je scenarij koji vjerojatno ne bi mogao imati svoje funkcije izvana, jer ako je to učinio, odmah bi počeo izračunavati i dodjeljivati ​​varijable. I, najvjerojatnije, ako pokušate ponovno koristiti funkciju, vaša nova skripta je usko povezana sa starom, da će postojati konfliktne varijable.

Dijeleći neovisne funkcije, dobivate mogućnost da ponovno upotrijebite svoj prethodni rad tako što ćete ih pozvati u drugu skriptu. Primjerice, example.py može uvesti xy.py i nazvati x() koristeći x funkciju iz xy.py. (Možda izravnava treću riječ zadane tekstualne linije, kreira NumPy niz iz popisa brojeva i kvadrira ih ili dešifrira trodimenzionalnu površinu. Mogućnosti su beskonačne).

(Osim toga, ovo pitanje sadrži odgovor iz @kindalla, koji mi je naposljetku pomogao da shvatim zašto, a ne kako. Na žalost, ovo je zabilježeno kao duplikat ovoga , što smatram pogreškom.)

58
29 сент. odgovor je dao joechoj 29. rujna 2016-09-29 07:33 '16 u 7:33 2016-09-29 07:33

Kada postoje određeni izrazi u našem modulu ( M.py ), želimo izvršiti M.py kada se pokrene kao glavna (ne uvezena), te M.py (testne primjere, print naredbe) možemo smjestiti u ovaj blok.

Po defaultu (kada modul radi kao glavni, a ne uvezen), varijabla __name__ je postavljena na "__main__" , a kada se uvozi, varijabla __name__ dobiva drugu vrijednost, najvjerojatnije ime modula ( 'M' ). To je korisno kada se dijele različite varijante modula i odvajaju njihove specifične ulazne i izlazne upute, kao iu prisutnosti testnih slučajeva.

Ukratko , upotrijebite ovaj " if __name__ == "main" blok kako biste spriječili (određeni) kod if __name__ == "main" kada se modul uvozi.

44
03 апр. Odgovor daje Nabeel Ahmed 03. travnja. 2013-04-03 17:09 '13 u 17:09 2013-04-03 17:09

Pogledajmo odgovor na apstraktniji način:

Pretpostavimo da je ovaj kôd u x.py:

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

Blokovi A i B se pokreću kada pokrenemo x.py.

Ali samo blok A (a ne B) počinje kada pokrenemo drugi modul, na primjer "y.py", u koji se uvozi xy i kôd se pokreće od tamo (na primjer, kada se iz y.py poziva funkcija u "x". Py " ,

35
20 янв. odgovor dat Alisi 20. siječnja 2015-01-20 20:48 '15 u 20:48 2015-01-20 20:48

Jednostavno rečeno, __name__ je varijabla definirana za svaku skriptu koja određuje da li se skripta izvodi kao glavni modul ili radi kao uvezeni modul.

Dakle, ako imamo dva scenarija;

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

i također

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