0

ほら、人々。gevent.poolクラスとpool.wait_available()メソッドについて質問があります。どちらもコードスニペットです。

1.1。

def fetch(url):
    print 'start fetching...', url
    data = urllib2.urlopen(url)
    print url,':',data.code

urls = ['http://www.google.ru', 'http://www.s-str.ru', 'http://www.vk.com', 'http://www.yandex.ru', 'http://www.xxx.com']

pool = Pool(2)

def producer():
    for url in urls:
        pool.spawn(fetch, url)
    pool.join()

p = gevent.spawn(producer)
p.join()

2.2。

def fetch(url):
    print 'start fetching...', url
    data = urllib2.urlopen(url)
    print url,':',data.code

urls = ['http://www.google.ru', 'http://www.s-str.ru', 'http://www.vk.com', 'http://www.yandex.ru', 'http://www.xxx.com']

pool = Pool(2)

def producer():
    for url in urls:
        pool.wait_available()
        pool.spawn(fetch, url)
    pool.join()

p = gevent.spawn(producer)
p.join()

同様の結果が得られます:

start fetching... http://www.google.ru
start fetching... http://www.s-str.ru
http://www.google.ru : 200
start fetching... http://www.vk.com
http://www.s-str.ru : 200
start fetching... http://www.yandex.ru
http://www.yandex.ru : 200
start fetching... http://www.xxx.com
http://www.vk.com : 200
http://www.xxx.com : 200

誰かがwait_available()メソッドの意味を説明できますか?そしてそれの使用法の可能なケース。

======= update ========私はすでにそれをサルパスしました、それは正しく動作します、私が知りたいのはこれらの2つのコードスニペットの違いです。

4

2 に答える 2

2

TL;DR :wait_available両方の方法で同じチェックが実行されるため、spawn を使用している場合は必要ありません。ただし、使用apply_asyncしていて、プールの上限を超えるスレッドを送信したくない場合は、wait_available最初に呼び出す必要があります。


おそらくもう少し明確な説明のために.. geventのPoolクラスで同じことを達成する方法がいくつかあります。プールで使用すると、新しい greenlet を実行するためspawnのスペースが利用可能になるまでブロックされます。Pool簡単な例を次に示します。

import gevent.monkey
gevent.monkey.patch_all()
import gevent.pool
import time

def my_slow_function():
    time.sleep(5)

def log(text):
    print '%d : %s' % (int(time.time()), text)

if __name__ == '__main__':
    thread_pool = gevent.pool.Pool(5)
    for i in xrange(20):
        log('Submitting slow func %d' % i)
        thread_pool.spawn(my_slow_function)
    thread_pool.join()
    log('Exiting')

この出力は、プールに 5 つの greenlet 用のスペースがあるため、これらが 5 つのグループで生成されることを示しています。

1403037287:スローファン
の提出0 1403037287:遅いFUNCの提出1 1403037287
:遅いFUNCの提出2 1403037287
:スロー ファン の提出3
1403037287遅いFUNCの提出8 1403037292:遅いFUNC の提出9 1403037297:遅い FUNCの提出10 1403037297:遅い FUNCの提出11 1403037297:スロー ファン の提出12 1403037297











1403037302 : 低速関数 16
を送信中 1403037302 : 低速関数 17
を送信中 1403037302 : 低速関数 18
を送信中 1403037302 : 低速関数 19
を送信中 1403037307 : 終了

ご覧のとおり、それらは約 5 秒間隔で 5 つのグループでスポーンされます。gevent コードを掘り下げて Pool オブジェクトを見ると、実行中の greenlet を追跡するために使用される s 内部セマフォで呼び出しspawnがロックを要求することがわかります。Pool

apply_async逆に、の代わりに を使用してこの同じコードを試すとspawn、すべての呼び出しが同時に実行されます。

1403037313:遅いFUNC
の提出0 1403037313:遅いFUNC
の提出1 1403037313:遅い
FUNCの提出2 1403037313:スローファンの提出3 1403037313
:スロー ファン の提出4
1403037313遅いFUNCの提出8 1403037313:スローファン の提出9 1403037313:遅い FUNCの提出10 1403037313:遅い FUNCの提出11 1403037313:スロー ファン の提出12 1403037313










1403037313 : 低速関数 16
を送信中 1403037313 : 低速関数 17
を送信中 1403037313 : 低速関数 18
を送信中 1403037313 : 低速関数 19
を送信中 1403037318 : 終了

ここでは、ブロックや待機がなく、すべて同時に押し込まれていることがわかります。ただし、 for ループの先頭で a をスローするwait_available()と、 と同様の動作に戻りますspawn

1403038292:遅いFUNC
の提出0 1403038292:遅いFUNC
の提出1 1403038292:遅いFUNCの送信2
1403038292:スローファンの提出3
1403038292:スローファンの提出4
1403038297の 提出
スロー ファン遅いFUNCの提出8 1403038297:スローファン の提出9 1403038302:遅い FUNCの提出10 1403038302:スロー FUNCの提出11 1403038302:スロー FUNCの提出12 1403038302:スロー FANC の提出









1403038307 : 低速関数 16
を送信中 1403038307 : 低速関数 17
を送信中 1403038307 : 低速関数 18
を送信中 1403038307 : 低速関数 19
を送信中 1403038312 : 終了

もう一度、gevent のソースを見ると、wait_availableを呼び出した結果と同じチェックが行われspawnます。これは、セマフォをチェックして、プールに実際に余裕があるかどうかを確認します。

于 2014-06-17T21:00:42.100 に答える
0

作業するgevent前に、標準モジュールにパッチを適用する必要があります。

>>> import gevent.monkey
>>> gevent.monkey.patch_all()
>>> ...
>>> p = gevent.spawn(producer)
>>> p.join()
start fetching... http://www.google.ru
start fetching... http://www.s-str.ru
http://www.google.ru : 200
start fetching... http://www.vk.com
http://www.vk.com : 200
start fetching... http://www.yandex.ru
http://www.yandex.ru : 200
start fetching... http://www.xxx.com
http://www.xxx.com : 200
http://www.s-str.ru : 200

ご覧のとおり、これpool.wait_available()は予測可能です。

アップデート

Pool関数に対してのみ同じようにspawn機能します(プールで利用可能な「スロット」を待ちます)。状態に基づいて他の機能Pool(ロギング、トレース、監視) を提供する必要がある場合は、間違いなくなどwait_availableの関数を使用します。新しいグリーン スレッドfree_countのみが必要な場合は、実装spawnに頼ることができます。Pool

于 2012-12-17T09:47:18.690 に答える