19

このコードの場合:

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)

この結果:

by requests: 18.3397213892 seconds
by urllib2: 2.48605842363 seconds

スニファーでは、次のようになります。

説明: 最初の 5 つのリクエストは requests ライブラリによって送信され、次の 5 つのリクエストは urllib2 ライブラリによって送信されます。赤 - 作業がフリーズしたとき、暗い - データを受信したとき... えっ!?

ソケットライブラリにパッチが適用され、ライブラリが同じように動作する必要がある場合、どのように可能ですか? 非同期作業に requests.async なしでリクエストを使用するにはどうすればよいですか?

4

5 に答える 5

17

申し訳ありませんが、ケネス・ライツ。彼の図書館は素晴らしいです。

私は愚かだ。次のようにhttplibのモンキーパッチを選択する必要があります。

gevent.monkey.patch_all(httplib=True)

httplibのパッチはデフォルトで無効になっているためです。

于 2012-03-05T08:45:28.867 に答える
7

Kenneth が指摘したように、requestsモジュールに非同期部分を処理させることもできます。それに応じてコードを変更しました。繰り返しますが、私にとっては、結果は一貫してそのrequestsモジュールのパフォーマンスがより優れていることを示していますurllib2

これを行うことは、コールバック部分を「スレッド化」できないことを意味します。ただし、リクエスト/レスポンスの遅延により、HTTP リクエストでのみ大きな効果が期待できるため、問題はありません。

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)

これが私の結果の1つです:

by requests: 2.44117593765 seconds
by urllib2: 4.41298294067 seconds
于 2012-03-01T23:00:02.617 に答える
5

Requests には、コードベースに統合された gevent サポートがあります。

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

于 2012-03-01T19:44:33.070 に答える
2

あなたのコードを自分のマシン ( python 2.7.1gevent 0.13.0requests 0.10.6) で実行しました。requests モジュールを使用すると、常に 1 秒か 2 秒速くなることがわかりました。どのバージョンを使用していますか? アップグレードするだけで問題が解決する場合があります。

by requests: 3.7847161293 seconds
by urllib2: 4.92611193657 seconds

by requests: 2.90777993202 seconds
by urllib2: 7.99798607826 seconds
于 2012-03-01T17:58:36.427 に答える