2012-02-29 20 views
16

cho mã này:cách bật yêu cầu chế độ không đồng bộ?

import sys 

import gevent 
from gevent import monkey 

monkey.patch_all() 

import requests 
import urllib2 

def worker(url, use_urllib2=False): 
    if use_urllib2: 
     content = urllib2.urlopen(url).read().lower() 
    else: 
     content = requests.get(url, prefetch=True).content.lower() 
    title = content.split('<title>')[1].split('</title>')[0].strip() 

urls = ['http://www.mail.ru']*5 

def by_requests(): 
    jobs = [gevent.spawn(worker, url) for url in urls] 
    gevent.joinall(jobs) 

def by_urllib2(): 
    jobs = [gevent.spawn(worker, url, True) for url in urls] 
    gevent.joinall(jobs) 

if __name__=='__main__': 
    from timeit import Timer 
    t = Timer(stmt="by_requests()", setup="from __main__ import by_requests") 
    print 'by requests: %s seconds'%t.timeit(number=3) 
    t = Timer(stmt="by_urllib2()", setup="from __main__ import by_urllib2") 
    print 'by urllib2: %s seconds'%t.timeit(number=3) 
    sys.exit(0) 

kết quả này:

by requests: 18.3397213892 seconds 
by urllib2: 2.48605842363 seconds 

trong sniffer có vẻ này:

mô tả: 5 yêu cầu đầu tiên được sended bởi thư viện yêu cầu, 5 yêu cầu tiếp theo là được gửi bởi thư viện urllib2. màu đỏ - là thời gian khi công việc bị đóng băng, tối - khi dữ liệu nhận được ... wtf ?!

Làm thế nào để đặt thư viện socket được vá và thư viện phải hoạt động giống nhau? Cách yêu cầu sử dụng mà không có yêu cầu. Đồng bộ hóa cho công việc không đồng bộ?

+0

bạn có thể giải thích vấn đề của bạn một chút nữa? Tại sao bạn không muốn sử dụng mô-đun requests.async? – Phani

+0

Yêu cầu không hoạt động không đồng bộ. Tại sao? Tôi không muốn sử dụng requests.async vì có chứa giao diện xấu để sử dụng và không làm việc không đồng bộ quá. Nhìn vào hình ảnh, có thể nhìn thấy cách yêu cầu công việc và urllib2. – user1239798

+1

Xem http://stackoverflow.com/questions/9110593/asynchronous-requests-with-python-requests và https://github.com/kennethreitz/grequests. –

Trả lời

14

Xin lỗi Kenneth Reitz. Thư viện của anh ấy thật tuyệt vời.

Tôi ngu ngốc. Tôi cần chọn miếng vá khỉ cho httplib như thế này:

gevent.monkey.patch_all(httplib=True) 

Vì miếng vá cho httplib bị tắt theo mặc định.

+11

Không hợp lệ nữa: ValueError: gevent.httplib không còn được cung cấp, httplib phải là False – mamcx

+1

Sử dụng grequests (bởi @KennethReitz). Nó chủ yếu là ghi đè các động từ chính, và kế thừa phần còn lại. –

2

Tôi đã chạy mã trên máy của mình (python 2.7.1, gevent 0.13.0, requests 0.10.6). Nó bật ra rằng thời gian luôn luôn là một tốt thứ hai hoặc hai nhanh hơn khi sử dụng các mô-đun yêu cầu. Bạn đang sử dụng phiên bản nào? Việc nâng cấp có thể chỉ giải quyết vấn đề cho bạn.

by requests: 3.7847161293 seconds 
by urllib2: 4.92611193657 seconds 

by requests: 2.90777993202 seconds 
by urllib2: 7.99798607826 seconds 
+0

Tôi đang sử dụng phiên bản này: python 2.7.2.5, gevent 0.13.6, yêu cầu 0.10.6 – user1239798

+0

Các phiên bản của bạn thậm chí còn nâng cao hơn, vì vậy điều đó thật kỳ lạ. Tôi đã đăng một câu trả lời khác, có thể giúp bạn. – Phani

5

Các yêu cầu có hỗ trợ gevent tích hợp vào codebase:

http://docs.python-requests.org/en/latest/user/advanced/#asynchronous-requests

+0

Xin lỗi, nhưng nó cũng không hoạt động không đồng bộ. Tại sao nó là posible? – user1239798

+0

Tôi cảm ơn rất nhiều vì bạn đã quan tâm đến vấn đề của tôi. Đó là một vinh dự đối với tôi rằng tác giả của thư viện này đã trả lời cho câu hỏi của tôi. – user1239798

7

Như đã chỉ ra bởi Kenneth, một điều chúng ta có thể làm là để cho các requests mô-đun xử lý các phần không đồng bộ. Tôi đã thực hiện các thay đổi đối với mã của bạn cho phù hợp. Một lần nữa, đối với tôi, kết quả cho thấy nhất quán rằng mô-đun requests hoạt động tốt hơn urllib2

Làm điều này có nghĩa là chúng tôi không thể "chuyển" phần gọi lại. Nhưng điều đó sẽ không sao, vì lợi ích chính chỉ nên được mong đợi với các yêu cầu HTTP do sự chậm trễ yêu cầu/đáp ứng.

import sys 

import gevent 
from gevent import monkey 

monkey.patch_all() 

import requests 
from requests import async 
import urllib2 

def call_back(resp): 
    content = resp.content 
    title = content.split('<title>')[1].split('</title>')[0].strip() 
    return title 

def worker(url, use_urllib2=False): 
    if use_urllib2: 
     content = urllib2.urlopen(url).read().lower() 
     title = content.split('<title>')[1].split('</title>')[0].strip() 

    else: 
     rs = [async.get(u) for u in url] 
     resps = async.map(rs) 
     for resp in resps: 
      call_back(resp) 

urls = ['http://www.mail.ru']*5 

def by_requests(): 
    worker(urls) 
def by_urllib2(): 
    jobs = [gevent.spawn(worker, url, True) for url in urls] 
    gevent.joinall(jobs) 

if __name__=='__main__': 
    from timeit import Timer 
    t = Timer(stmt="by_requests()", setup="from __main__ import by_requests") 
    print 'by requests: %s seconds'%t.timeit(number=3) 
    t = Timer(stmt="by_urllib2()", setup="from __main__ import by_urllib2") 
    print 'by urllib2: %s seconds'%t.timeit(number=3) 
    sys.exit(0) 

Dưới đây là một trong những kết quả của tôi:

by requests: 2.44117593765 seconds 
by urllib2: 4.41298294067 seconds 
+0

Xin chào! Cảm ơn bạn đã quan tâm đến vấn đề của tôi. Tôi đã thực thi mã của bạn và đã cập nhật hình ảnh của bài đăng đầu tiên để hiển thị cách mã của bạn hoạt động. – user1239798

+0

Đây là kết quả công việc: theo yêu cầu: 25.532893147 giây bởi urllib2: 9.65230888283 giây – user1239798

+0

Tôi sợ rằng tôi không thể sao chép vấn đề của bạn. Tôi nâng cấp gevent lên 0.13.6 và thử nó trên hai máy khác nhau. Nhưng mô-đun 'requests' đã hoạt động không đồng bộ. FYI, tôi đã thử nó trên Ubuntu 11.04 và 11.10. – Phani