rllib2ドキュメント は、timeoutパラメータがPython 2.6に追加されたことを示しています。残念ながら私のコードベースはPython 2.5および2.4プラットフォームで実行されています。
タイムアウトをシミュレートする別の方法はありますか?私がやりたいのは、コードが一定時間リモートサーバーと通信できるようにすることだけです。
おそらく、代替の組み込みライブラリはありますか? (pycurlのようなサードパーティをインストールしたくない)
以下を使用して、すべてのソケット操作(HTTP要求を含む)のグローバルタイムアウトを設定できます。
このような:
import urllib2
import socket
socket.setdefaulttimeout(30)
f = urllib2.urlopen('http://www.python.org/')
この場合、urllib2リクエストは30秒後にタイムアウトし、ソケット例外をスローします。 (これはPython 2.3)で追加されました
かなりの苛立ちで、urllib2.HTTPHandlerが使用するhttplib.HTTPConnectionクラスをオーバーライドできます。
def urlopen_with_timeout(url, data=None, timeout=None):
# Create these two helper classes fresh each time, since
# timeout needs to be in the closure.
class TimeoutHTTPConnection(httplib.HTTPConnection):
def connect(self):
"""Connect to the Host and port specified in __init__."""
msg = "getaddrinfo returns an empty list"
for res in socket.getaddrinfo(self.Host, self.port, 0,
socket.SOCK_STREAM):
af, socktype, proto, canonname, sa = res
try:
self.sock = socket.socket(af, socktype, proto)
if timeout is not None:
self.sock.settimeout(timeout)
if self.debuglevel > 0:
print "connect: (%s, %s)" % (self.Host, self.port)
self.sock.connect(sa)
except socket.error, msg:
if self.debuglevel > 0:
print 'connect fail:', (self.Host, self.port)
if self.sock:
self.sock.close()
self.sock = None
continue
break
if not self.sock:
raise socket.error, msg
class TimeoutHTTPHandler(urllib2.HTTPHandler):
http_request = urllib2.AbstractHTTPHandler.do_request_
def http_open(self, req):
return self.do_open(TimeoutHTTPConnection, req)
opener = urllib2.build_opener(TimeoutHTTPHandler)
opener.open(url, data)
Urllib2に 2.6メンテナンスブランチからの変更 でパッチを適用(またはローカルバージョンをデプロイ)するのが最善の選択だと思います。
ファイルは/usr/lib/python2.4/urllib2.py
にある必要があります(Linuxおよび2.4の場合)
標準ライブラリのhttplibを使用しています。非常に単純なAPIがありますが、ご想像のとおりhttpのみを処理します。 IIUC urllibは、httplibを使用してhttpのものを実装します。
タイムアウトは2か所で設定する必要があります。
import urllib2
import socket
socket.setdefaulttimeout(30)
f = urllib2.urlopen('http://www.python.org/', timeout=30)
ええと、2.4と2.6のどちらでもタイムアウトが処理される方法は同じです。 2.6でurllib2.pyファイルを開くと、タイムアウトとして追加の引数を取り、前述のようにsocket.defaulttimeout()メソッドを使用して処理することがわかります。
したがって、その場合はurllib2.pyを更新する必要はありません。