einen Strom von urllib2 gemacht Lesen erholt sich nie, wenn die Verbindung unterbrochen wurde
Frage
Bei dem Versuch, eine meiner Python-Anwendungen ein bisschen robuster bei Verbindungsunterbrechungen zu machen entdeckte ich, dass die Lesefunktion eines http-Stream von urllib2 gemacht Aufruf kann für immer das Skript blockieren.
Ich dachte, dass die Lesefunktion Timeout wird und schließlich eine Ausnahme auslösen, aber diese Naht nicht der Fall sein, wenn die Verbindung während einer Lesefunktion Anruf unterbrochen wurde.
Hier ist der Code, der das Problem verursacht:
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"
(Wenn Sie das Skript ausprobieren müssen Sie wahrscheinlich die Verbindung mehrmals zu unterbrechen, bevor Sie den Zustand erreichen wird, aus dem das Skript erholt sich nie)
beobachtete ich das Drehbuch über Winpdb und einen Screenshot des Staates, aus dem das Skript erholt sich nie (auch wenn das Netzwerk wieder verfügbar bekam).
Winpdb http://img10.imageshack.us/img10/6716/urllib2.jpg
Gibt es eine Möglichkeit, einen Python-Skript zu erstellen, die zuverlässig arbeiten auch dann weiter, wenn die Netzwerkverbindung unterbrochen wurde? (Ich würde es vorziehen, tat dies innerhalb eines extra Thread zu vermeiden.)
Lösung
Versuchen Sie so etwas wie:
import socket
socket.setdefaulttimeout(5.0)
...
try:
...
except socket.timeout:
(it timed out, retry)
Andere Tipps
Gute Frage, ich würde bei der Suche nach einer Antwort wirklich interessiert. Die einzige Abhilfe, die ich denken konnte, wird das Signal Trick erklärt in Python docs . In Ihrem Fall wird es mehr wie:
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