[Python-ideas] Retrying EAFP without DRY

Steven D'Aprano steve at pearwood.info
Tue Jan 24 12:19:35 CET 2012

Carl M. Johnson wrote:
> On Jan 23, 2012, at 9:00 PM, Nick Coghlan wrote:
>> On Tue, Jan 24, 2012 at 3:47 PM, Mike Meyer <mwm at mired.org> wrote:
>>> The argument isn't that we need a new syntax for a small set of loops,
>>> it's that the only ways to implement retrying after an exception leave
>>> a code smell.
>> Uh, saying "retrying is fundamentally a looping operation" is not a code
>> smell.
> I do think there's something code smelly about a retry--if it didn't work
> the first time, why should it work the second time after you give it a
> whack? Either whacking is good and you should do it in advance or it's bad
> and you should do something more sophisticated

"Whacking" is not necessarily bad or difficult, and is not necessarily a code 
smell. There are many common situations where "try again" is natural and 
expected. E.g. in response to a busy signal, you should wait a little while 
before retrying:

delay = 5  # Initial delay between attempts in seconds.
for _ in range(MAX_ATTEMPTS):
         response = urllib2.urlopen(url)
     except urllib2.HTTPError as e:
         if e.code == 503:  # Service Unavailable.
             delay *= 2  # Exponential back-off.

This could be written without the for-loop using a hypothetical retry 
statement, but it doesn't really gain us much:

delay = 2  # Initial delay between attempts in seconds.
count = 0
     response = urllib2.urlopen(url)
except urllib2.HTTPError as e:
     if e.code == 503 and count < MAX_ATTEMPTS:  # Service Unavailable
         delay *= 2  # Exponential back-off
         count += 1

Although you save one indent level, you don't save any lines of code, and it 
costs you the effort of handling the book-keeping that a for-loop would give 
you for free. I don't count this as a win.


More information about the Python-ideas mailing list