2009-05-01 10 views
8

Durante il tentativo di fare una delle mie applicazioni Python un po 'più robusti in caso di interruzioni di connessione ho scoperto che chiamando la funzione di lettura di un http-stream fatta da urllib2 può bloccare la sceneggiatura per sempre.lettura di un flusso fatta da urllib2 non si riprende quando la connessione ottenuto interrotta

ho pensato che la funzione di lettura verrà timeout e infine sollevare un'eccezione, ma questo non cucitura essere il caso in cui il collegamento ottenuto interrotto durante una chiamata funzione di lettura.

Qui è il codice che causerà il 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" 

(Se si prova lo script è probabilmente necessario interrompere il collegamento più volte prima di raggiungere lo stato da cui lo script non recupera)

ho guardato la sceneggiatura via Winpdb e ha fatto uno screenshot dello stato da cui lo script non riprenderà mai (anche se la rete ha nuovamente disponibile).

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

C'è un modo per creare uno script python che continuerà a lavorare affidabile anche se la connessione di rete ottenuto interrotto? (Preferirei evitare di fare questo all'interno di un filo in più.)

+0

+1 per una questione ben scritto –

risposta

6

Prova qualcosa di simile:

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

Sembra che questo sia risolto il mio problema. Grazie! – Martin

+0

Funziona, eccetto se rovina il multiprocessing a causa di [Bug 6056] (http://bugs.python.org/issue6056). C'è un altro modo per aggiungere un timeout a urllib2 senza influire sul timeout predefinito dei socket? – UsAaR33

2

Buona domanda, sarei molto interessato a trovare una risposta. L'unica soluzione che potrei pensare è usare il trucco del segnale spiegato in python docs. Nel tuo caso, sarà più simile a:

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 
+0

che sembra un lavoro molto promettente, ma abituato per me visto che sto lavorando su un PC Windows. – Martin

+0

ah, capisco. La soluzione di Alex sembra comunque promettente. –

Problemi correlati