чтение потока, созданного urllib2, никогда не восстанавливается, когда соединение было прервано

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

  •  03-07-2019
  •  | 
  •  

Вопрос

Пытаясь сделать одно из моих приложений на Python более устойчивым в случае прерывания соединения, я обнаружил, что вызов функции чтения http-потока, созданного urllib2, может навсегда заблокировать скрипт.

Я думал, что функция чтения прекратит работу и в конечном итоге вызовет исключение, но это не похоже на случай, когда соединение было прервано во время вызова функции чтения.

Вот код, который вызовет проблему:

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"

(Если вы попробуете сценарий, вам, вероятно, потребуется несколько раз прервать соединение, прежде чем вы достигнете состояния, из которого сценарий никогда не восстанавливается)

Я наблюдал за сценарием через Winpdb и сделал скриншот состояния, из которого сценарий никогда не восстанавливается (даже если сеть снова стала доступной).

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

Есть ли способ создать сценарий Python, который будет продолжать работать надежно, даже если сетевое соединение было прервано? (Я бы предпочел не делать этого внутри дополнительного потока.)

Это было полезно?

Решение

Попробуйте что-то вроде:

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

Другие советы

Хороший вопрос, мне было бы очень интересно найти ответ. Единственный обходной путь, о котором я могу подумать, - это использовать прием сигнала, описанный в документах python , В вашем случае это будет больше похоже на:

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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top