[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):
try:
response = urllib2.urlopen(url)
except urllib2.HTTPError as e:
if e.code == 503: # Service Unavailable.
time.sleep(delay)
delay *= 2 # Exponential back-off.
else:
raise
else:
break
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
try:
response = urllib2.urlopen(url)
except urllib2.HTTPError as e:
if e.code == 503 and count < MAX_ATTEMPTS: # Service Unavailable
time.sleep(delay)
delay *= 2 # Exponential back-off
count += 1
retry
else:
raise
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.
--
Steven
More information about the Python-ideas
mailing list