Bedeutung des if-mains Blocks

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
crazyyzarc
User
Beiträge: 28
Registriert: Freitag 10. Juli 2015, 21:08
Wohnort: PyLand

Was bedeutet es genau mir wurde es immer ganz lang erklärt wobei ich wenig verstand aber was nützt es und man muss man es überhaupt eintragen?

Code: Alles auswählen

if __name__ == '__main__':
    main()
Benutzeravatar
HarteWare
User
Beiträge: 69
Registriert: Samstag 23. Februar 2013, 21:16
Wohnort: localhost

Mein Verständnis ist folgendes: Du sorgst dafür, dass das Script nur ausgeführt wird, wenn es o.a. via

Code: Alles auswählen

python script.py
aufgerufen wird. Man will dadurch verhindern, dass irgendwelcher Code als Nebenwirkung ausgeführt wird, wenn man z.B. das hier macht

Code: Alles auswählen

import script
P.S.: Versuch nächstes mal verstärkt selbst zu recherchieren: https://docs.python.org/3/library/__main__.html

LG
HarteWare
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

In kleinen Skripten bringt Dir dieses Konstrukt keine Vorteile. Insbesondere wenn das Skript keinerlei Funktionen oder Klassen enthält. Diese Seite http://matplotlib.org/gallery.html ist voll mit hochwertigen Beispiel-Skripten und es wird keine spezielle main() Funktion benötigt. Wenn ein Konstrukt keine Vorteile bringt, dann sollte es weggelassen werden. Hier z.B. ein kleines Beispiel-Skript, das einen 2D-Plot erzeugt ohne main() Funktion

Code: Alles auswählen

import numpy as np
import matplotlib.pyplot as plt

x_1d = np.linspace(-3,3,601)
y_1d = np.linspace(-2,2,401)

x_2d, y_2d = np.meshgrid(x_1d, y_1d)
z_2d = 1/(x_2d**2 + y_2d**2 + 1) * np.cos(np.pi * x_2d) * np.cos(np.pi * y_2d)

plt.figure()
plt.pcolormesh(x_2d, y_2d, z_2d)
plt.gca().set_aspect("equal") 
plt.show()
und hier mit main() Funktion

Code: Alles auswählen

import numpy as np
import matplotlib.pyplot as plt

def main():
    x_1d = np.linspace(-3,3,601)
    y_1d = np.linspace(-2,2,401)
    
    x_2d, y_2d = np.meshgrid(x_1d, y_1d)
    z_2d = 1/(x_2d**2 + y_2d**2 + 1) * np.cos(np.pi * x_2d) * np.cos(np.pi * y_2d)
    
    plt.figure()
    plt.pcolormesh(x_2d, y_2d, z_2d)
    plt.gca().set_aspect("equal") 
    plt.show()
    
if __name__ == '__main__':
    main()
Zähl die Zeilen, dann weist Du was besser ist.

Es gibt allerdings auch viele Situationen bei denen eine main() Funktion sehr nützlich ist.

Wenn Du z.B. in der GUI-Programmierung in einem Modul ein MainWindow entwickelst und der Code zum Starten des MainWindows und damit der ganzen Anwendung im selben Modul sein soll. Wenn Du das ohne main() Funktion machst, dann hast Du keine Möglichkeit das Fenster auch von woanders zu benutzen. Auch bei einem Dialog kann das Sinn machen. Ein Dialog soll eigentlich nur vom Hauptfenster aus aufgerufen werden, trotzdem bekommt das Modul mit dem Dialog eine main() Funktion, damit man beim Entwickeln mal eben sehen kann, ob das Layout und die Beschriftung passt.

Ein Modul, das eigentlich nur für den Import bestimmt ist, kann eine main() Funktion enthalten. Diese main() Funktion kann beispielhaft zeigen, wie die Funktionen und Klassen des Moduls zu benutzen sind oder diese testen.

Manchmal wird die main() Funktion auch eingesetzt um zu zeigen, dass man nicht blos skriptet, sondern wie in Java oder C++ Anwendungen entwickelt.
a fool with a tool is still a fool, www.magben.de, YouTube
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

crazyyzarc hat geschrieben:Was bedeutet es genau mir wurde es immer ganz lang erklärt wobei ich wenig verstand aber was nützt es und man muss man es überhaupt eintragen?

Code: Alles auswählen

if __name__ == '__main__':
    main()
Der `if`-Block wird ausgeführt, wenn das Programm als Skript gestartet wird (z.B. via ``python dein_programm.py``). Denn in diesem Fall trägt Python für `__name__` den Wert "__main__" ein. Bei einem Import als Modul (``import dein_programm``) wird der Block *nicht* ausgeführt.

Man will dies üblicherweise dann, wenn man das zu startende Programm in Funktionen und/oder Klassen aufgeteilt hat. Python kann nämlich nicht auf magische Weise wissen, welche Funktion als erstes aufgerufen werden soll. Einige andere Programiersprachen erwarten `main()` als die erste aufzurufende Funktion, aber Python hat diesen Mechanismus bewusst nicht eingebaut. Irgendwie muss man Python also mitteilen können, was überhaupt passieren soll, wenn das Skript gestartet wurde. Nach einem Import als Modul kann man die benötigte Funktion einfach selbst aufrufen, aber bei einem Skript gibt es die Möglichkeit des direkten Funktionsaufrufes nicht.

Man ist beim Schreiben des Skripts gewissermaßen also gezwungen, immer am Ende `main()` ausführen lassen (wie gesagt: die Aufteilung in entsprechende Funktionen vorausgesetzt), damit das Skript mit seiner eigentlichen Arbeit beginnen kann. Ein schlichtes `main()` ohne den `if`-Block führt aber dazu, dass `main()` *immer* durchlaufen wird. Das möchte man in Fällen, wo das Skript als Modul importiert wird, jedoch *nicht* haben. In diesem Fall will man nur Teile des Skripts über entsprechende Funktionen aufrufen, z.B. zum Testen oder für eine anderweitige Verwendung. Da würde das automatische Ausführen von `main()` eher nervig anstatt nützlich sein. Daher vollzieht man die besagte Unterscheidung.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

snafu hat geschrieben:Der `if`-Block wird ausgeführt, wenn das Programm als Skript gestartet wird (z.B. via ``python dein_programm.py``). Denn in diesem Fall trägt Python für `__name__` den Wert "__main__" ein. Bei einem Import als Modul (``import dein_programm``) wird der Block *nicht* ausgeführt.
Das etwas verwirrend ausgedrückt:

Letztlich wird nur die Variable __name__ anders gesetzt. Sodas die typische If-Abfrage erfüllt oder nicht erfüllt ist.

Will sagen: Python "sucht" nicht nach genau diesem if-Konstrukt :wink:

Man kann das auch anders abfragen und die "main()" Funktion kann auch ganz anders heißen.

Mal eine test.py:

Code: Alles auswählen

#!/usr/bin/env python

from __future__ import print_function

print("__name__:", __name__)
Direkt aufgerufen:

Code: Alles auswählen

~ $ python test.py
__name__: __main__
und aufgerufen:

Code: Alles auswählen

~ $ python
Python 2.7.6 (default, Jun 22 2015, 18:00:18) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import test
__name__: test
>>> 

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

@MagBen: Die Matplotlib-Gallery-Schnippsel sind hochwertige Beispielskripte? Ach na gut, Du bist ja auch der Fehlgeleitete der behauptet alle Physiker wären bessere Programmierer als die meisten (oder war das gar alle?) Informatikabsolventen. :twisted:
crazyyzarc
User
Beiträge: 28
Registriert: Freitag 10. Juli 2015, 21:08
Wohnort: PyLand

Also im Grunde nütz es nur wenn man die main()-Methode benutzt um sie überhaupt aufzurufen hab es hier mal getestet:

Code: Alles auswählen

def main():
    print("Hi")
Was kam raus? Nichts (PS: ich arbeite mit IDLE also klicke auf den "Run" button und nicht über die Konsole mit "python name.py" das ist mir zu kompliziert :D

und wenn ich die if-Funktion hinzufüge kommt "Hi" raus, also so wie das aufrufen einer Methode in einer Main Methode (Java, C(++))

Also theoretisch: kann man alle Funktionen(bspw. ciao()) in der main()-Funktion rein schreiben um sie überhaupt auszuführen. Die main()-Funktion wiederum wird nur dannn ausgeführt und die darin enthaltene Funktionen wenn man es im if-Abteil beschreibt das er sie ausführen soll als erstes.

Meine Frage: Wäre es nicht schlau alle Funktionen im if-Abteil zu lagern ? :D theoretisch könnte es gehen oder? also wie im Beispiel gezeigt:

Code: Alles auswählen

def main():
    print("Hi")

def ciao():
    print("ciao")

if __name__ == '__main__':
    main()
    ciao()
*immerhin funktioniert das Skript
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

crazyyzarc hat geschrieben: Meine Frage: Wäre es nicht schlau alle Funktionen im if-Abteil zu lagern ? :D theoretisch könnte es gehen oder? also wie im Beispiel gezeigt:
Es gibt Leute, die das machen und *keine* eigene ``main``-Methode schreiben. In Deinem Beispiek gäbe es also kein ``main()``, sondern nur ``ciao()``! Ich persönlich bevorzuge eine ``main``-Methode der Bündelung von Funktionsaufrufen direkt im Hook.

Ich denke die meisten Python-Projekte arbeiten auch so!

Ich würde also so vorgehen:

Code: Alles auswählen

def do_something_else():
    # usw.

def ciao():
    # usw.

def main():
    print("Hi")
    do_something_else()
    ciao()
    # and so on...
 
if __name__ == '__main__':
    main()
Es ist auch gebräuchlich, den ``if __name__ == '__main__'-Hook ganz ans Ende eines Moduls zu schreiben und die darin aufgerufene Funktion *direkt* darüber, also quasi als vorletztes. Das offzielle Python macht das durchaus auch so, z.B. im ``json``-Modul, welches direkt über den Interpreter für das pretty printing eines JSON-Dokuments zur Verfügung gestellt wird: http://svn.python.org/view/python/trunk ... iew=markup
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Antworten