Beim Schreiben von Code möchte ich oft Folgendes tun:
try:
foo()
except FooError:
handle_foo()
else:
try:
bar()
except BarError:
handle_bar()
else:
try:
baz()
except BazError:
handle_baz()
else:
qux()
finally:
cleanup()
Dies ist offensichtlich völlig unlesbar. Es drückt jedoch eine relativ einfache Idee aus: Führen Sie eine Reihe von Funktionen (oder Kurzcode-Schnipsel) mit jeweils einem Ausnahmebehandler aus und stoppen Sie, sobald eine Funktion ausfällt. Ich stelle mir vor, Python könnte syntaktischen Zucker für diesen Code bereitstellen, vielleicht so etwas:
# NB: This is *not* valid Python
try:
foo()
except FooError:
handle_foo()
# GOTO finally block
else try:
bar()
except BarError:
handle_bar()
# ditto
else try:
baz()
except BazError:
handle_baz()
# ditto
else:
qux()
finally:
cleanup()
Wenn keine Ausnahmen gemacht werden, entspricht dies foo();bar();baz();qux();cleanup()
. Wenn Ausnahmen ausgelöst werden, werden sie vom entsprechenden Ausnahmebehandler (falls vorhanden) behandelt, und wir fahren mit fort cleanup()
. Insbesondere wenn bar()
ein FooError
oder BazError
ausgelöst wird, wird die Ausnahme nicht abgefangen und an den Anrufer weitergegeben. Dies ist wünschenswert, damit wir nur Ausnahmen abfangen, die wir wirklich erwarten.
Ist diese Art von Code unabhängig von der syntaktischen Hässlichkeit im Allgemeinen nur eine schlechte Idee? Wenn ja, wie würden Sie es umgestalten? Ich stelle mir vor, dass Kontextmanager verwendet werden könnten, um einen Teil der Komplexität zu absorbieren, aber ich verstehe nicht wirklich, wie das im allgemeinen Fall funktionieren würde.
handle_*
Funktionen?