bukzor <[EMAIL PROTECTED]> wrote: > On May 21, 4:33 pm, Karlo Lozovina <[EMAIL PROTECTED]> wrote: >> André <[EMAIL PROTECTED]> wrote >> innews:a9913f2d-0c1a-4492-bf58-5c7 > [EMAIL PROTECTED]: >> >> > 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 -- http://mail.python.org/mailman/listinfo/python-list