Tempo limite para urllib2.urlopen () nas versões pré -python 2.6
Pergunta
o Documentação URLLIB2 diz que tempo esgotado O parâmetro foi adicionado no Python 2.6. Infelizmente, minha base de código está em execução nas plataformas Python 2.5 e 2.4.
Existe alguma maneira alternativa de simular o tempo limite? Tudo o que quero fazer é permitir que o código fale ao servidor remoto por um período fixo de tempo.
Talvez alguma biblioteca interna alternativa? (Não quero instalar a 3ª festa, como pycurl)
Solução
Você pode definir um tempo limite global para todas as operações de soquete (incluindo solicitações HTTP) usando:
assim:
import urllib2
import socket
socket.setdefaulttimeout(30)
f = urllib2.urlopen('http://www.python.org/')
Nesse caso, sua solicitação de urllib2 teria tempo limite após 30 segundos e lançaria uma exceção de soquete. (Isso foi adicionado no Python 2.3)
Outras dicas
Com uma irritação considerável, você pode substituir a classe httplib.httpconnection que o urllib2.httphandler usa.
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)
Eu acho que sua melhor escolha é corrigir (ou implantar uma versão local de) seu urllib2 com A mudança do ramo de manutenção 2.6
O arquivo deve estar em /usr/lib/python2.4/urllib2.py
(no Linux e 2.4)
Eu uso httplib da biblioteca padrão. Ele tem uma API simples, mas apenas lida com o HTTP, como você pode imaginar. O iiuc urllib usa httplib para implementar o material HTTP.
Você deve definir o tempo limite em dois lugares.
import urllib2
import socket
socket.setdefaulttimeout(30)
f = urllib2.urlopen('http://www.python.org/', timeout=30)
Bem, a maneira como o tempo limite é tratado em 2.4 ou 2.6 é o mesmo. Se você abrir o arquivo urllib2.py em 2.6, veria que ele leva um argumento extra como o tempo limite e o lida usando o método Socket.DefaultTimeout (), conforme mencionado, é a resposta 1.
Portanto, você realmente não precisa atualizar seu urllib2.py nesse caso.