web-dev-qa-db-ja.com

Python 3でurllibのタイムアウトを処理する方法は?

まず、私の問題は これ によく似ています。 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')
urlopen内のファイル「/usr/lib/python3.2/urllib/request.py」、138行目
return opener.open(url、data、timeout)
ファイル「/usr/lib/python3.2/urllib/request.py」、369行目、オープン
応答= self._open(req、data)
_ open内のファイル「/usr/lib/python3.2/urllib/request.py」、387行目
'_ open'、req)
_ call_chainのファイル「/usr/lib/python3.2/urllib/request.py」、行347
結果= func(* args)
http_openのファイル「/usr/lib/python3.2/urllib/request.py」、1156行目
return self.do_open(http.client.HTTPConnection、req)
ファイル「/usr/lib/python3.2/urllib/request.py」、1141行、do_open
r = h.getresponse()
getresponseのファイル「/usr/lib/python3.2/http/client.py」、行1046
response.begin()
ファイル「/usr/lib/python3.2/http/client.py」、346行目、開始
バージョン、ステータス、理由= self._read_status()
_ read_statusのファイル「/usr/lib/python3.2/http/client.py」、308行
line = str(self.fp.readline(_MAXLINE + 1)、 "iso-8859-1")
ファイル「/usr/lib/python3.2/socket.py」、276行目、readinto
return self._sock.recv_into(b)
socket.timeout:タイムアウト

Python 3からurllibおよびurllib2モジュールをurllibに再編成したときに、から大きな変更がありました。これを引き起こす変更はありましたか?

23
nindalf

例外はソケットからのタイムアウトなので、

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

新しい例外をキャッチする必要があります。

33
danodonovan

前の回答はタイムアウトエラーを正しくインターセプトしません。タイムアウトエラーは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と同様に、タイムアウトには関連付けられていません。

9
Régis B.