[Python-ideas] Retrying EAFP without DRY
Steven D'Aprano
steve at pearwood.info
Sat Jan 21 08:47:46 CET 2012
Mike Meyer wrote:
> A single new keyword/clause, "retry". It has the same syntax as an
> "except" clause, can be used anywhere "except" can be used, and can be
> intermingled with them in the same try statement. There's probably a
> better syntax, but this is easy to describe.
> The behavior change from except is that instead of exiting the "try"
> statement when the "retry" clause ends, it restarts the try
This sounds like retry should be a flow-control statement, like continue or
break, not a block. E.g.:
try:
something()
except ValueError:
if condition: retry
else: raise
"retry" will jump back to the start of the try block -- a limited form of
GOTO, with all the pros and cons of this.
> clause. In python, this code:
>
> try:
> # try block
> except:
> # except block
> retry:
> # retry block
> else:
> # else block
> finally:
> # finally block
>
> Would provide the same behavior as this code:
>
> while True:
> try:
> # try block
> except:
> # except block
> retry:
> # retry block
> else:
> # else block
> finally:
> # finally block
> break
Um, you're trying to explain the behaviour of retry here, but your Python code
includes a retry. This is one case where recursion is NOT your friend.
> Where except & retry can be repeated, include exceptions to check
> against, and intermixed with each other. The break would propagate up
> to the else block and any except blocks if there was no finally. If
> there's no else, the break from it winds up at the end of the try.
None of your explanation is clear to me.
Under what circumstances will the retry block be executed? E.g. given:
try:
len(None)
except TypeError:
print("spam spam spam")
retry:
print("a")
what will happen?
How about these?
#1
try:
len(None)
retry:
print("a")
except TypeError:
print("spam spam spam")
#2
try:
len(None)
except TypeError:
print("spam spam spam")
retry:
print("a")
except ValueError:
print("this never gets called")
retry:
print("b")
#3
try:
len(None)
except TypeError:
print("spam spam spam")
retry:
print("a")
retry:
print("b")
> The use case, as mentioned, is avoiding doing EAFP without repeating
> the code in the exception handler. I.e., the choices without retry
> are things like (LBYL):
I think that the idiom of a while or for loop is easy enough to read and write:
for _ in range(5): # retry five times
try:
do_something(x)
except SpamError:
x = fix_up(x)
else:
break
else:
raise HamError("tried 5 times, giving up now")
I just wish that break and continue could be written outside of a loop, so you
can factor out common code:
def do_the_thing(x):
try:
do_something(x)
except SpamError:
x = fix_up(x)
else:
break
def try_repeatedly(n, func):
for _ in range(n):
func()
else:
raise HamError('tried %d times, giving up now" % n)
try_repeatedly(5, do_the_thing)
--
Steven
More information about the Python-ideas
mailing list