Как обработать тайм-аут urllib в Python 3? - PullRequest
20 голосов
/ 06 января 2012

Во-первых, моя проблема очень похожа на эту .Я хотел бы, чтобы тайм-аут urllib.urlopen () сгенерировал исключение, которое я могу обработать.

Разве это не относится к 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.')

Сообщение об ошибке:

resp = urllib.request.urlopen (req, timeout = 10) .read (). Decode ('utf-8')
Файл "/usr/lib/python3.2/urllib/request.py ", строка 138, в urlopen
вернуть opener.open (url, data, timeout)
Файл" /usr/lib/python3.2/urllib/request.py ", строка 369, в открытом
response = self._open (req, data)
Файл "/usr/lib/python3.2/urllib/request.py", строка 387, в _open
'_open', req)
Файл "/usr/lib/python3.2/urllib/request.py", строка 347, в _call_chain
result = func (* args)
Файл "/usr/lib/python3.2/urllib/request.py ", строка 1156, в http_open
вернуть self.do_open (http.client.HTTPConnection, req)
Файл" /usr/lib/python3.2/urllib/request.py ", строка 1141, вdo_open
r = h.getresponse ()
Файл "/usr/lib/python3.2/http/client.py", строка 1046, в ответе getresponse
.begin ()
Файл "/usr/lib/python3.2/http/client.py", строка 346, в начале
версия, статус, причина = self._read_status ()
Файл "/ usr/lib/python3.2/http/client.py ", строка 308, в _read_status
line = str (self.fp.readline (_MAXLINE + 1)," iso-8859-1 ")
File"/usr/lib/python3.2/socket.py ", строка 276, в readinto
return self._sock.recv_into (b)
socket.timeout: timed out

Thereбыло серьезным изменением по сравнению с Python 3, когда они реорганизовали модули urllib и urllib2 в urllib.Возможно ли, что тогда произошло изменение, которое вызывает это?

Ответы [ 2 ]

28 голосов
/ 06 января 2012

Исключением является тайм-аут от сокета, поэтому

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.')

должно перехватить новое исключение.

5 голосов
/ 17 сентября 2018

Предыдущий ответ не правильно перехватывает ошибки тайм-аута. Ошибки тайм-аута выдаются как URLError, поэтому, если мы хотим специально их перехватить, нам нужно написать:

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.')

Обратите внимание, что ValueError может быть вызвано независимо, т. Е. Если URL недействителен. Как и HTTPError, он не связан с тайм-аутом.

...