[python] Was passiert, wenn __name__ == "__main__": tun?


Answers

Wenn Ihr Skript ausgeführt wird, indem Sie es als Befehl an den Python-Interpreter übergeben,

python myscript.py

Der gesamte Code auf der Einrückungsebene 0 wird ausgeführt. Funktionen und Klassen, die definiert sind, sind gut definiert, aber keiner ihrer Code wird ausgeführt. Im Gegensatz zu anderen Sprachen gibt es keine main() -Funktion, die automatisch ausgeführt wird - die main() Funktion ist implizit der gesamte Code auf der obersten Ebene.

In diesem Fall ist der Code der obersten Ebene ein if Block. __name__ ist eine eingebaute Variable, die den Namen des aktuellen Moduls auswertet. Wenn jedoch ein Modul direkt ausgeführt wird (wie in myscript.py oben), wird __name__ stattdessen auf die Zeichenfolge "__main__" . So können Sie testen, ob Ihr Skript direkt ausgeführt wird oder durch etwas anderes importiert wird

if __name__ == "__main__":
    ...

Wenn Ihr Skript in ein anderes Modul importiert wird, werden seine verschiedenen Funktions- und Klassendefinitionen importiert und sein Code auf oberster Ebene wird ausgeführt, aber der Code im then-body der if Klausel wird nicht als Bedingung ausgeführt wird nicht erfüllt. Betrachten Sie als ein grundlegendes Beispiel die folgenden zwei Skripts:

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

Jetzt, wenn Sie den Interpreter als aufrufen

python one.py

Die Ausgabe wird sein

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

Wenn Sie stattdessen two.py :

python two.py

Du erhältst

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

Wenn also Modul one geladen wird, ist sein __name__ gleich "one" statt "__main__" .

Question

Was macht der if __name__ == "__main__": tun?

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



Was passiert, if __name__ == "__main__": tun?

__name__ ist eine globale Variable (in Python bedeutet global eigentlich auf Modulebene ), die in allen Namespaces existiert. Dies ist normalerweise der Name des Moduls (als str Typ).

Als einziger Spezialfall jedoch, in welchem ​​Python-Prozess Sie auch laufen, wie in mycode.py:

python mycode.py

Der ansonsten anonyme globale Namespace erhält den Wert '__main__' für seinen __name__ .

Also einschließlich der letzten Zeilen

if __name__ == '__main__':
    main()
  • Am Ende deines mycode.py-Skripts
  • Wenn es das primäre Einstiegspunktmodul ist, das von einem Python-Prozess ausgeführt wird,

bewirkt, dass die eindeutig definierte main Ihres Skripts ausgeführt wird.

Ein weiterer Vorteil dieses Konstrukts: Sie können Ihren Code auch als Modul in ein anderes Skript importieren und dann die Hauptfunktion ausführen, wenn und wenn Ihr Programm entscheidet:

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



Es gab viele verschiedene Annahmen über die Mechanik des fraglichen Codes, das "Wie", aber für mich machte alles keinen Sinn, bis ich das "Warum" verstand. Dies sollte besonders für neue Programmierer hilfreich sein.

Nimm die Datei "ab.py":

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

und eine zweite Datei "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()

Was macht dieser Code eigentlich?

Wenn Sie xy.py ausführen, import ab Sie import ab . Die import-Anweisung führt das Modul sofort beim Import aus, so dass die Operationen von ab vor dem Rest von xy ausgeführt werden. Wenn Sie mit ab fertig sind, geht es weiter mit xy .

Der Interpreter verfolgt, welche Skripte mit __name__ . Wenn Sie ein Skript ausführen - egal, wie Sie es benannt haben - nennt der Interpreter es "__main__" , was es zum Master- oder Home-Skript macht, zu dem nach dem Ausführen eines externen Skripts zurückgekehrt wird. Jedes andere Skript, das von diesem "__main__" __name__ , __name__ == "ab.py" seinen Dateinamen als __name__ (z. B. __name__ == "ab.py" ). Daher ist die Zeile if __name__ == "__main__": der Interpretertest, um zu bestimmen, ob das zu Beginn ausgeführte if __name__ == "__main__": interpretiert wird oder ob es vorübergehend in ein anderes (externes) Skript hineinspäht. Dies gibt dem Programmierer die Flexibilität, das Skript anders zu verhalten, wenn es direkt oder extern aufgerufen wird.

Lassen Sie uns den obigen Code durchgehen, um zu verstehen, was passiert, indem wir uns zunächst auf die nicht eingerückten Zeilen und deren Reihenfolge in den Skripten konzentrieren. Denken Sie daran, dass Funktions- oder def Blöcke nichts tun, bis sie aufgerufen werden. Was der Dolmetscher sagen könnte, wenn er zu sich selbst murmelte:

  • Öffne xy.py als 'home' Datei; nenne es "__main__" in der Variablen __name__ .
  • Importieren und öffnen Sie die Datei mit dem __name__ == "ab.py" .
  • Oh, eine Funktion. Ich werde mich daran erinnern.
  • Ok, Funktion a() ; Das habe ich gerade gelernt. ' Eine Funktion in einer Datei ' drucken .
  • Ende der Datei; zurück zu "__main__" !
  • Oh, eine Funktion. Ich werde mich daran erinnern.
  • Noch einer.
  • Funktion x() ; ok, Druck ' Peripherieaufgabe: könnte in anderen Projekten nützlich sein '.
  • Was ist das? Eine if Anweisung. Nun, die Bedingung wurde erfüllt (die Variable __name__ wurde auf "__main__" ), also gebe ich die main() -Funktion ein und "__main__" main function: Hier ist die Aktion ".

Die unteren zwei Zeilen bedeuten: "Wenn dies das main oder Heim-Skript ist, führen Sie die Funktion main() " aus. Aus diesem Grund sehen Sie ein def main(): block up top, das den Hauptfluss der Skriptfunktionalität enthält.

Warum das umsetzen?

Erinnern Sie sich an das, was ich zuvor über Importanweisungen gesagt habe? Wenn Sie ein Modul importieren, "erkennt" es es nicht nur und wartet auf weitere Anweisungen - es führt tatsächlich alle ausführbaren Operationen aus, die im Skript enthalten sind. Wenn Sie also das Fleisch Ihres Skripts in die Funktion main() setzen, wird es isoliert und isoliert, sodass es beim Import durch ein anderes Skript nicht sofort ausgeführt wird.

Auch hier gibt es Ausnahmen, aber in der Regel wird main() normalerweise nicht extern aufgerufen. Vielleicht fragen Sie sich also noch etwas: Wenn wir nicht main() aufrufen, warum rufen wir überhaupt das Skript an? Viele Leute strukturieren ihre Skripte mit eigenständigen Funktionen, die unabhängig vom Rest des Codes in der Datei ausgeführt werden. Sie werden später an anderer Stelle im Skripttext aufgerufen. Was mich dazu bringt:

Aber der Code funktioniert ohne ihn

Ja, das ist richtig. Diese separaten Funktionen können von einem Inline-Skript aufgerufen werden, das nicht in einer main() -Funktion enthalten ist. Wenn Sie (wie ich bin, in meinen frühen Lernphasen der Programmierung) daran gewöhnt sind, Inline-Skripte zu erstellen, die genau das tun, was Sie brauchen, und Sie werden versuchen, es wieder herauszufinden, wenn Sie diese Operation jemals wieder benötigen. Nun, Sie sind nicht an diese Art von interner Struktur zu Ihrem Code gewöhnt, weil es komplizierter zu bauen ist und nicht so intuitiv zu lesen ist. Aber das ist ein Skript, das seine Funktionen wahrscheinlich nicht extern aufgerufen haben kann, denn wenn es so wäre, würde es sofort beginnen, Variablen zu berechnen und zuzuordnen. Und wenn Sie versuchen, eine Funktion wiederzuverwenden, ist das neue Skript wahrscheinlich eng genug mit dem alten verwandt, dass es widersprüchliche Variablen geben wird.

Durch das Aufteilen unabhängiger Funktionen erhalten Sie die Möglichkeit, Ihre vorherige Arbeit wiederzuverwenden, indem Sie sie in ein anderes Skript aufrufen. Beispiel: "example.py" importiert möglicherweise "xy.py" und ruft x() , wobei die Funktion "x" aus "xy.py" verwendet wird. (Vielleicht wird das 3. Wort einer gegebenen Textzeichenfolge groß geschrieben; aus einer Liste von Zahlen wird ein numpliges Array erzeugt und in eine Quadratur gebracht; oder eine 3D-Oberfläche wird detrendiert. Die Möglichkeiten sind grenzenlos.)

[Nebenbei, dieser Thread enthält eine Antwort von @Kindall, die mir endlich geholfen hat zu verstehen - das Warum, nicht das Wie. Leider wurde es als ein Duplikat von diesem markiert, was ich für einen Fehler halte.]




Es gibt eine Reihe von Variablen, die das System (Python-Interpreter) für Quelldateien (Module) bereitstellt. Sie können ihre Werte jederzeit abrufen. Konzentrieren Sie sich also auf die Variable / Attribut __name__ :

Wenn Python eine Quellcodedatei lädt, wird der gesamte darin enthaltene Code ausgeführt. (Beachten Sie, dass es nicht alle in der Datei definierten Methoden und Funktionen aufruft, sondern sie definiert.)

Bevor der Interpreter jedoch die Quellcodedatei ausführt, definiert er einige spezielle Variablen für diese Datei. __name__ ist eine der speziellen Variablen, die Python automatisch für jede Quellcodedatei definiert.

Wenn Python diese Quellcodedatei als Hauptprogramm (dh die Datei, die Sie ausführen) lädt, legt es die spezielle Variable __name__ für diese Datei auf den Wert "__main__" fest .

Wenn dies von einem anderen Modul importiert wird, wird __name__ auf den Namen dieses Moduls gesetzt.

Also, in deinem Beispiel teilweise:

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

bedeutet, dass der Codeblock:

lock = thread.allocate_lock()
thread.start_new_thread(myfunction, ("Thread #: 1", 2, lock))
thread.start_new_thread(myfunction, ("Thread #: 2", 2, lock))

wird nur ausgeführt, wenn Sie das Modul direkt ausführen; Der Codeblock wird nicht ausgeführt, wenn ein anderes Modul ihn aufruft / importiert, da der Wert von __name__ in dieser bestimmten Instanz nicht mit " main " übereinstimmt .

Hoffe das hilft aus.




Wenn Name == ' Haupt ':

Wir sehen, ob __name__ == '__main__' : ziemlich oft.

Es prüft, ob ein Modul importiert wird oder nicht.

Mit anderen Worten, der Code innerhalb des if Blocks wird nur ausgeführt, wenn der Code direkt ausgeführt wird. Hier bedeutet directly not imported .

Lassen Sie uns sehen, was es mit einem einfachen Code macht, der den Namen des Moduls ausgibt:

# test.py
def test():
   print('test module name=%s' %(__name__))

if __name__ == '__main__':
   print('call test()')
   test()

Wenn wir den Code direkt über python test.py , lautet der __main__ :

call test()
test module name=__main__



Sie können die Datei sowohl als Skript als auch als importierbares Modul verwenden .

fibo.py (ein Modul namens 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]))

Referenz: https://docs.python.org/3.5/tutorial/modules.html




Bevor Sie etwas über if __name__ == '__main__' es wichtig zu verstehen, was __name__ ist und was es tut.

Was ist __name__ ?

__name__ ist ein DunderAlias ​​- kann als globale Variable betrachtet werden (zugänglich von Modulen) und funktioniert ähnlich wie global .

Es ist ein String (global wie oben erwähnt), wie durch den type(__name__) (ergibt <class 'str'> ) und ist ein eingebauter Standard für Python 3 und Python 2 .

Woher:

Es kann nicht nur in Skripten verwendet werden, sondern kann auch im Interpreter und in Modulen / Paketen gefunden werden.

Dolmetscher:

>>> print(__name__)
__main__
>>>

Skript:

test_file.py :

print(__name__)

Resultierend in __main__

Modul oder Paket:

somefile.py:

def somefunction():
    print(__name__)

test_file.py:

import somefile
somefile.somefunction()

Resultierend in somefile

Beachten Sie, dass __name__ bei Verwendung in einem Paket oder Modul den Namen der Datei __name__ . Der Pfad des eigentlichen Modul- oder Paketpfades ist nicht angegeben, hat aber ein eigenes DunderAlias __file__ , das dies zulässt.

Sie sollten sehen, dass wo __name__ , wo es die Hauptdatei (oder das Programm) ist, immer __main__ , und wenn es ein Modul / Paket ist oder irgendetwas, das von einem anderen Python-Skript __main__ , wird der Name der Datei zurückgegeben woher es stammt.

Trainieren:

Da eine Variable bedeutet, dass ihr Wert überschrieben werden kann ("kann" nicht "sollte" bedeuten), wird das Überschreiben des Wertes von __name__ zu einem Mangel an Lesbarkeit führen. Also tu es nicht, aus irgendeinem Grund. Wenn Sie eine Variable benötigen, definieren Sie eine neue Variable.

Es wird immer angenommen, dass der Wert von __name__ __main__ oder der Name der Datei ist. Wenn Sie diesen Standardwert erneut ändern, führt dies zu mehr Verwirrung, was wiederum zu Problemen führt, die später Probleme verursachen.

Beispiel:

>>> __name__ = 'Horrify' # Change default from __main__
>>> if __name__ == 'Horrify': print(__name__)
...
>>> else: print('Not Horrify')
...
Horrify
>>>

Im Allgemeinen wird es als gute Praxis if __name__ == '__main__' in Skripten das if __name__ == '__main__' .

Jetzt beantworten, if __name__ == '__main__' :

Jetzt wissen wir, dass das Verhalten von __name__ Dingen klarer wird:

Ein if ist eine Flusssteuerungs-Anweisung, die den Code-Block ausführt, wenn der angegebene Wert wahr ist. Wir haben gesehen, dass __name__ entweder __main__ oder den Dateinamen __name__ kann, aus dem es importiert wurde.

Das heißt, wenn __name__ gleich __name__ ist, __main__ die Datei die Hauptdatei sein und muss tatsächlich ausgeführt werden (oder es ist der Interpreter), nicht ein Modul oder Paket, das in das Skript importiert wurde.

Wenn __name__ tatsächlich den Wert von __main__ dann wird alles, was in diesem Codeblock ist, ausgeführt.

Dies sagt uns, dass, wenn die laufende Datei die Hauptdatei ist (oder Sie direkt vom Interpreter ausgeführt werden), diese Bedingung ausgeführt werden muss. Wenn es ein Paket ist, dann sollte es nicht, und der Wert wird nicht __main__ .

Module:

__name__ kann auch in Modulen verwendet werden, um den Namen eines Moduls zu definieren

Varianten:

Es ist auch möglich, andere, weniger gebräuchliche, aber nützliche Dinge mit __name__ zu __name__ , einige werde ich hier zeigen:

Wird nur ausgeführt, wenn die Datei ein Modul oder ein Paket ist:

if __name__ != '__main__':
    # Do some useful things 

Eine Bedingung ausführen, wenn die Datei die Hauptdatei ist, und eine andere, wenn dies nicht der Fall ist:

if __name__ == '__main__':
    # Execute something
else:
    # Do some useful things

Sie können es auch verwenden, um runnable Hilfefunktionen / Dienstprogramme für Pakete und Module ohne die aufwendige Verwendung von Bibliotheken bereitzustellen.

Außerdem können Module über die Befehlszeile als Hauptscripts ausgeführt werden, was ebenfalls sehr nützlich sein kann.




Wenn Sie Python interaktiv __name__ , wird der lokalen Variablen __name__ der Wert __main__ . Wenn Sie ein Python-Modul über die Befehlszeile ausführen, anstatt es in ein anderes Modul zu __name__ , wird dem Attribut __name__ der Wert __main__ und nicht der tatsächliche Name des Moduls zugewiesen. Auf diese Weise können Module ihren eigenen __name__ Wert __name__ , um selbst zu bestimmen, wie sie verwendet werden, sei es als Unterstützung für ein anderes Programm oder als Hauptanwendung, die über die Befehlszeile ausgeführt wird. Daher ist das folgende Idiom in Python-Modulen recht häufig:

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.



Was macht der if __name__ == "__main__": tun?

Um die Grundlagen zu skizzieren:

  • Die globale Variable __name__ in dem Modul, das der Einstiegspunkt für Ihr Programm ist, lautet '__main__' . Ansonsten ist es der Name, unter dem Sie das Modul importieren.

  • Der Code unter dem if Block wird also nur ausgeführt, wenn das Modul der Einstiegspunkt für Ihr Programm ist.

  • Es ermöglicht, dass der Code im Modul von anderen Modulen importiert werden kann, ohne dass der darunter liegende Codeblock beim Import ausgeführt wird.

Warum brauchen wir das?

Entwickeln und testen Sie Ihren Code

Angenommen, Sie schreiben ein Python-Skript, das als Modul verwendet werden soll:

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

Sie könnten das Modul testen, indem Sie diesen Aufruf der Funktion an den unteren Rand hinzufügen:

do_important()

und es (an einer Eingabeaufforderung) mit etwas wie:

~$ python important.py

Das Problem

Wenn Sie das Modul jedoch in ein anderes Skript importieren möchten:

import important

Beim Import wird die Funktion do_important aufgerufen, sodass Sie Ihren Funktionsaufruf do_important() am Ende do_important() .

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

Und dann müssen Sie sich daran erinnern, ob Sie Ihren Testfunktionsanruf auskommentiert haben oder nicht. Und diese zusätzliche Komplexität würde bedeuten, dass Sie wahrscheinlich vergessen werden, was Ihren Entwicklungsprozess schwieriger macht.

Ein besserer Weg

Die Variable __name__ zeigt auf den Namespace, wo auch immer der Python-Interpreter gerade ist.

In einem importierten Modul ist dies der Name dieses Moduls.

Aber innerhalb des primären Moduls (oder einer interaktiven Python-Sitzung, dh dem Read, Eval, Print Loop oder REPL des Interpreters) läuft alles von seinem "__main__" .

Also, wenn Sie vor der Ausführung überprüfen:

if __name__ == "__main__":
    do_important()

Mit dem oben genannten wird Ihr Code nur ausgeführt, wenn Sie ihn als primäres Modul ausführen (oder absichtlich von einem anderen Skript aus aufrufen).

Ein noch besserer Weg

Es gibt jedoch einen pythonischen Weg, dies zu verbessern.

Was ist, wenn wir diesen Geschäftsprozess von außerhalb des Moduls ausführen möchten?

Wenn wir den Code, den wir ausprobieren wollen, in eine Funktion wie diese '__main__' und testen, dann machen wir sofort nach '__main__' Überprüfung auf '__main__'

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

Wir haben nun eine letzte Funktion für das Ende unseres Moduls, das ausgeführt wird, wenn wir das Modul als primäres Modul ausführen.

Das Modul und seine Funktionen und Klassen können in andere Skripts importiert werden, ohne dass die main wird. Außerdem kann das Modul (und seine Funktionen und Klassen) aufgerufen werden, wenn es von einem anderen Modul '__main__' wird

import important
important.main()

Dieses Idiom finden Sie auch in der Python-Dokumentation in einer Erklärung des Moduls __main__ . In diesem Text heißt es:

Dieses Modul stellt den (ansonsten anonymen) Bereich dar, in dem das Hauptprogramm des Interpreters ausgeführt wird - Befehle, die entweder von der Standardeingabe, von einer Skriptdatei oder von einer interaktiven Eingabeaufforderung gelesen werden. Es ist diese Umgebung, in der die idiomatische Zeilengruppe "Conditional Script" bewirkt, dass ein Skript ausgeführt wird:

if __name__ == '__main__':
    main()



if __name__ == "__main__": ist im Grunde eine Skriptumgebung der obersten Ebene, sie gibt den Interpreter an ('Ich habe die höchste Priorität, die zuerst ausgeführt wird').

'__main__' ist der Name des Bereichs, in dem der Code der obersten Ebene ausgeführt wird. Das __name__ eines Moduls wird gleich '__main__' wenn es von der Standardeingabe, einem Skript oder von einer interaktiven Eingabeaufforderung gelesen wird.

if __name__ == "__main__":
    # execute only if run as a script
    main()



if __name__ == "__main__":
    main()

Überprüft, ob das Attribut __name__ des Python-Skripts "__main__" . Mit anderen Worten, wenn das Programm selbst ausgeführt wird, ist das Attribut __main__ , so dass das Programm ausgeführt wird (in diesem Fall die Funktion main() ).

Wenn Ihr Python-Skript jedoch von einem Modul verwendet wird, wird jeder Code außerhalb der if Anweisung ausgeführt. if \__name__ == "\__main__" nur verwendet wird, um zu prüfen, ob das Programm als Modul verwendet wird oder nicht, und entscheidet daher, ob der Code ausgeführt werden soll.






Related