Ao escrever código, geralmente quero fazer algo assim:
try:
foo()
except FooError:
handle_foo()
else:
try:
bar()
except BarError:
handle_bar()
else:
try:
baz()
except BazError:
handle_baz()
else:
qux()
finally:
cleanup()
Obviamente, isso é completamente ilegível. Mas está expressando uma idéia relativamente simples: execute uma série de funções (ou trechos de código curto), com um manipulador de exceção para cada uma, e pare assim que uma função falhar. Eu imagino que o Python poderia fornecer açúcar sintático para esse código, talvez algo como isto:
# 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()
Se nenhuma exceção for gerada, isso será equivalente a foo();bar();baz();qux();cleanup()
. Se as exceções são geradas, elas são tratadas pelo manipulador de exceções apropriado (se houver) e pulamos para cleanup()
. Em particular, se bar()
gerar a FooError
ou BazError
, a exceção não será capturada e será propagada para o chamador. Isso é desejável, de modo que apenas capturamos exceções que realmente esperamos tratar.
Independentemente da feiura sintática, esse tipo de código é apenas uma má idéia em geral? Se sim, como você o refatoraria? Imagino que os gerentes de contexto possam ser usados para absorver parte da complexidade, mas não entendo realmente como isso funcionaria no caso geral.
handle_*
funções?