тайм-аут для urllib2.urlopen() в версиях, предшествующих Python 2.6

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

  •  21-09-2019
  •  | 
  •  

Вопрос

В документация urllib2 говорит , что тайм - аут параметр был добавлен в Python 2.6.К сожалению, моя кодовая база работает на платформах Python 2.5 и 2.4.

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

Может быть, какая-нибудь альтернативная встроенная библиотека?(Не хотите устанавливать стороннюю версию, например pycurl)

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

Решение

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

socket.setdefaulttimeout()

вот так:

import urllib2
import socket
socket.setdefaulttimeout(30)
f = urllib2.urlopen('http://www.python.org/')

в этом случае ваш запрос urllib2 завершится таймаутом через 30 секунд и вызовет исключение сокета.(это было добавлено в Python 2.3)

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

Со значительным раздражением вы можете переопределить класс httplib.HttpConnection, который использует urllib2.HttpHandler.

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)

Я думаю, что ваш лучший выбор - это исправить (или развернуть локальную версию) вашего urllib2 с изменение из ветки обслуживания 2.6

Файл должен быть в /usr/lib/python2.4/urllib2.py (в Linux и 2.4)

Я использую httplib из стандартной библиотеки.Он имеет очень простой API, но обрабатывает только http, как вы могли догадаться.IIUC urllib использует httplib для реализации http-содержимого.

Вы должны установить тайм-аут в двух местах.

import urllib2
import socket

socket.setdefaulttimeout(30)
f = urllib2.urlopen('http://www.python.org/', timeout=30)

Что ж, способ обработки таймаута в 2.4 или 2.6 одинаков.Если вы откроете файл urllib2.py в версии 2.6, вы увидите, что он принимает дополнительный аргумент в качестве таймаута и обрабатывает его с помощью сокета.упомянутый метод defaulttimeout() является ответом 1.

Так что вам действительно не нужно обновлять свой urllib2.py в этом случае.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top