Wat doet de 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))
Wanneer de Python interpreter een bronbestand leest, doet hij twee dingen:
__name__
, en dan__name__
controles die we altijd zien in Python scripts.
Code VoorbeeldLaten we een iets ander codevoorbeeld gebruiken om te onderzoeken hoe imports en scripts werken. Stel dat het volgende in een bestand genaamd foo.py
staat.
# 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")
Wanneer de Python interpeter een bronbestand leest, definieert hij eerst een paar speciale variabelen. In dit geval gaat het om de __name__
variabele.
Wanneer uw module het hoofdprogramma is
Als je je module (het bronbestand) als het hoofdprogramma uitvoert, bijv.
python foo.py
zal de interpreter de hard-coded string "__main__"
toewijzen aan de __name__
variabele, d.w.z.
# It's as if the interpreter inserts this at the top
# of your module when run as the main program.
__name__ = "__main__"
Wanneer uw module wordt geïmporteerd door een andere Aan de andere kant, stel dat een andere module het hoofdprogramma is en het importeert jouw module. Dit betekent dat er een verklaring als deze is in het hoofdprogramma, of in een andere module die het hoofdprogramma importeert:
# Suppose this is in some other main program.
import foo
In dit geval kijkt de interpreter naar de bestandsnaam van uw module, foo.py
, haalt de .py
weg, en wijst die string toe aan uw module's __name__
variabele, d.w.z.
# It's as if the interpreter inserts this at the top
# of your module when it's imported from another module.
__name__ = "foo"
Nadat de speciale variabelen zijn ingesteld, voert de interpreter alle code in de module uit, één statement per keer. U wilt misschien een ander venster openen aan de zijkant met het codevoorbeeld, zodat u deze uitleg kunt volgen. Altijd
"before import"
af (zonder aanhalingstekens).math
module en wijst het toe aan een variabele genaamd math
. Dit is equivalent aan het vervangen van import math
door het volgende (merk op dat __import__
een low-level functie in Python is die een string neemt en de eigenlijke import in gang zet):# Zoek en laad een module met zijn stringnaam, "math",
# en wijs het dan toe aan een lokale variabele genaamd math.
math = __import__("math")
"before functionA"
af.def
blok uit, creëert een functie object en wijst dat functie object toe aan een variabele genaamd functionA
."before functionB"
af.def
-blok wordt uitgevoerd, waarbij een ander functieobject wordt aangemaakt en vervolgens wordt toegewezen aan een variabele met de naam functieB
."before __name__ guard"
af.
Alleen als je module het hoofdprogramma is__name__
inderdaad is ingesteld op "__main__"
en het roept de twee functies aan, waarbij de strings "Function A"
en "Function B 10.0"
worden afgedrukt.
Alleen wanneer uw module door een ander wordt geïmporteerd__name__
"foo"
zijn, en niet "__main__"
, en het'zal de body van de if
verklaring overslaan.
Altijd"na __name__ guard"
in beide situaties afdrukken.
Samenvatting
Samenvattend, hier'is wat'in de twee gevallen zou worden afgedrukt:
# 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
Je zou je natuurlijk kunnen afvragen waarom iemand dit zou willen. Wel, soms wil je een .py
bestand schrijven dat zowel gebruikt kan worden door andere programma's en/of modules als een module, en ook als het hoofdprogramma zelf kan worden uitgevoerd. Voorbeelden:
Uw module is een bibliotheek, maar u wilt een script modus hebben waar het een aantal unit tests of een demo uitvoert.
Uw module wordt alleen gebruikt als hoofdprogramma, maar het heeft een aantal unit tests, en het test framework werkt door het importeren van .py
bestanden zoals uw script en het uitvoeren van speciale test functies. Je wilt niet dat het probeert het script uit te voeren alleen omdat het de module importeert.
Vraag: Kan ik meerdere __name__
controlerende blokken hebben? Antwoord: het'is vreemd om dat te doen, maar de taal zal'je niet tegenhouden.
Stel dat het volgende in foo2.py
staat. Wat gebeurt er als je python foo2.py
zegt op de command-line? Waarom?
# 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")
__name__
check in foo3.py
verwijdert:# 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")
# Suppose this is in foo4.py
__name__ = "__main__"
def bar():
print("bar")
print("before __name__ guard")
if __name__ == "__main__":
bar()
print("after __name__ guard")
Wanneer uw script wordt uitgevoerd door het als een commando aan de Python interpreter door te geven,
python myscript.py
wordt alle code uitgevoerd die op inspringniveau 0 staat. Functies en klassen die gedefinieerd zijn, nou ja, gedefinieerd, maar niets 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 top-level code een if
blok. __name__
is een ingebouwde variabele die evalueert naar de naam van de huidige module. Echter, als een module direct wordt uitgevoerd (zoals in myscript.py
hierboven), dan wordt __name__
in plaats daarvan ingesteld op de string "__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 wordt geïmporteerd in een andere module, zullen de verschillende functie en klasse definities worden geïmporteerd en de top-level code zal worden uitgevoerd, maar de code in de then-body van de if
clausule hierboven zal niet worden uitgevoerd omdat niet aan de voorwaarde is voldaan. Als een basisvoorbeeld, beschouw 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 je de interpreter aanroept als
python one.py
De uitvoer zal zijn
top-level in one.py
one.py is being run directly
Als je in plaats daarvan two.py
uitvoert:
python two.py
Je 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, als module one
wordt geladen, is zijn __name__
gelijk aan "one"
in plaats van "__main__"
.
if __name__ == "__main__"
is het deel dat wordt uitgevoerd als het script wordt uitgevoerd vanaf (zeg) de commandoregel met een commando als python myscript.py
.