Quand urllib2.request
atteint le délai d'expiration, un urllib2.URLError
l'exception est levée. Quelle est la méthode Pythonic pour réessayer d'établir une connexion?
J'utiliserais un décorateur réessayer . Il y en a d'autres, mais celui-ci fonctionne plutôt bien. Voici comment vous pouvez l'utiliser:
@retry(urllib2.URLError, tries=4, delay=3, backoff=2)
def urlopen_with_retry():
return urllib2.urlopen("http://example.com")
Cela réessayera la fonction si URLError
est levé. Consultez le lien ci-dessus pour obtenir de la documentation sur les paramètres, mais en gros, il réessayera un maximum de 4 fois, avec un retard de coupure exponentiel doublant à chaque fois, par ex. 3 secondes, 6 secondes, 12 secondes.
Il existe quelques bibliothèques spécialisées dans ce domaine.
L'un est backoff , qui est conçu avec une sensibilité particulièrement fonctionnelle. Les décorateurs reçoivent des callables arbitraires renvoyant des générateurs qui produisent des valeurs de retard successives. Une interruption exponentielle simple avec un temps de relance maximum de 32 secondes pourrait être définie comme:
@backoff.on_exception(backoff.expo,
urllib2.URLError,
max_value=32)
def url_open(url):
return urllib2.urlopen("http://example.com")
Un autre est nouvelle tentative qui a des fonctionnalités très similaires mais une API où les paramètres de nouvelle tentative sont spécifiés au moyen d'arguments de mot clé prédéfinis.
Pour réessayer sur timeout, vous pouvez attraper l'exception comme @ Karl Barker suggéré dans le commentaire :
assert ntries >= 1
for _ in range(ntries):
try:
page = urlopen(request, timeout=timeout)
break # success
except URLError as err:
if not isinstance(err.reason, socket.timeout):
raise # propagate non-timeout errors
else: # all ntries failed
raise err # re-raise the last timeout error
# use page here