was als return, wenn Fehler in Funktion?

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
pynomos
User
Beiträge: 10
Registriert: Freitag 1. April 2011, 08:49

Hi,

gibt es ein "Standard"-Vorgehen, wenn ich in einer Funktion einen Fehler habe/erzeuge was ich als return angebe, wenn ich sonnst ein Array zurück gebe, d.h. wenn ich bei einer Funktion wenn alles "glatt läuft" ein Array zurück gebe, was mache ich wenn ein Fehler aufgetreten ist?

Im "Hauptprogramm" müsste ich ja irgendwie abfangen, ob Werte oder ein Fehler zurück gegeben werden...


Wie macht man das am elegantensten...??

mit Dank!

pynomos
Benutzeravatar
snafu
User
Beiträge: 6732
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Dann wirft man eine Ausnahme (engl. Exception), welche für den Abbruch der Funktion sorgt. Die Ausnahme wird an die aufrufende (also "höhergestellte") Funktion weitergereicht. Der aufrufenden Funktion steht es dann frei, ob sie die Ausnahme sinnvoll behandelt, die Ausnahme explizit ignoriert (wenn sie denn gute Gründe dafür hat) oder (bewusst oder unbewusst) überhaupt keine Behandlung der Ausnahme betreibt, was letztlich zum Programmabbruch führt (sofern es oberhalb dieser Funktion nichts mehr gibt, was den Fehler behandeln würde).
pynomos
User
Beiträge: 10
Registriert: Freitag 1. April 2011, 08:49

wenn ich das richtig verstehe, brauche ich in der Funktion in except kein return einbauen? wird den die Fehlernummer/Bezeichnung auch mit übergeben?

so i.E. ??

Code: Alles auswählen

def test():
  try:
    x = 0/1
  except:
    pass

def main():
  try:
    test()
  except:
    print('fehler')

main()
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

pynomos hat geschrieben:wenn ich das richtig verstehe, brauche ich in der Funktion in except kein return einbauen?
Kapiere ich nicht! Wenn Du einen Wert zurückgeben willst, musst Du das auch tun. Du kannst auch in einem except-Ast ein return einbauen - das kommt halt immer auf die Logik an.
pynomos hat geschrieben: wird den die Fehlernummer/Bezeichnung auch mit übergeben?
Wenn Du ein "raise Exception"-Konstrukt verwendest, kannst Du das alles realisieren. Bei den gängigen Exceptions werden idR. auch Beschreibungen mit übergeben.

Arbeite halt mal den Abschnitt im offiziellen Tutorial durch (das in die Doku integrierte).
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
pynomos
User
Beiträge: 10
Registriert: Freitag 1. April 2011, 08:49

upps ein return muss natürlich in das test-try rein...

meine Frage ist eher in der Funktion main() - müsste ich dann prüfen

Code: Alles auswählen

   wert = test()
   if wert == 'ERROR':
       ....
oder geht das "hübscher" - dazu finde ich eben nix

Code: Alles auswählen

def test():
  try:
    x = 0/1
    return x
  except:
    return 'ERROR'

def main():
  try:
    test()
  except:
    print('fehler')

main()
Benutzeravatar
snafu
User
Beiträge: 6732
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Genau das von dir gezeigte sollte man *nicht* tun. Das meinte ich auch mit "expliziter Behandlung". Besser wäre sowas in der Art:

Code: Alles auswählen

def get_number_input():
    while True:
        try:
            return int(raw_input('Give me a natural number: '))
        except ValueError:
            print 'Wrong input type. Try again!'
Falls du Python 3.x benutzt, müsstest du aus dem `raw_input` ein `input` machen und um den String für die Ausgabe von `print` Klammern setzen. Beachte, dass man die Schleife in meiner Version mit Strg+C abbrechen kann, da der dann geworfene `KeyboardInterrupt` eben kein `ValueError` ist.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Sollte es keine von sich aus auftretende Exception sein, die Du nach oben durchreichen willst, musst Du per raise eine werfen.

Dein Beispiel sieht mir danach aus, denn 0 / x ist ja ein mathematisch vollkommen gültiger Ausdruck; andersherum gäbe es natürlich eine Exception...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
snafu
User
Beiträge: 6732
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Und noch ein Tipp am Rande: Nachdenken/sacken lassen bevor man alle 2 Minuten etwas neues schreibt, hilft meistens ungemein. Es liegt nämlich in der Natur der Sache, dass man völlig neue Konzepte nicht auf Anhieb versteht. Mit übermäßiger Fragerei neigt man schnell dazu, den bereitwilligen Helfern irgendwann auf die Nerven zu gehen. ;)
pynomos
User
Beiträge: 10
Registriert: Freitag 1. April 2011, 08:49

o.k. - "die Beispiele" habe ich schon gesehen - meine Frage geht eher in die Richtung, wie ich einem "Hauptprogram" mitteile, dass es in einer Funktion einen Fehler gegeben hat... es wird ja nicht im Sinne des Erfinders sein, immr gleich ein print + sys.exit() zu schmeißen

Das "Hauptprogramm" sollte ja noch die Chance bekommen, "sauber runter zu fahren" und ggf. Logfiles zu bestücken und zu schließen...
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Das ist dann das Problem deiner konkreten Anwendung. Wenn du den Fehler behandeln kannst, dann fängst du die Exception ab, machst deine Aufräumarbeiten und wirfst ggf. eine neue Exception und höhere Ebenen im Programm zu informieren. Wenn du nichts machen kannst, dann lässt du die Exception unbehandelt und sie wird immer weiter durchgereit, bis sie irgendwann das Programm beendet.
Das Leben ist wie ein Tennisball.
pynomos
User
Beiträge: 10
Registriert: Freitag 1. April 2011, 08:49

@eydu

... und wie "informiere" ich die höheren Ebenen im Programm?

irgendwie muss ich doch "in der höheren Ebene" mitbekommen, ob als return ein Wert/Array kommt oder ein Fehler??

Das ist der Haken, "an dem ich hänge"...
Pekh
User
Beiträge: 482
Registriert: Donnerstag 22. Mai 2008, 09:09

Indem du in deiner Unterfunktion per 'raise' eine Exception wirfst. Unter Umständen nimmt Python dir das ab, wenn du eine ungültige Operation durchführst (z.B. Division durch 0). Diese Ausnahme wird dann von Python durch den ganzen Aufruf-Stack hochgereicht, bis sich irgendein Programmteil für zuständig erklärt (via try ... except MeineKonkreteException). Wird auf diese Weise die höchste Ebene erreicht, und es findet sich immer noch keine Fehlerbehandlung, bricht das Programm ab und der Traceback verrät dir, wo das Problem aufgetreten ist.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Genau das macht die Exception für dich. Versuche mal das folgende Stückchen Code zu verstehen:

Code: Alles auswählen

def spam(x):
    return 1/x
def eggs(x):
    print spam(x)
def foo(x):
    print eggs(x)
def bar(x):
    try:
        print foo(x)
    except ZeroDivisionError:
        print "error"

bar(1)
print
bar(0)
Das Leben ist wie ein Tennisball.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

pynomos hat geschrieben:@eydu

... und wie "informiere" ich die höheren Ebenen im Programm?

irgendwie muss ich doch "in der höheren Ebene" mitbekommen, ob als return ein Wert/Array kommt oder ein Fehler??

Das ist der Haken, "an dem ich hänge"...
Na, die Exception wird doch entsprechend der Funktionsaufrufe hochgereicht! An einer geeigneten Stelle greifst Du die eben per try... except ab:

Code: Alles auswählen

def div(a, b):
    return a / b

dev foo():
    return div(2, 0)

def bar():
    return foo()

def func():
    try:
        res = bar()
    except ZeroDivisionError
        # res wird noch benötigt; wenn Berechnung nicht klappt, soll res = 0 sein
        res = 0
    # hier weiter
    value = res + ...
Du kannst die Exception natürlich auch in div, foo oder auch bar behandeln. Hängt eben davon ab, wo es sinnvoll ist. In diesem Beispiel wäre es direkt in div() am sinnvollsten, da es einen default-Wert gibt, mit dem weiter gerechnet werden soll.

Edit: @EyDu: Lol... zwei Dumme ein Gedanke ;-) Naja, hat so viel Mühe gemacht, da poste ich trotz Zeitrückstands dennoch mal meine Variante.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Den zeitlichen Vorsprung habe ich mir durch konsequentes Einsparen von Leerzeilen und Kommentaren herausgeholt ^^
Das Leben ist wie ein Tennisball.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

EyDu hat geschrieben:Den zeitlichen Vorsprung habe ich mir durch konsequentes Einsparen von Leerzeilen und Kommentaren herausgeholt ^^
Ich schiebe es jetzt mal auch darauf und nicht auf meine Chat-Aktivitäten paralleler Weise... :mrgreen:
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Antworten