La lectura de un flujo hecho por urllib2 nunca se recupera cuando se interrumpe la conexión

StackOverflow https://stackoverflow.com/questions/811446

  •  03-07-2019
  •  | 
  •  

Pregunta

Al intentar hacer que una de mis aplicaciones de Python sea un poco más robusta en caso de interrupciones de conexión, descubrí que llamar a la función de lectura de una secuencia http hecha por urllib2 puede bloquear el script para siempre.

Pensé que la función de lectura expirará y eventualmente generará una excepción, pero este no parece ser el caso cuando la conexión se interrumpió durante una llamada a la función de lectura.

Aquí está el código que causará el problema:

import urllib2

while True:
    try:
        stream = urllib2.urlopen('http://www.google.de/images/nav_logo4.png')
        while stream.read(): pass
        print "Done"
    except:
        print "Error"

(Si prueba el script, probablemente deba interrumpir la conexión varias veces antes de llegar al estado desde el cual el script nunca se recupera)

Observé el script a través de Winpdb e hice una captura de pantalla del estado desde el cual el script nunca se recupera (incluso si la red estuviera disponible nuevamente).

Winpdb http://img10.imageshack.us/img10/6716/urllib2.jpg

¿Hay alguna forma de crear una secuencia de comandos de Python que continúe funcionando de manera confiable incluso si se interrumpe la conexión de red? (Preferiría evitar hacer esto dentro de un hilo adicional).

¿Fue útil?

Solución

Prueba algo como:

import socket
socket.setdefaulttimeout(5.0)
   ...
try:
   ...
except socket.timeout:
   (it timed out, retry)

Otros consejos

Buena pregunta, estaría realmente interesado en encontrar una respuesta. La única solución que se me ocurre es usar el truco de señal que se explica en python docs . En tu caso será más como:

import signal
import urllib2

def read(url):
    stream = urllib2.urlopen(url)
    return stream.read()

def handler(signum, frame):
    raise IOError("The page is taking too long to read")

# Set the signal handler and a 5-second alarm
signal.signal(signal.SIGALRM, handler)
signal.alarm(5)

# This read() may hang indefinitely
try:
    output = read('http://www.google.de/images/nav_logo4.png')
except IOError:
    # try to read again or print an error
    pass

signal.alarm(0)          # Disable the alarm
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top