2010-01-18 23 views
28

Các urllib2 documentation nói rằng tham số timeout được thêm vào trong Python 2.6. Thật không may, cơ sở mã của tôi đã chạy trên các nền tảng Python 2.5 và 2.4.timeout cho urllib2.urlopen() trong các phiên bản pre Python 2.6

Có cách nào khác để mô phỏng thời gian chờ không? Tất cả những gì tôi muốn làm là cho phép mã để nói chuyện với máy chủ từ xa trong một khoảng thời gian cố định.

Có lẽ bất kỳ thư viện tích hợp thay thế nào khác? (Không muốn cài đặt bên thứ 3, như pycurl)

Trả lời

57

bạn có thể thiết lập một thời gian chờ toàn cầu cho tất cả các hoạt động ổ cắm (bao gồm các yêu cầu HTTP) bằng cách sử dụng:

socket.setdefaulttimeout()

như thế này:

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

trong trường hợp này, yêu cầu urllib2 của bạn sẽ timeout sau 30 giây và ném một ngoại lệ ổ cắm. (điều này đã được thêm vào bằng Python 2.3)

+0

'Mô-đun urllib2 đã được chia thành nhiều mô-đun trong Python 3.0 có tên urllib.request và urllib.error.' Nhưng các mã còn lại đủ đơn giản. – MewX

2

Tôi nghĩ rằng lựa chọn tốt nhất của bạn là để vá (hoặc triển khai một phiên bản địa phương của) urllib2 của bạn với the change from the 2.6 maintenance branch

Các tập tin phải ở trong /usr/lib/python2.4/urllib2.py (trên Linux và 2.4)

+1

còn socket.settimeout() thì sao? Nó có giúp được không? – rubayeet

+0

Tôi nghĩ rằng có thể, tôi đã có cùng một vấn đề khá lâu rồi, và vì một lý do nào đó tôi không thể làm cho nó hoạt động được. Tuy nhiên, tôi không có hồi ức bất cứ điều gì nơi mã có thể không thể kiểm tra:/ – Kimvais

1

Tôi sử dụng httplib từ thư viện chuẩn. Nó có một API đơn giản chết, nhưng chỉ xử lý http như bạn có thể đoán. IIUC urllib sử dụng httplib để thực hiện các công cụ http.

+2

Thật không may httplib chỉ hỗ trợ timeout trong 2.6 – rubayeet

0

Vâng, thời gian chờ xử lý được xử lý bằng 2,4 hoặc 2,6 là như nhau. Nếu bạn mở tập tin urllib2.py trong 2.6 u sẽ thấy rằng phải mất thêm một đối số là timeout và xử lý nó bằng phương thức socket.defaulttimeout() như đã đề cập là câu trả lời 1.

Vì vậy, bạn thực sự không cần cập nhật urllib2 của bạn .py trong trường hợp đó.

4

Với kích ứng đáng kể, bạn có thể ghi đè lên lớp httplib.HTTPConnection mà urllib2.HTTPHandler sử dụng.

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) 
1

Bạn phải đặt thời gian chờ ở hai nơi.

import urllib2 
import socket 

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

Cả hai đều hoạt động độc lập. Tuy nhiên timeout = 30 hoạt động một mình. Đây là câu trả lời tốt nhất cho tôi, vì vậy tôi loại bỏ -1 bạn đã có. Nếu bạn sửa đổi tiêu đề câu trả lời của mình thành tiêu đề "Bạn có thể chọn đặt thời gian chờ ở một hoặc cả hai địa điểm". Câu hỏi chính cũng khắc phục được vấn đề của phiên bản Python. – ruralcoder

Các vấn đề liên quan