Which of these is easier to read?
An empty except
block:
try:
foo = do_foo()
except FooError:
pass # see below
else:
return do_bar(foo)
# Recover from the FooError (long, complicated)
Or this:
try:
foo = do_foo()
except FooError:
# Recover from the FooError (long, complicated)
else:
return do_bar(foo)
Note that the recovery is significantly more complex than the one-line else
block. It may itself involve indented blocks or other complications. The first option has the advantage of eliminating a level of indentation. But the second option is probably closer to what the average developer expects to see. I’m uncertain which of these concerns is more important for readability.
3
I think you are accurate about the trade-off involved – neither is ideal. Out of those two, I personally prefer the first one since the control flow is easier to follow.
That said, I’d suggest considering a third option that you didn’t mention: factor out some or all of the recovery logic into a separate function. That keeps the control flow simple and avoids having a big block of recovery code in the except clause.
Explicit is better than implicit.
If you are handling an exception, handle it. Right there, right then.
1