563 Stimmen

Warum brauchen wir die "finally"-Klausel in Python?

Ich bin mir nicht sicher, warum wir finally en try...except...finally Erklärungen. Meiner Meinung nach ist dieser Codeblock

try:
    run_code1()
except TypeError:
    run_code2()
other_code()

ist das Gleiche mit diesem hier, das finally :

try:
    run_code1()
except TypeError:
    run_code2()
finally:
    other_code()

Habe ich etwas verpasst?

735voto

Mark Byers Punkte 761508

Es macht einen Unterschied, wenn Sie früher zurückkehren:

try:
    run_code1()
except TypeError:
    run_code2()
    return None   # The finally block is run before the method returns
finally:
    other_code()

Vergleichen Sie mit diesem:

try:
    run_code1()
except TypeError:
    run_code2()
    return None   

other_code()  # This doesn't get run if there's an exception.

Andere Situationen, die zu Unterschieden führen können:

  • Wenn innerhalb des Except-Blocks eine Ausnahme ausgelöst wird.
  • Wenn eine Ausnahme ausgelöst wird in run_code1() aber es ist kein TypeError .
  • Andere Kontrollflussanweisungen wie continue y break Erklärungen.

143voto

kindall Punkte 167554

Sie können verwenden finally um sicherzustellen, dass Dateien oder Ressourcen unabhängig davon, ob eine Ausnahme auftritt, geschlossen oder freigegeben werden, auch wenn Sie die Ausnahme nicht abfangen. (Oder wenn Sie das nicht verstehen spezifisch Ausnahme).

myfile = open("test.txt", "w")

try:
    myfile.write("the Answer is: ")
    myfile.write(42)   # raises TypeError, which will be propagated to caller
finally:
    myfile.close()     # will be executed before TypeError is propagated

In diesem Beispiel wäre es besser, wenn Sie die with Anweisung, aber diese Art von Struktur kann auch für andere Arten von Ressourcen verwendet werden.

Ein paar Jahre später schrieb ich einen Blogbeitrag über einen Missbrauch von finally die die Leser vielleicht amüsant finden.

36voto

Antimony Punkte 35481

Sie sind nicht gleichwertig. finally Der Code wird ausgeführt, egal was sonst passiert*. Er ist nützlich für Bereinigungscode, der ausgeführt werden muss.


* : Wie Mark Byers kommentiert wird, verhindert alles, was den Prozess sofort beendet, auch die finally -Code auszuführen. Letzteres könnte ein os._exit(). oder Stromausfall, aber auch eine Endlosschleife oder andere Dinge fallen in diese Kategorie.

30voto

captainblack Punkte 3342

Ergänzend zu den anderen oben genannten Antworten sei gesagt, dass die finally Klausel wird auf jeden Fall ausgeführt, während die else Klausel wird nur ausgeführt, wenn keine Ausnahme ausgelöst wurde.

Wenn Sie beispielsweise in eine Datei ohne Ausnahmen schreiben, wird Folgendes ausgegeben:

file = open('test.txt', 'w')

try:
    file.write("Testing.")
    print("Writing to file.")
except IOError:
    print("Could not write to file.")
else:
    print("Write successful.")
finally:
    file.close()
    print("File closed.")

OUTPUT:

Writing to file.
Write successful.
File closed.

Wenn eine Ausnahme auftritt, gibt der Code Folgendes aus (beachten Sie, dass ein absichtlicher Fehler dadurch verursacht wird, dass die Datei schreibgeschützt ist).

file = open('test.txt', 'r')

try:
    file.write("Testing.")
    print("Writing to file.")
except IOError:
    print("Could not write to file.")
else:
    print("Write successful.")
finally:
    file.close()
    print("File closed.")

OUTPUT:

Could not write to file.
File closed.

Wir können sehen, dass die finally Klausel wird unabhängig von einer Ausnahme ausgeführt. Ich hoffe, das hilft.

21voto

Shub Punkte 342

Hier ist ein Stück Code, um den Unterschied zu verdeutlichen:

...

try: 
  a/b
  print('In try block')

except TypeError:
  print('In except block')

finally: 
  print('In finally block')

print('Outside')

a, b = 0, 1

Ausgabe:

In try block 
In finally block 
Outside

(Keine Fehler, außer übersprungener Block.)


a, b = 1, 0

Ausgabe:

In finally block

Traceback (most recent call last):
a/b
ZeroDivisionError: division by zero

(Es ist keine Ausnahmebehandlung für ZeroDivisionError und wird nur der finally-Block ausgeführt. )


a, b = 0, '1'

Ausgabe:

In except block 
In finally block 
Outside

(Die Ausnahme wird ordnungsgemäß behandelt und das Programm wird nicht unterbrochen).


Hinweis: Wenn Sie eine außer Block zur Behandlung aller Arten von Fehlern, der schließlich Block wird überflüssig sein.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X