web-dev-qa-db-fra.com

Comment gérer le délai d'expiration d'urllib dans Python 3?

Tout d'abord, mon problème est assez similaire à celui-ci . Je voudrais un délai d'expiration de urllib.urlopen () pour générer une exception que je peux gérer.

Cela ne relève-t-il pas d'URLError?

try:
    response = urllib.request.urlopen(url, timeout=10).read().decode('utf-8')
except (HTTPError, URLError) as error:
    logging.error(
        'Data of %s not retrieved because %s\nURL: %s', name, error, url)
else:
    logging.info('Access successful.')

Le message d'erreur:

resp = urllib.request.urlopen (req, timeout = 10) .read (). decode ('utf-8')
Fichier "/usr/lib/python3.2/urllib/request.py", ligne 138, dans urlopen
return opener.open (url, data, timeout)
Fichier "/usr/lib/python3.2/urllib/request.py", ligne 369, en ouvert
response = self._open (req, data)
Fichier "/usr/lib/python3.2/urllib/request.py", ligne 387, dans _open
'_ open', req)
Fichier "/usr/lib/python3.2/urllib/request.py", ligne 347, dans _call_chain
result = func (* args)
Fichier "/usr/lib/python3.2/urllib/request.py", ligne 1156, dans http_open
return self.do_open (http.client.HTTPConnection, req)
Fichier "/usr/lib/python3.2/urllib/request.py", ligne 1141, dans do_open
r = h.getresponse ()
Fichier "/usr/lib/python3.2/http/client.py", ligne 1046, dans getresponse
response.begin ()
Fichier "/usr/lib/python3.2/http/client.py", ligne 346, au début
version, statut, raison = self._read_status ()
Fichier "/usr/lib/python3.2/http/client.py", ligne 308, dans _read_status
line = str (self.fp.readline (_MAXLINE + 1), "iso-8859-1")
Fichier "/usr/lib/python3.2/socket.py", ligne 276, en lecture dans
return self._sock.recv_into (b)
socket.timeout: expiration

Il y a eu un changement majeur par rapport à Python 3 quand ils ont réorganisé les urllib et urllib2 modules dans urllib. Est-il possible qu'il y ait eu alors un changement qui provoque cela?

23
nindalf

L'exception est le délai d'expiration du socket, donc

from socket import timeout
try:
    response = urllib.request.urlopen(url, timeout=10).read().decode('utf-8')
except (HTTPError, URLError) as error:
    logging.error('Data of %s not retrieved because %s\nURL: %s', name, error, url)
except timeout:
    logging.error('socket timed out - URL %s', url)
else:
    logging.info('Access successful.')

devrait attraper la nouvelle exception.

33
danodonovan

La réponse précédente n'intercepte pas correctement les erreurs de délai d'attente. Les erreurs de timeout sont déclenchées comme URLError, donc si nous voulons les attraper spécifiquement, nous devons écrire:

from urllib.error import HTTPError, URLError
import socket

try:
    response = urllib.request.urlopen(url, timeout=10).read().decode('utf-8')
except HTTPError as error:
    logging.error('Data not retrieved because %s\nURL: %s', error, url)
except URLError as error:
    if isinstance(error.reason, socket.timeout):
        logging.error('socket timed out - URL %s', url)
    else:
        logging.error('some other error happened)
else:
    logging.info('Access successful.')

Notez que ValueError peut être augmenté indépendamment, c'est-à-dire si l'URL n'est pas valide. Comme HTTPError, il n'est pas associé à un timeout.

9
Régis B.