bukzor <wo**********@gmail.comwrote:
On May 21, 4:33 pm, Karlo Lozovina <_karlo_@_mosor.net_wrote:
>André <andre.robe...@gmail.comwrote
innews:a9913f2d-0c1a-4492-bf58-5c7
88*******@s50g2000hsb.googlegroups.com:
>>
How about something like the following (untested)
done = False
while not done:
try:
some_function()
done = True
except:
some_function2()
some_function3()
Sure, that works, but I was aiming for something more elegant and
Pythonic
Catching only the specific exceptions you think you can handle would be
more Pythonic: that way things like sys.exit() will still work inside
some_function.
>
It's hard to get around a while loop if you want to conditionally
repeat something. There's no built-in way to do what you ask.
I prefer a 'for' loop rather than 'while' so I can limit the number of
retries.
The following may or may not be 'more pythonic', but is something I've
used. It's a factory to generate decorators which will retry the
decorated function. You have to specify the maximum number of retries,
the exceptions which indicate that it is retryable, and an optional
filter function which can try to do fixups or just specify some
additional conditions to be tested.
class TooManyRetries(Exception):
def __init__(self, inner):
self.inner = inner
def __str__(self):
return 'Too many retries: %s' % (str(self.inner),)
def retryable(max_retries, exceptions, filter=None):
"""Creates a decorator which will retry specific exceptions.
After there have been too many retries it raises TooManyRetries.
"""
def decorator(f):
def wrapper(*args, **kw):
for i in xrange(max_retries):
try:
return f(*args, **kw)
except exceptions, e:
exc_info = sys.exc_info()
# Check for retry even the last time in case the
# filter wants to do any logging.
if filter is not None and filter(e,
i==max_retries-1):
pass
else:
raise
# If we get here we have exceeded the maximum number of
# retries.
raise TooManyRetries, e, exc_info[2]
wrapper.__name__ = f.__name__
return wrapper
return decorator
def isConflictError(error, lasttime):
if (error.code==500
and error.hdrs['Bobo-Exception-Type']=='ConflictError'):
timestamp("Conflict Error", error.filename)
return True
return False
retryConflict = retryable(3, HTTPError, isConflictError)
# ----- some code showing it in use -----------
from mechanize import Browser
browser = Browser()
submit = retryConflict(browser.submit)
follow_link = retryConflict(browser.follow_link)
@retryConflict
def openpage(message, url, name=None):
global PASSWORD
if PASSWORD is None:
start = time.time()
PASSWORD = getpass.getpass()
#PASSWORD = raw_input("password?")
end = time.time()
logger.LASTTIME += end-start # Don't include input in timestamp.
resp = browser.open(url)
follow_relay()
if "ourloginpage" in browser.geturl():
# Not yet logged in
timestamp("Got login form")
browser.select_form(nr=0)
browser["user"] = USERID
browser["pass"] = PASSWORD
resp = browser.submit()
follow_relay()
if 'query' in [f.name for f in browser.forms()]:
if name=="query":
soup = BeautifulSoup(browser.response().read())
err = soup.find('td', 'tdbodywarning')
sys.exit(''.join(err.p.contents).strip())
timestamp(message, name, url)
return resp