Vraag Wat doet als __name__ == "__main__": doen?


Wat doet de if __name__ == "__main__": do?

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

4128
2018-01-07 04:11


oorsprong


antwoorden:


Wanneer de Python-interpreter een bronbestand leest, voert het alle daarin gevonden code uit.

Voordat u de code uitvoert, definieert deze een paar speciale variabelen. Als de Python-interpreter bijvoorbeeld die module (het bronbestand) als hoofdprogramma gebruikt, wordt de special ingesteld __name__ variabele om een ​​waarde te hebben "__main__". Als dit bestand uit een andere module wordt geïmporteerd, __name__ wordt ingesteld op de naam van de module.

In het geval van uw script, laten we aannemen dat het wordt uitgevoerd als de hoofdfunctie, bijvoorbeeld je zei zoiets

python threading_example.py

op de opdrachtregel. Na het instellen van de speciale variabelen, zal het de import verklaring en laad die modules. Het zal dan de def blokkeren, een functieobject maken en een variabele maken die wordt aangeroepen myfunction die naar het functieobject wijst. Het zal dan de if verklaring en zie dat __name__ doet hetzelfde "__main__", dus het zal het daar getoonde blok uitvoeren.

Een reden om dit te doen is dat je soms een module schrijft (a .py bestand) waar het direct kan worden uitgevoerd. Als alternatief kan het ook worden geïmporteerd en gebruikt in een andere module. Door de hoofdcontrole uit te voeren, kunt u die code alleen laten uitvoeren als u de module als een programma wilt uitvoeren en niet wilt laten uitvoeren wanneer iemand uw module wil importeren en uw functies zelf wilt bellen.

Zien deze pagina voor wat extra details.


4407
2018-01-07 04:26



Wanneer uw script wordt uitgevoerd door het door te geven als een opdracht aan de Python-interpreter,

python myscript.py

alle code op inspringniveau 0 wordt uitgevoerd. Functies en klassen die zijn gedefinieerd, zijn goed gedefinieerd, maar geen van hun code wordt uitgevoerd. In tegenstelling tot andere talen is er geen main() functie die automatisch wordt uitgevoerd - de main() functie is impliciet alle code op het hoogste niveau.

In dit geval is de code op het hoogste niveau een if blok. __name__ is een ingebouwde variabele die evalueert naar de naam van de huidige module. Als een module echter direct wordt uitgevoerd (zoals in myscript.py hierboven), dan __name__ in plaats daarvan is ingesteld op de tekenreeks "__main__". U kunt dus testen of uw script direct wordt uitgevoerd of door iets anders wordt geïmporteerd door te testen

if __name__ == "__main__":
    ...

Als uw script in een andere module wordt geïmporteerd, worden de verschillende functie- en klassendefinities ervan geïmporteerd en wordt de code op het hoogste niveau uitgevoerd, maar de code in het hoofdgedeelte van de module if clausule hierboven wordt niet uitgevoerd als aan de voorwaarde niet is voldaan. Als een eenvoudig voorbeeld, overweeg de volgende twee scripts:

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

Nu, als u de interpreter als aanroept

python one.py

De uitvoer zal zijn

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

Als je rent two.py in plaats daarvan:

python two.py

Jij krijgt

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

Dus, wanneer module one wordt geladen, zijn __name__ is gelijk aan "one" in plaats van "__main__".


1403
2018-01-07 04:28



De eenvoudigste verklaring voor de __name__ variabele (imho) is de volgende:

Maak de volgende bestanden.

# a.py
import b

en

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

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

Als u ze uitvoert, krijgt u deze uitvoer:

$ python a.py
Hello World from b!

Zoals je kunt zien, stelt Python in wanneer een module wordt geïmporteerd globals()['__name__'] in deze module naar de naam van de module.

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

Zoals je kunt zien, stelt Python in wanneer een bestand wordt uitgevoerd globals()['__name__'] in dit bestand naar "__main__".


560
2018-01-07 11:35



Wat doet de if __name__ == "__main__": do?

Om de basis te schetsen:

  • De globale variabele, __name__, in de module die het beginpunt van uw programma is, is '__main__'. Anders is dit de naam waarnaar u de module importeert.

  • Dus, code onder de if blok wordt alleen uitgevoerd als de module het beginpunt van uw programma is.

  • Hiermee kan de code in de module geïmporteerd worden door andere modules, zonder het onderstaande codeblok uit te voeren tijdens het importeren.


Waarom hebben we dit nodig?

Ontwikkelen en testen van uw code

Stel dat je een Python-script schrijft dat is ontworpen om als module te worden gebruikt:

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

U kon test de module door deze oproep van de functie onderaan toe te voegen:

do_important()

en het uitvoeren (op een opdrachtprompt) met zoiets als:

~$ python important.py

Het probleem

Als u de module echter naar een ander script wilt importeren:

import important

Bij importeren, de do_important functie zou worden aangeroepen, dus je zou waarschijnlijk je functieaanroep opmerken, do_important(), aan de onderkant.

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

En dan moet je onthouden of je je testfunctieoproep al dan niet hebt becommentarieerd. En deze extra complexiteit zou betekenen dat je het waarschijnlijk vergeet, waardoor je ontwikkelingsproces lastiger wordt.

Een betere manier

De __name__ variabele wijst naar de naamruimte waar de Python-tolk zich op dat moment bevindt.

In een geïmporteerde module is het de naam van die module.

Maar in de primaire module (of een interactieve Python-sessie, dat wil zeggen de Read, Eval, Print Loop of REPL van de interpreter), wordt alles uitgevoerd "__main__".

Dus als je het controleert voordat je het uitvoert:

if __name__ == "__main__":
    do_important()

Met het bovenstaande wordt uw code alleen uitgevoerd als u deze als primaire module gebruikt (of deze met opzet vanuit een ander script aanroept).

Een nog betere manier

Er is echter een Pythonische manier om dit te verbeteren.

Wat als we dit bedrijfsproces van buiten de module willen uitvoeren?

Als we de code zetten die we willen oefenen terwijl we ons ontwikkelen en testen in een functie als deze en dan onze controle uitvoeren '__main__' onmiddellijk na:

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

We hebben nu een laatste functie voor het einde van onze module die zal worden uitgevoerd als we de module als de primaire module uitvoeren.

Hiermee kunnen de module en de bijbehorende functies en klassen in andere scripts worden geïmporteerd zonder de main functie, en zal ook toestaan ​​dat de module (en de bijbehorende functies en klassen) worden aangeroepen wanneer vanuit een ander wordt uitgevoerd '__main__' module, i.e.

import important
important.main()

Dit idioom is ook te vinden in de documentatie van Python in een uitleg van de __main__ module. Die tekst zegt:

Deze module vertegenwoordigt de (overigens anonieme) scope waarin de   het hoofdprogramma van de tolk wordt uitgevoerd - opdrachten waaruit ofwel gelezen kan worden   standaardinvoer, van een scriptbestand of van een interactieve prompt. Het   is deze omgeving waarin de idiomatische "conditionele script" strofe   zorgt ervoor dat een script wordt uitgevoerd:

if __name__ == '__main__':
    main()

412
2017-11-23 04:38



if __name__ == "__main__"is het onderdeel dat wordt uitgevoerd wanneer het script wordt uitgevoerd vanaf (laten we zeggen) de opdrachtregel met een commando zoals python myscript.py.


92
2018-01-07 04:14



Wat doet if __name__ == "__main__": do?

__name__ is een globale variabele (in Python betekent globaal eigenlijk op de moduleniveau) die in alle naamruimten bestaat. Het is meestal de naam van de module (als een str type).

Als het enige speciale geval echter in welk Python-proces u ook wordt uitgevoerd, zoals in mycode.py:

python mycode.py

de anders anonieme globale naamruimte krijgt de waarde van '__main__' naar zijn __name__.

Dus inclusief de laatste regels

if __name__ == '__main__':
    main()
  • aan het einde van uw mycode.py-script,
  • wanneer het de primaire startmodule is die wordt uitgevoerd door een Python-proces,

zorgt ervoor dat uw script uniek gedefinieerd is main functie om uit te voeren.

Nog een voordeel van het gebruik van dit construct: u kunt uw code ook als een module in een ander script importeren en vervolgens de hoofdfunctie uitvoeren als en wanneer uw programma beslist:

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

57
2017-10-14 20:22



Er zijn hier veel verschillende takes over de werking van de code in kwestie, het "Hoe", maar voor mij klopte er niets van totdat ik het "Waarom" begreep. Dit zou met name nuttig moeten zijn voor nieuwe programmeurs.

Neem bestand "ab.py":

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

En een tweede bestand "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()

Wat doet deze code eigenlijk?

Wanneer je uitvoert xy.py, u import ab. De importinstructie voert de module onmiddellijk uit bij importeren, dus abDe bewerkingen worden uitgevoerd vóór de rest van xy'S. Eenmaal klaar met ab, het gaat verder met xy.

De interpreter houdt bij met welke scripts wordt uitgevoerd __name__. Wanneer je een script uitvoert - ongeacht wat je het hebt genoemd - roept de interpreter het "__main__", waardoor het het hoofd- of 'home'-script wordt waarnaar wordt teruggekeerd na het uitvoeren van een extern script.

Elk ander script dat hier vanaf wordt genoemd "__main__" script heeft de bestandsnaam als zijn __name__ (B.v. __name__ == "ab.py"). Vandaar de lijn if __name__ == "__main__": is de tolktest om te bepalen of het 'thuis'-script dat oorspronkelijk werd uitgevoerd, wordt geïnterpreteerd / ontleed of dat het tijdelijk in een ander (extern) script gloort. Dit geeft de programmeur de flexibiliteit om het script anders te laten werken als het direct wordt uitgevoerd of extern wordt aangeroepen.

Laten we door de bovenstaande code bladeren om te begrijpen wat er gebeurt, met eerst aandacht voor de niet-aangedane regels en de volgorde waarin ze in de scripts verschijnen. Onthoud die functie - of def - blokken doen niets zelfstandig totdat ze worden gebeld. Wat de tolk zou kunnen zeggen als hij tegen zichzelf mompelde:

  • Open xy.py als het 'thuis'-bestand; noem het "__main__" in de __name__ variabel.
  • Importeer en open bestand met de __name__ == "ab.py".
  • Oh, een functie. Ik zal het onthouden.
  • Ok, functie a(); Ik heb dat net geleerd. Afdrukken 'Een functie in ab-bestand'.
  • Einde van het bestand; terug naar "__main__"!
  • Oh, een functie. Ik zal het onthouden.
  • Nog een.
  • Functie x(); oké, afdrukken 'perifere taak: kan nuttig zijn in andere projecten'.
  • Wat is dit? Een if uitspraak. Welnu, aan de voorwaarde is voldaan (de variabele __name__is ingesteld op "__main__"), dus ik ga naar de main() functie en afdrukken 'hoofdfunctie: dit is waar de actie is'.

De onderste twee regels betekenen: "Als dit het is "__main__" of 'home' script, voer de functie uit genaamd main()"Dat is waarom je een a zult zien def main(): block up top, die de hoofdstroom van de functionaliteit van het script bevat.

Waarom dit implementeren?

Weet je nog wat ik eerder zei over importstatements? Wanneer u een module importeert, herkent deze deze niet alleen en wacht op verdere instructies - hij voert feitelijk alle uitvoerbare bewerkingen uit die in het script zijn opgenomen. Dus, het vlees van je script in de main() functioneert het in quarantaine en wordt het in een isolement geplaatst, zodat het niet onmiddellijk wordt uitgevoerd wanneer het wordt geïmporteerd door een ander script.

Nogmaals, er zullen uitzonderingen zijn, maar dat is de gangbare praktijk main() wordt meestal niet extern aangeroepen. U vraagt ​​zich misschien nog één ding af: als we niet bellen main(), waarom noemen we het script helemaal? Dit komt omdat veel mensen hun scripts structureren met zelfstandige functies die zijn gebouwd om onafhankelijk van de rest van de code in het bestand te worden uitgevoerd. Ze worden dan later ergens anders in het lichaam van het script geroepen. Dat brengt me hiertoe:

Maar de code werkt zonder

Ja dat klopt. Deze afzonderlijke functies kan worden aangeroepen vanuit een in-line script dat niet is opgenomen in een main() functie. Als je gewend bent (zoals ik ben, in mijn vroege programmeerstadia) aan het bouwen van in-line scripts die precies doen wat je nodig hebt, en je zult proberen het opnieuw uit te zoeken als je die operatie ooit nog nodig hebt. . nou, je bent niet gewend aan dit soort interne structuur van je code, omdat het ingewikkelder is om te bouwen en het is niet zo intuïtief om te lezen.

Maar dat is een script waarvan de functies waarschijnlijk niet extern worden genoemd, omdat als dit gebeurt, het meteen zou beginnen met het berekenen en toewijzen van variabelen. En als u een functie probeert te hergebruiken, is de kans groot dat uw nieuwe script dicht genoeg bij de oude staat en dat er conflicterende variabelen zijn.

Door onafhankelijke functies op te splitsen, krijgt u de mogelijkheid uw vorige werk opnieuw te gebruiken door ze naar een ander script te bellen. "Example.py" kan bijvoorbeeld "xy.py" importeren en bellen x(), gebruikmakend van de 'x'-functie van' xy.py '. (Misschien is het hoofdlettergebruik van het derde woord van een bepaalde tekenreeks, het maken van een NumPy-array uit een lijst met getallen en het kwadrateren ervan, of het ontzetten van een 3D-oppervlak.De mogelijkheden zijn onbeperkt.)

(Terzijde, deze vraag bevat een antwoord van @kindall dat me uiteindelijk heeft geholpen te begrijpen - het waarom, niet het hoe. Helaas is het gemarkeerd als een duplicaat van deze, waarvan ik denk dat het een vergissing is.)


47
2017-09-29 04:33



Wanneer er bepaalde uitspraken zijn in onze module (M.py) we willen worden uitgevoerd als het als hoofdbestand (niet geïmporteerd) wordt uitgevoerd, we kunnen deze verklaringen (testgevallen, afdrukinstructies) onder deze ifblok.

Zoals standaard (wanneer module als hoofdbediening wordt uitgevoerd, niet geïmporteerd), is de __name__ variabele is ingesteld op "__main__", en wanneer het zal worden geïmporteerd __name__ variabele krijgt een andere waarde, hoogstwaarschijnlijk de naam van de module ('M'). Dit is handig bij het samen uitvoeren van verschillende varianten van een module en het scheiden van hun specifieke invoer- en uitvoerverklaringen en ook als er testcases zijn.

In het kort, gebruik dit 'if __name__ == "main" 'blokkeren om te voorkomen dat (bepaalde) code wordt uitgevoerd wanneer de module wordt geïmporteerd.


39
2018-04-03 14:09



Laten we het antwoord op een meer abstracte manier bekijken:

Stel dat we deze code in x.py hebben:

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

Blokken A en B worden uitgevoerd wanneer we 'x.py' uitvoeren.

Maar blok A (en niet B) wordt alleen uitgevoerd als we een andere module gebruiken, "y.py" bijvoorbeeld, waarbij xy wordt geïmporteerd en de code vanaf daar wordt uitgevoerd (bijvoorbeeld wanneer een functie in "x.py" is gebeld van y.py).


32
2018-01-20 17:48



Wanneer u Python interactief uitvoert met de lokale __name__ variabele krijgt een waarde van __main__. Evenzo, wanneer u een Python-module vanaf de opdrachtregel uitvoert, in plaats van deze in een andere module te importeren, is het __name__ attribuut krijgt een waarde van __main__, in plaats van de echte naam van de module. Op deze manier kunnen modules naar hun eigen niveau kijken __name__ waarde om zelf te bepalen hoe ze worden gebruikt, als ondersteuning voor een ander programma of als de hoofdtoepassing die wordt uitgevoerd vanaf de opdrachtregel. Het volgende idioom is dus vrij gebruikelijk in Python-modules:

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