[Python-ideas] Retrying EAFP without DRY

Carl M. Johnson cmjohnson.mailinglist at gmail.com
Sat Jan 21 10:14:41 CET 2012


On Jan 20, 2012, at 10:57 PM, Steven D'Aprano wrote:

> Chris Rebert wrote:
>> On Fri, Jan 20, 2012 at 11:47 PM, Steven D'Aprano <steve at pearwood.info> wrote:
>> <snip>
>>> I just wish that break and continue could be written outside of a loop, so
>>> you can factor out common code:
> [...]
>> Easily accomplished:
>> def do_the_thing(x):
>>    try:
>>        do_something(x)
>>    except SpamError:
>>        fix_up(x)
>>        return False
>>    else:
>>        return True
>> def try_repeatedly(n, func, arg):
>>   for _ in range(n):
>>       if func(arg): break
>>   else:
>>       raise HamError('tried %d times, giving up now" % n)
>> try_repeatedly(5, do_the_thing, y)
> 
> Not so easily accomplished if you need the return result from do_the_thing. Naturally you can always return a tuple
> 
> (result_I_actually_want, code_to_break_or_continue)
> 
> but that's not exactly elegant.

I'd make the place I factor out code different:

    def try_repeatedly(times, exception, callback, args, kwargs):
        for _ in range(times):
            try:
                return callback(*args, **kwargs)
            except exception:
                continue
            break
        error_message = "Tried {} times but could not complete callback {}"
        error_message = error_message.format(times, repr(callback))
        raise Exception(error_message)

    try_repeatedly(5, SpamError, do_something, [x])


More information about the Python-ideas mailing list