Gegeven de volgende code, 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))
Antwoord 1, autoriteit 100%
Kort antwoord
Het is standaardcode die gebruikers beschermt tegen het per ongeluk aanroepen van het script wanneer ze dat niet van plan waren. Hier zijn enkele veelvoorkomende problemen wanneer de bewaker wordt weggelaten uit een script:
-
Als u het guardless-script in een ander script importeert (bijv.
import my_script_without_a_name_eq_main_guard
), dan zal het tweede script het eerste activeren om op het moment van importeren en met behulp van de opdrachtregelargumenten van het tweede script. Dit is bijna altijd een vergissing. -
Als je een aangepaste klasse in het guardless-script hebt en deze opslaat in een augurkbestand, zal het uitpakken ervan in een ander script een import van het guardless-script activeren, met dezelfde problemen als beschreven in het vorige bullet.
Lang antwoord
Om beter te begrijpen waarom en hoe dit van belang is, moeten we een stap terug doen om te begrijpen hoe Python scripts initialiseert en hoe dit interageert met het module-importmechanisme.
Telkens wanneer de Python-interpreter een bronbestand leest, doet hij twee dingen:
-
het stelt een paar speciale variabelen in, zoals
__name__
, en dan -
het voert alle code uit die in het bestand wordt gevonden.
Laten we eens kijken hoe dit werkt en hoe dit verband houdt met uw vraag over de __name__
-controles die we altijd zien in Python-scripts.
Codevoorbeeld
Laten we een iets ander codevoorbeeld gebruiken om te onderzoeken hoe import en scripts werken. Stel dat het volgende in een bestand staat met de naam 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")
Speciale variabelen
Als de Python-interpreter een bronbestand leest, definieert het eerst een paar speciale variabelen. In dit geval geven we om de variabele __name__
.
Als uw module het hoofdprogramma is
Als u uw module (het bronbestand) als hoofdprogramma gebruikt, bijv.
python foo.py
de interpreter wijst de hardgecodeerde string "__main__"
toe aan de variabele __name__
, 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 door een ander wordt geïmporteerd
Aan de andere kant, stel dat een andere module het hoofdprogramma is en uw module importeert. Dit betekent dat er een statement als dit in het hoofdprogramma staat, of in een andere module die het hoofdprogramma importeert:
# Suppose this is in some other main program.
import foo
De interpreter zoekt naar uw foo.py
-bestand (samen met zoeken naar een paar andere varianten), en voordat die module wordt uitgevoerd, zal het de naam "foo"
van het importstatement naar de __name__
variabele, dwz
# It's as if the interpreter inserts this at the top
# of your module when it's imported from another module.
__name__ = "foo"
De modulecode uitvoeren
Nadat de speciale variabelen zijn ingesteld, voert de interpreter alle code in de module uit, één instructie tegelijk. Misschien wilt u een ander venster openen aan de zijkant met het codevoorbeeld, zodat u deze uitleg kunt volgen.
Altijd
-
Het drukt de tekenreeks
"before import"
af (zonder aanhalingstekens). -
Het laadt de module
math
en wijst deze toe aan een variabele met de naammath
. Dit komt overeen met het vervangen vanimport math
door het volgende (merk op dat__import__
een functie op laag niveau is in Python die een string nodig heeft en de daadwerkelijke import activeert):
# Find and load a module given its string name, "math",
# then assign it to a local variable called math.
math = __import__("math")
-
Het drukt de tekenreeks
"before functionA"
af. -
Het voert het blok
def
uit, maakt een functieobject en wijst dat functieobject vervolgens toe aan een variabele met de naamfunctionA
. -
Het drukt de tekenreeks
"before functionB"
af. -
Het voert het tweede
def
-blok uit, creëert een ander functieobject en wijst het vervolgens toe aan een variabele met de naamfunctionB
. -
Het drukt de string
"before __name__ guard"
af.
Alleen als uw module het hoofdprogramma is
- Als uw module het hoofdprogramma is, zal het zien dat
__name__
inderdaad is ingesteld op"__main__"
en het roept de twee functies aan en drukt de strings"Function A"
en"Function B 10.0"
.
Alleen wanneer uw module door een ander is geïmporteerd
- (in plaats daarvan) Als uw module niet het hoofdprogramma is maar door een ander is geïmporteerd, dan is
__name__
"foo"
, niet"__main__"
, en het zal de hoofdtekst van deif
-instructie overslaan.
Altijd
- In beide situaties wordt de string
"after __name__ guard"
afgedrukt.
Samenvatting
Samengevat, dit is wat er 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
Waarom werkt het op deze manier?
Je kunt je natuurlijk afvragen waarom iemand dit zou willen. Welnu, soms wil je een .py
-bestand schrijven dat zowel door andere programma’s en/of modules als module kan worden gebruikt, en dat ook als hoofdprogramma zelf kan worden uitgevoerd. Voorbeelden:
-
Uw module is een bibliotheek, maar u wilt een scriptmodus hebben waarin enkele unittests of een demo worden uitgevoerd.
-
Je module wordt alleen als hoofdprogramma gebruikt, maar er zijn enkele unit-tests, en het testframework werkt door
.py
-bestanden zoals je script te importeren en speciale testfuncties uit te voeren. Je wilt niet dat het het script probeert uit te voeren alleen omdat het de module importeert. -
Uw module wordt meestal gebruikt als hoofdprogramma, maar biedt ook een programmeervriendelijke API voor gevorderde gebruikers.
Naast deze voorbeelden is het elegant dat het uitvoeren van een script in Python slechts het instellen van een paar magische variabelen is en het importeren van het script. “Hardlopen” het script is een neveneffect van het importeren van de scriptmodule.
Voedsel tot nadenken
-
Vraag: kan ik meerdere
__name__
controleblokken hebben? Antwoord: het is vreemd om dat te doen, maar de taal houdt je niet tegen. -
Stel dat het volgende in
foo2.py
staat. Wat gebeurt er als jepython foo2.py
zegt op de opdrachtregel? Waarom?
# Suppose this is foo2.py.
import os, sys; sys.path.insert(0, os.path.dirname(__file__)) # needed for some interpreters
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")
- Bedenk nu wat er zal gebeuren als je de
__name__
check infoo3.py
verwijdert:
# Suppose this is foo3.py.
import os, sys; sys.path.insert(0, os.path.dirname(__file__)) # needed for some interpreters
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")
- Wat doet dit als het als script wordt gebruikt? Wanneer geïmporteerd als module?
# Suppose this is in foo4.py
__name__ = "__main__"
def bar():
print("bar")
print("before __name__ guard")
if __name__ == "__main__":
bar()
print("after __name__ guard")
Antwoord 2, autoriteit 26%
Als je script wordt uitgevoerd door het als commando door te geven aan de Python-interpreter,
python myscript.py
alle code op inspringniveau 0 wordt uitgevoerd. Functies en klassen die zijn gedefinieerd, zijn, nou ja, gedefinieerd, maar geen van hun code wordt uitgevoerd. In tegenstelling tot andere talen is er geen functie main()
die automatisch wordt uitgevoerd – de functie main()
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 rechtstreeks wordt uitgevoerd (zoals in myscript.py
hierboven), dan wordt __name__
in plaats daarvan ingesteld op de tekenreeks "__main__"
. U kunt dus testen of uw script rechtstreeks 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 klassedefinities geïmporteerd en wordt de code op het hoogste niveau uitgevoerd, maar de code in de then-body van de if
bovenstaande clausule wordt niet uitgevoerd omdat niet aan de voorwaarde is voldaan. Beschouw als basisvoorbeeld 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")
Als u nu de interpreter aanroept als
python one.py
De uitvoer zal zijn
top-level in one.py
one.py is being run directly
Als u 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, wanneer module one
wordt geladen, is de __name__
gelijk aan "one"
in plaats van "__main__"
.
Antwoord 3, autoriteit 10%
De eenvoudigste verklaring voor de variabele __name__
(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, wanneer een module wordt geïmporteerd, globals()['__name__']
in deze module in op de naam van de module. Ook wordt bij het importeren alle code in de module uitgevoerd. Aangezien de if
-instructie evalueert tot False
wordt dit deel niet uitgevoerd.
$ python b.py
Hello World from __main__!
Hello World again from __main__!
Zoals je kunt zien, stelt Python, wanneer een bestand wordt uitgevoerd, globals()['__name__']
in dit bestand in op "__main__"
. Deze keer evalueert de if
-instructie tot True
en wordt uitgevoerd.
Antwoord 4, autoriteit 7%
Wat doet de
if __name__ == "__main__":
?
Om de basis te schetsen:
-
De globale variabele,
__name__
, in de module die het toegangspunt is tot uw programma, is'__main__'
. Anders is het de naam waarmee u de module importeert. -
Dus de code onder het
if
-blok wordt alleen uitgevoerd als de module het toegangspunt tot je programma is. -
Hiermee kan de code in de module worden geïmporteerd door andere modules, zonder het codeblok eronder uit te voeren bij het importeren.
Waarom hebben we dit nodig?
Uw code ontwikkelen en testen
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 zou de module kunnen testen door deze aanroep van de functie onderaan toe te voegen:
do_important()
en het uitvoeren (op een opdrachtprompt) met iets als:
~$ python important.py
Het probleem
Als u de module echter naar een ander script wilt importeren:
import important
Bij het importeren zou de functie do_important
worden aangeroepen, dus je zou waarschijnlijk je functieaanroep, do_important()
, onderaan als commentaar plaatsen.
# do_important() # I must remember to uncomment to execute this!
En dan moet je onthouden of je al dan niet commentaar hebt gegeven op je testfunctie-aanroep. En deze extra complexiteit zou betekenen dat u het waarschijnlijk vergeet, waardoor uw ontwikkelingsproces lastiger wordt.
Een betere manier
De variabele __name__
verwijst naar de naamruimte waar de Python-interpreter zich op dat moment bevindt.
Binnen een geïmporteerde module is dit de naam van die module.
Maar binnen de primaire module (of een interactieve Python-sessie, d.w.z. de Read, Eval, Print Loop of REPL van de interpreter) voer je alles uit vanuit zijn "__main__"
.
Dus als u controleert voordat u het uitvoert:
if __name__ == "__main__":
do_important()
Met het bovenstaande wordt uw code alleen uitgevoerd als u deze als de primaire module uitvoert (of opzettelijk 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 laten lopen?
Als we de code die we willen gebruiken tijdens het ontwikkelen en testen in een functie als deze plaatsen en dan onze controle uitvoeren op '__main__'
onmiddellijk daarna:
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 wordt uitgevoerd als we de module als de primaire module uitvoeren.
Hiermee kunnen de module en zijn functies en klassen worden geïmporteerd in andere scripts zonder de functie main
uit te voeren, en kan de module (en zijn functies en klassen) ook worden aangeroepen tijdens het uitvoeren van een andere '__main__'
module, bijv.
import important
important.main()
Dit idioom is ook te vinden in de Python-documentatie in een uitleg van de __main__
module. In die tekst staat:
Deze module vertegenwoordigt het (anders anonieme) bereik waarin de
het hoofdprogramma van de interpreter voert opdrachten uit die gelezen worden van
standaardinvoer, vanuit een scriptbestand of vanuit een interactieve prompt. Het
is deze omgeving waarin de idiomatische strofe ‘voorwaardelijk schrift’
zorgt ervoor dat een script wordt uitgevoerd:if __name__ == '__main__': main()
Antwoord 5, autoriteit 2%
if __name__ == "__main__"
is het deel dat wordt uitgevoerd wanneer het script wordt uitgevoerd vanaf (bijvoorbeeld) de opdrachtregel met een opdracht als python myscript.py
.
Antwoord 6
Wat doet
if __name__ == "__main__":
?
__name__
is een globale variabele (in Python betekent global eigenlijk op het 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 je ook draait, zoals in mycode.py:
python mycode.py
de anders anonieme globale naamruimte krijgt de waarde '__main__'
toegewezen aan zijn __name__
.
Dus inclusief de laatste regels
if __name__ == '__main__':
main()
- aan het einde van uw mycode.py-script,
- wanneer het de primaire ingangsmodule is die wordt uitgevoerd door een Python-proces,
zal ervoor zorgen dat de uniek gedefinieerde main
-functie van uw script wordt uitgevoerd.
Een ander voordeel van het gebruik van deze constructie: u kunt uw code ook als module in een ander script importeren en vervolgens de hoofdfunctie uitvoeren als en wanneer uw programma dat beslist:
import mycode
# ... any amount of other code
mycode.main()
Antwoord 7
Er zijn hier veel verschillende opvattingen over de mechanica van de code in kwestie, het “Hoe”, maar voor mij was niets logisch totdat ik het “Waarom” begreep. Dit zou vooral handig 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 u xy.py
uitvoert, import ab
. Het importstatement voert de module direct bij het importeren uit, dus de bewerkingen van ab
worden uitgevoerd vóór de rest van de xy
‘s. Eenmaal klaar met ab
, gaat het verder met xy
.
De interpreter houdt bij welke scripts draaien met __name__
. Wanneer je een script uitvoert – ongeacht hoe je het genoemd hebt – noemt de interpreter het "__main__"
, waardoor het het master- of ‘home’-script wordt waarnaar wordt teruggekeerd na het uitvoeren van een extern script.
Elk ander script dat wordt aangeroepen vanuit dit "__main__"
-script krijgt zijn bestandsnaam toegewezen als zijn __name__
(bijv. __name__ == "ab.py"
). Daarom is de regel if __name__ == "__main__":
de test van de interpreter om te bepalen of het het ‘home’-script interpreteert/parseert dat in eerste instantie werd uitgevoerd, of dat het tijdelijk naar een ander (extern) gluurt script. Dit geeft de programmeur de flexibiliteit om het script zich anders te laten gedragen als het direct wordt uitgevoerd of extern wordt aangeroepen.
Laten we de bovenstaande code eens doornemen om te begrijpen wat er gebeurt, waarbij we ons eerst concentreren op de niet-ingesprongen regels en de volgorde waarin ze in de scripts verschijnen. Onthoud dat functie- of def
-blokken niets uit zichzelf doen totdat ze worden aangeroepen. Wat de tolk zou zeggen als hij in zichzelf mompelde:
- Open xy.py als het ‘home’-bestand; noem het
"__main__"
in de variabele__name__
. - Importeer en open bestand met de
__name__ == "ab.py"
. - O, een functie. Dat zal ik onthouden.
- Ok, functie
a()
; Dat heb ik net geleerd. Afdrukken van ‘Een functie in ab-bestand‘. - Einde van bestand; terug naar
"__main__"
! - O, een functie. Dat zal ik onthouden.
- Nog een.
- Functie
x()
; ok, afdrukken van ‘randtaak: kan nuttig zijn in andere projecten‘. - Wat is dit? Een
if
-statement. Welnu, aan de voorwaarde is voldaan (de variabele__name__
is ingesteld op"__main__"
), dus ik voer demain()
in functie en print ‘hoofdfunctie: dit is waar de actie is‘.
De onderste twee regels betekenen: “Als dit het "__main__"
of ‘home’ script is, voer dan de functie uit met de naam main()
“. Daarom zie je een def main():
-blok bovenaan, dat 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 – het voert eigenlijk alle uitvoerbare bewerkingen uit die in het script zijn opgenomen. Dus als je het vlees van je script in de functie main()
plaatst, wordt het effectief in quarantaine geplaatst, waardoor het geïsoleerd wordt zodat het niet onmiddellijk wordt uitgevoerd wanneer het door een ander script wordt geïmporteerd.
Nogmaals, er zullen uitzonderingen zijn, maar het is gebruikelijk dat main()
meestal niet extern wordt aangeroepen. Dus je vraagt je misschien nog iets af: als we main()
niet aanroepen, waarom roepen we dan het script aan? Dat 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 de hoofdtekst van het script genoemd. Dat brengt me bij dit:
Maar de code werkt ook zonder
Ja, dat klopt. Deze afzonderlijke functies kunnen worden aangeroepen vanuit een in-line script dat niet is opgenomen in een functie main()
. Als je gewend bent (zoals ik, in mijn vroege leerstadia van programmeren) om in-line scripts te bouwen die precies doen wat je nodig hebt, en je zult het opnieuw proberen uit te zoeken als je die bewerking ooit weer nodig hebt. Nou, je bent niet gewend aan dit soort interne structuur van je code, omdat het ingewikkelder is om te bouwen en niet zo intuïtief om te lezen.
Maar dat is een script waarvan de functies waarschijnlijk niet extern kunnen worden aangeroepen, want als het dat wel zou doen, zou het onmiddellijk beginnen met het berekenen en toewijzen van variabelen. En de kans is groot dat als je een functie probeert te hergebruiken, je nieuwe script nauw genoeg verwant is aan het oude, dat er conflicterende variabelen zullen zijn.
Door onafhankelijke functies op te splitsen, krijgt u de mogelijkheid om uw eerdere werk opnieuw te gebruiken door ze in een ander script aan te roepen. “example.py” kan bijvoorbeeld “xy.py” importeren en x()
aanroepen, gebruikmakend van de ‘x’-functie van “xy.py”. (Misschien is het een hoofdletter van het derde woord van een gegeven tekstreeks, een NumPy-array maken van een lijst met getallen en deze kwadrateren, of een 3D-oppervlak ontwijken. De mogelijkheden zijn onbeperkt.)
(Terzijde: deze vraag bevat een antwoord van @kindall dat uiteindelijk heeft me geholpen te begrijpen – het waarom, niet het hoe. Helaas is het gemarkeerd als een duplicaat van deze, wat volgens mij een vergissing is.)
Antwoord 8
Als er bepaalde statements in onze module (M.py
) zijn die we willen uitvoeren wanneer deze als main wordt uitgevoerd (niet geïmporteerd), kunnen we die statements (testcases) plaatsen , print statements) onder dit if
blok.
Standaard (wanneer module draait als main, niet geïmporteerd) is de __name__
variabele ingesteld op "__main__"
, en wanneer deze wordt geïmporteerd de __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 & output-statements en ook of er testgevallen zijn.
Kortom, gebruik dit ‘if __name__ == "main"
‘ blok om te voorkomen dat (bepaalde) code wordt uitgevoerd wanneer de module wordt geïmporteerd.
Antwoord 9
Simpel gezegd, __name__
is een variabele die voor elk script is gedefinieerd en die bepaalt of het script wordt uitgevoerd als de hoofdmodule of als een geïmporteerde module.
Dus als we twee scripts hebben;
#script1.py
print "Script 1's name: {}".format(__name__)
en
#script2.py
import script1
print "Script 2's name: {}".format(__name__)
De uitvoer van het uitvoeren van script1 is
Script 1's name: __main__
En de uitvoer van het uitvoeren van script2 is:
Script1's name is script1
Script 2's name: __main__
Zoals je kunt zien, vertelt __name__
ons welke code de ‘hoofd’-module is.
Dit is geweldig, omdat je gewoon code kunt schrijven en je geen zorgen hoeft te maken over structurele problemen zoals in C/C++, waar, als een bestand geen ‘hoofd’-functie implementeert, het niet als een uitvoerbaar bestand kan worden gecompileerd en als dat wel het geval is, het kan dan niet als bibliotheek worden gebruikt.
Stel dat je een Python-script schrijft dat iets geweldigs doet en je implementeert een massa functies die nuttig zijn voor andere doeleinden. Als ik ze wil gebruiken, kan ik gewoon je script importeren en gebruiken zonder je programma uit te voeren (aangezien je code alleen wordt uitgevoerd binnen de context if __name__ == "__main__":
). Terwijl je in C/C++ die stukjes zou moeten verdelen in een aparte module die dan het bestand bevat. Stel je de situatie hieronder voor;
De pijlen zijn importlinks. Voor drie modules die elk de code van de vorige modules proberen op te nemen, zijn er zes bestanden (negen, de implementatiebestanden meegerekend) en vijf links. Dit maakt het moeilijk om andere code in een C-project op te nemen, tenzij deze specifiek als bibliotheek is gecompileerd. Stel je het nu voor voor Python:
Je schrijft een module, en als iemand je code wil gebruiken, importeren ze die gewoon en de variabele __name__
kan helpen om het uitvoerbare gedeelte van het programma te scheiden van het bibliotheekgedeelte.
Antwoord 10
Laten we het antwoord op een meer abstracte manier bekijken:
Stel dat we deze code hebben in x.py
:
...
<Block A>
if __name__ == '__main__':
<Block B>
...
Blokken A en B worden uitgevoerd wanneer we x.py
gebruiken.
Maar blok A (en niet B) wordt uitgevoerd wanneer we een andere module gebruiken, bijvoorbeeld y.py
, waarin x.py
wordt geïmporteerd en de code wordt vanaf daar uitgevoerd (zoals wanneer een functie in x.py
wordt aangeroepen vanuit y.py
).
Antwoord 11
Ik heb zoveel gelezen tijdens de antwoorden op deze pagina. Ik zou zeggen, als je het weet, zul je die antwoorden zeker begrijpen, anders ben je nog steeds in de war.
Om kort te zijn, je moet een aantal punten weten:
-
import a
actie voert eigenlijk alles uit wat kan worden uitgevoerd ina.py
, wat betekent dat elke regel ina.py
-
Vanwege punt 1 wil je misschien niet dat alles in
a.py
wordt uitgevoerd bij het importeren -
Om het probleem in punt 2 op te lossen, kunt u met python een conditiecontrole uitvoeren
-
__name__
is een impliciete variabele in alle.py
-modules:
- wanneer
a.py
wordtimport
ed, wordt de waarde van__name__
van de modulea.py
ingesteld naar de bestandsnaam "a
" - wanneer
a.py
rechtstreeks wordt uitgevoerd met "python a.py
", wordt de waarde van__name__
ingesteld op een tekenreeks__main__
- Weet je op basis van het mechanisme hoe python de variabele
__name__
voor elke module instelt, hoe je punt 3 kunt bereiken? Het antwoord is vrij eenvoudig, toch? Zet een if-voorwaarde:if __name__ == "__main__": // do A
- dan zal
python a.py
het onderdeel// do A
- en
import a
slaan het deel// do A
uitvoeren
over
- Je kunt zelfs if
__name__ == "a"
plaatsen, afhankelijk van je functionele behoefte, maar doe dat zelden
Het belangrijkste waar python speciaal in is, is punt 4! De rest is gewoon basislogica.
Antwoord 12
Als je Python interactief uitvoert, krijgt de lokale variabele __name__
de waarde __main__
toegewezen. Evenzo, wanneer u een Python-module vanaf de opdrachtregel uitvoert, in plaats van deze in een andere module te importeren, wordt aan het kenmerk __name__
de waarde __main__
toegewezen in plaats van de werkelijke naam van de module. Op deze manier kunnen modules naar hun eigen __name__
waarde kijken om voor zichzelf te bepalen hoe ze worden gebruikt, als ondersteuning voor een ander programma of als de hoofdtoepassing die vanaf de opdrachtregel wordt uitgevoerd. 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.
Antwoord 13
Overweeg:
if __name__ == "__main__":
main()
Het controleert of het kenmerk __name__
van het Python-script "__main__"
is. Met andere woorden, als het programma zelf wordt uitgevoerd, is het attribuut __main__
, dus het programma wordt uitgevoerd (in dit geval de functie main()
).
Als uw Python-script echter door een module wordt gebruikt, wordt elke code buiten de if
-instructie uitgevoerd, dus if \__name__ == "\__main__"
wordt alleen gebruikt om te controleren of het programma als module wordt gebruikt of niet, en beslist daarom of de code moet worden uitgevoerd.
Antwoord 14
De code onder if __name__ == '__main__':
wordt alleen uitgevoerd als de module wordt aangeroepen als een script.
Beschouw als voorbeeld de volgende module my_test_module.py
:
# my_test_module.py
print('This is going to be printed out, no matter what')
if __name__ == '__main__':
print('This is going to be printed out, only if user invokes the module as a script')
1e mogelijkheid: importeer my_test_module.py
in een andere module
# main.py
import my_test_module
if __name__ == '__main__':
print('Hello from main.py')
Als je nu main.py
aanroept:
python main.py
>> 'This is going to be printed out, no matter what'
>> 'Hello from main.py'
Merk op dat alleen het print()
-statement op het hoogste niveau in my_test_module
wordt uitgevoerd.
2e mogelijkheid: roep my_test_module.py
op als een script
Als u nu my_test_module.py
uitvoert als een Python-script, worden beide print()
-instructies uitgevoerd:
python my_test_module.py
>>> 'This is going to be printed out, no matter what'
>>> 'This is going to be printed out, only if user invokes the module as a script'
Voor een uitgebreidere uitleg kun je lezen Wat doet if __name__ == '__main__'
doen in Python.
Antwoord 15
Alvorens iets uit te leggen over if __name__ == '__main__'
is het belangrijk om te begrijpen wat __name__
is en wat het doet.
Wat is
__name__
?
__name__
is een DunderAlias – kan worden gezien als een globale variabele (toegankelijk vanuit modules) en werkt op dezelfde manier als global
.
Het is een string (algemeen zoals hierboven vermeld) zoals aangegeven door type(__name__)
(die <class 'str'>
oplevert), en is een ingebouwde standaard voor zowel Python 3 als Python 2-versies.
Waar:
Het kan niet alleen in scripts worden gebruikt, maar is ook te vinden in zowel de interpreter als modules/pakketten.
Tolk:
>>> print(__name__)
__main__
>>>
Script:
test_file.py:
print(__name__)
Resulterend in __main__
Module of pakket:
een bestand.py:
def somefunction():
print(__name__)
test_file.py:
import somefile
somefile.somefunction()
Resulterend in somefile
Merk op dat bij gebruik in een pakket of module, __name__
de naam van het bestand aanneemt. Het pad van het eigenlijke module- of pakketpad wordt niet gegeven, maar heeft zijn eigen DunderAlias __file__
, die dit mogelijk maakt.
Je zou moeten zien dat, waar __name__
, waar het het hoofdbestand (of programma) is, altijd __main__
wordt geretourneerd, en als het is een module/pakket, of iets dat op een ander Python-script draait, retourneert de naam van het bestand waar het vandaan komt.
Oefen:
Een variabele zijn betekent dat de waarde ervan kan worden overschreven (“kan” betekent niet “zou moeten”), het overschrijven van de waarde van __name__
zal resulteren in een gebrek aan leesbaarheid. Dus doe het niet, om welke reden dan ook. Als je een variabele nodig hebt, definieer dan een nieuwe variabele.
Er wordt altijd aangenomen dat de waarde van __name__
__main__
is of de naam van het bestand. Nogmaals, het wijzigen van deze standaardwaarde zal meer verwarring veroorzaken dat het goed zal doen, wat later problemen veroorzaakt.
voorbeeld:
>>> __name__ = 'Horrify' # Change default from __main__
>>> if __name__ == 'Horrify': print(__name__)
...
>>> else: print('Not Horrify')
...
Horrify
>>>
Het wordt in het algemeen als een goede gewoonte beschouwd om de if __name__ == '__main__'
in scripts op te nemen.
Nu antwoorden
if __name__ == '__main__'
:
Nu weten we het gedrag van __name__
dingen worden duidelijker:
Een if
is een flow control-instructie die het codeblok bevat, wordt uitgevoerd als de opgegeven waarde waar is. We hebben gezien dat __name__
ofwel:
__main__
of de bestandsnaam waaruit het is geïmporteerd.
Dit betekent dat als __name__
gelijk is aan __main__
, het bestand het hoofdbestand moet zijn en daadwerkelijk moet worden uitgevoerd (of het is de interpreter), niet een module of pakket geïmporteerd in het script.
Als __name__
inderdaad de waarde van __main__
aanneemt, wordt alles wat in dat codeblok staat uitgevoerd.
Dit vertelt ons dat als het bestand dat wordt uitgevoerd het hoofdbestand is (of u rechtstreeks vanuit de interpreter uitvoert), die voorwaarde moet worden uitgevoerd. Als het een pakket is, zou het dat niet moeten zijn, en de waarde zal niet __main__
zijn.
Modules:
__name__
kan ook in modules worden gebruikt om de naam van een module te definiëren
Varianten:
Het is ook mogelijk om andere, minder gebruikelijke maar nuttige dingen te doen met __name__
, sommige zal ik hier laten zien:
Alleen uitvoeren als het bestand een module of pakket is:
if __name__ != '__main__':
# Do some useful things
Een voorwaarde uitvoeren als het bestand het hoofdbestand is en een andere als dit niet het geval is:
if __name__ == '__main__':
# Execute something
else:
# Do some useful things
Je kunt het ook gebruiken om uitvoerbare helpfuncties/hulpprogramma’s op pakketten en modules te bieden zonder het uitgebreide gebruik van bibliotheken.
Het staat ook toe dat modules vanaf de opdrachtregel als hoofdscripts worden uitgevoerd, wat ook erg handig kan zijn.
Antwoord 16
Ik denk dat het het beste is om het antwoord uitgebreid en in eenvoudige bewoordingen te bespreken:
__name__
: Elke module in Python heeft een speciaal attribuut genaamd __name__
.
Het is een ingebouwde variabele die de naam van de module retourneert.
__main__
: Net als andere programmeertalen heeft Python ook een invoerpunt voor de uitvoering, d.w.z. main. '__main__'
is de naam van het bereik waarin de code op het hoogste niveau wordt uitgevoerd. In principe heb je twee manieren om een Python-module te gebruiken: voer het rechtstreeks uit als een script of importeer het. Wanneer een module als een script wordt uitgevoerd, wordt de __name__
ingesteld op __main__
.
De waarde van het __name__
attribuut wordt dus ingesteld op __main__
wanneer de module als het hoofdprogramma wordt uitgevoerd. Anders wordt de waarde van __name__
ingesteld om de naam van de module te bevatten.
Antwoord 17
Het is speciaal voor wanneer een Python-bestand wordt aangeroepen vanaf de opdrachtregel. Dit wordt meestal gebruikt om een "main()" functie of voer andere geschikte opstartcode uit, zoals bijvoorbeeld het afhandelen van commandoregelargumenten.
Het kan op verschillende manieren worden geschreven. Een andere is:
def some_function_for_instance_main():
dosomething()
__name__ == '__main__' and some_function_for_instance_main()
Ik zeg niet dat je dit in productiecode moet gebruiken, maar het dient om te illustreren dat er niets “magisch” is. over if __name__ == '__main__'
.
Het is gewoon een conventie voor het aanroepen van een hoofdfunctie in Python-bestanden.
Antwoord 18
Er zijn een aantal variabelen die het systeem (Python-interpreter) biedt voor bronbestanden (modules). U kunt hun waarden op elk gewenst moment ophalen, dus laten we ons concentreren op de __name__ variabele/attribuut:
Wanneer Python een broncodebestand laadt, voert het alle code uit die erin wordt gevonden. (Merk op dat het niet alle methoden en functies aanroept die in het bestand zijn gedefinieerd, maar het definieert ze wel.)
Voordat de interpreter het broncodebestand uitvoert, definieert het echter een paar speciale variabelen voor dat bestand; __name__ is een van die speciale variabelen die Python automatisch definieert voor elk broncodebestand.
Als Python dit broncodebestand laadt als het hoofdprogramma (dwz het bestand dat u uitvoert), dan stelt het de speciale __name__ variabele voor dit bestand in op een waarde “__main__” .
Als dit wordt geïmporteerd uit een andere module, wordt __name__ ingesteld op de naam van die module.
Dus, in jouw voorbeeld gedeeltelijk:
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))
betekent dat het codeblok:
lock = thread.allocate_lock()
thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))
wordt alleen uitgevoerd als u de module rechtstreeks uitvoert; het codeblok wordt niet uitgevoerd als een andere module het aanroept/importeert omdat de waarde van __name__ in dat specifieke geval niet gelijk zal zijn aan “main“.
Hopelijk helpt dit.
Antwoord 19
if __name__ == "__main__":
is in feite de scriptomgeving op het hoogste niveau, en het specificeert de interpreter die (‘Ik heb de hoogste prioriteit om als eerste te worden uitgevoerd’).
'__main__'
is de naam van het bereik waarin de code op het hoogste niveau wordt uitgevoerd. De __name__
van een module is gelijk aan '__main__'
wanneer deze wordt gelezen vanuit standaardinvoer, een script of vanaf een interactieve prompt.
if __name__ == "__main__":
# Execute only if run as a script
main()
Antwoord 20
Overweeg:
print __name__
De uitvoer voor het bovenstaande is __main__
.
if __name__ == "__main__":
print "direct method"
De bovenstaande verklaring is waar en drukt “directe methode” af. Stel dat als ze deze klasse in een andere klasse hebben geïmporteerd, er geen “directe methode” wordt afgedrukt, omdat tijdens het importeren __name__ equal to "first model name"
.
Antwoord 21
Je kunt het bestand zowel bruikbaar maken als een script als een importeerbare module.
fibo.py (een module met de naam 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]))
Referentie: https://docs.python.org/3.5/tutorial/modules. html
Antwoord 22
De reden voor
if __name__ == "__main__":
main()
is voornamelijk om de importvergrendeling problemen die zouden ontstaan als code rechtstreeks geïmporteerd is. U wilt dat main()
wordt uitgevoerd als uw bestand rechtstreeks is aangeroepen (dat is het geval __name__ == "__main__"
), maar als uw code is geïmporteerd, moet de importeur voer uw code in vanuit de echte hoofdmodule om problemen met importvergrendeling te voorkomen.
Een neveneffect is dat u zich automatisch aanmeldt bij een methodologie die meerdere toegangspunten ondersteunt. U kunt uw programma uitvoeren met main()
als startpunt, maar dat hoeft niet. Terwijl setup.py
main()
verwacht, gebruiken andere tools alternatieve toegangspunten. Om uw bestand bijvoorbeeld uit te voeren als een gunicorn
-proces, definieert u een app()
-functie in plaats van een main()
. Net als bij setup.py
, importeert gunicorn
uw code, zodat u niet wilt dat deze iets doet terwijl deze wordt geïmporteerd (vanwege het probleem met de importvergrendeling).
Antwoord 23
Elke module in python heeft een attribuut genaamd __name__
. De waarde van het kenmerk __name__
is __main__
wanneer de module rechtstreeks wordt uitgevoerd, zoals python my_module.py
. Anders (zoals wanneer je zegt import my_module
) is de waarde van __name__
de naam van de module.
Klein voorbeeld om in het kort uit te leggen.
#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()
We kunnen dit direct uitvoeren als
python test.py
Uitvoer
Value of __name__ is: __main__
Going to call hello_world
I am inside hello_world
Stel nu dat we bovenstaand script aanroepen vanuit een ander script
#script external_calling.py
import test
print(test.apple)
test.hello_world()
print(test.__name__)
Wanneer u dit uitvoert
python external_calling.py
Uitvoer
42
I am inside hello_world
test
Het bovenstaande spreekt dus voor zich dat wanneer u test aanroept vanuit een ander script, de lus __name__
in test.py
niet wordt uitgevoerd.
Antwoord 24
Dit antwoord is bedoeld voor Java-programmeurs die Python leren.
Elk Java-bestand bevat meestal één openbare klasse. Je kunt die klasse op twee manieren gebruiken:
-
Bel de klas vanuit andere bestanden. Je hoeft het alleen maar te importeren in het aanroepprogramma.
-
Laat de klas stand-alone uitvoeren voor testdoeleinden.
Voor het laatste geval moet de klasse een openbare statische void main()-methode bevatten. In Python wordt dit doel gediend door het globaal gedefinieerde label '__main__'
.
Antwoord 25
Als dit .py-bestand wordt geïmporteerd door andere .py-bestanden, wordt de code onder “het if-statement” niet uitgevoerd.
Als deze .py wordt uitgevoerd door python this_py.py
onder shell, of dubbelklikt in Windows. de code onder “het if-statement” wordt uitgevoerd.
Het is meestal geschreven om te testen.
Antwoord 26
Als de python-interpreter een bepaalde module uitvoert, heeft de globale variabele __name__
de waarde "__main__"
def a():
print("a")
def b():
print("b")
if __name__ == "__main__":
print ("you can see me" )
a()
else:
print ("You can't see me")
b()
Wanneer je dit script uitvoert, wordt afgedrukt je kunt me zien
een
Als u dit bestand importeert, zegt u A naar bestand B en voert u het bestand B uit en if __name__ == "__main__"
in bestand A wordt onwaar, dus het wordt afgedrukt U kunt het niet zien ik
b
Antwoord 27
if naam == ‘hoofd‘:
We zien of __name__ == '__main__':
heel vaak.
Het controleert of een module wordt geïmporteerd of niet.
Met andere woorden, de code in het if
-blok wordt alleen uitgevoerd als de code direct wordt uitgevoerd. Hier betekent directly
not imported
.
Laten we eens kijken wat het doet met een eenvoudige code die de naam van de module afdrukt:
# test.py
def test():
print('test module name=%s' %(__name__))
if __name__ == '__main__':
print('call test()')
test()
Als we de code rechtstreeks uitvoeren via python test.py
, is de modulenaam __main__
:
call test()
test module name=__main__
Antwoord 28
In eenvoudige bewoordingen:
De code die je ziet onder if __name__ == "__main__":
wordt alleen aangeroepen als je python-bestand wordt uitgevoerd als "python example1.py".
Als u echter uw python-bestand ‘example1.py’ als module wilt importeren om met een ander python-bestand te werken, zegt u ‘example2.py’, de code onder if __name__ == "__main__":
wordt niet uitgevoerd of heeft geen effect.
Antwoord 29
Alle antwoorden hebben de functionaliteit vrijwel verklaard. Maar ik zal een voorbeeld geven van het gebruik ervan, wat kan helpen om het concept verder te verduidelijken.
Stel dat je twee Python-bestanden hebt, a.py en b.py. Nu importeert a.py b.py. We voeren het a.py-bestand uit, waar eerst de code “import b.py” wordt uitgevoerd. Voordat de rest van de a.py-code wordt uitgevoerd, moet de code in het bestand b.py volledig worden uitgevoerd.
In de b.py-code is er een code die exclusief is voor dat bestand b.py en we willen geen ander bestand (anders dan het b.py-bestand), dat het b.py-bestand heeft geïmporteerd, om voer het uit.
Dus dat is wat deze regel code controleert. Als het het hoofdbestand is (d.w.z. b.py) dat de code uitvoert, wat in dit geval niet het geval is (a.py is het hoofdbestand dat wordt uitgevoerd), dan wordt alleen de code uitgevoerd.
Antwoord 30
Maak een bestand, a.py:
print(__name__) # It will print out __main__
__name__
is altijd gelijk aan __main__
wanneer dat bestand direct wordt uitgevoerd om aan te geven dat dit het hoofdbestand is.
Maak een ander bestand, b.py, in dezelfde map:
import a # Prints a
Voer het uit. Het zal a afdrukken, d.w.z. de naam van het bestand dat is geïmporteerd.
Dus, om twee verschillende gedragingen van hetzelfde bestand te laten zien, is dit een veelgebruikte truc:
# Code to be run when imported into another python file
if __name__ == '__main__':
# Code to be run only when run directly