5

私はGevents(asych機能用のPythonライブラリ)を実行していて、それがどのように機能するかを理解するために非常に小さなプログラムを作成しましたが、結果は非常に困惑しました。以下はコードです

import gevent 
import time 


def mytime(t):
    time.sleep(t)
    print " i have slept for ",t,"secs"

x = range (0,10)
x.reverse()

for i in x :
    jobs = [ gevent.spawn(mytime , i) ] 
gevent.joinall(jobs)

何度実行しても出力は得られます

 i have slept for  9 secs
 i have slept for  8 secs
 i have slept for  7 secs
 i have slept for  6 secs
 i have slept for  5 secs
 i have slept for  4 secs
 i have slept for  3 secs
 i have slept for  2 secs
 i have slept for  1 secs
 i have slept for  0 secs

geventチュートリアルの一部として提示された同様の例があります。

非同期機能はかなり明白です。私が行ったのは、コードにスリープ機能を追加することだけです。出力はこのようなものであってはなりませんか?

     i have slept for  6 secs
     i have slept for  8 secs
     i have slept for  5 secs
     i have slept for  9 secs
     i have slept for  7 secs
     i have slept for  0 secs
     i have slept for  3 secs
     i have slept for  2 secs
     i have slept for  1 secs
     i have slept for  4 secs
4

2 に答える 2

9

チュートリアルに対するあなたの反応は、あなたが示そうとしているものの一部を見逃していることを示しているようです.

チュートリアルのコードの非同期部分で、タスクがランダムな順序で終了する主な理由は、タスクがランダムな期間スリープしたためです。

コードの同期部分ではランダムな期間スリープしますが、各タスクは前のタスクが終了した後に実行されるため、タスクもその順序で終了します

あなたのコードと非同期チュートリアルのコードの違いは、あらかじめ決められた時間スリープするため、タスクはその時間後に、あらかじめ決められた方法で終了する必要があることです。

最後に、注意深い人であれば、予想とは逆の順序で終了していることに気付くでしょう。

どうしてこれなの?

例にブロッキングコードを挿入したためです。ブロッキング コードはtime.sleep(). 何かがブロックされている場合、それはそれ自体のすべての実行を取得しており、それが完了するまで他のもの (たとえば、他の greenlet) を実行させないことを意味します。

これは各関数が行う唯一の「作業」であるため、コードを再び同期させる効果があります。

この種のプログラムを作成する際には、ブロッキング コードをできるだけ存在させないようにする必要があります。常にブロックする可能性のあるコードを書くことに注意する必要があり、通常はできるだけ頻繁に非ブロックの代替案を見つけたいと考えています。

time.sleep()Gevent は-のノンブロッキング バージョンを提供しますgevent.sleep()。それがチュートリアル コードで使用されていることに注意してください。また、その機能にモンキー パッチを適用することもできます。今のところ、通常は gevent のバージョンを使用することをお勧めします。

パッチを適用するもののリストを見ると、monkey_patch通常はブロックしている通常のものの種類について、網羅的ではありませんが、優れた概要が得られるはずです。

編集:ジョブ作成ループにも誤ったロジックがあります。

より良いのは-

jobs = []
for i in x:
    jobs.append(gevent.spawn(mytime, i))

またはもっと簡単に、単に:

jobs = [gevent.spawn(mytime, i) for i in x]
于 2012-02-07T15:10:44.497 に答える
4

正しい出力を得るには、ここgevent.sleep()の代わりに使用する必要があります。time.sleep()

import gevent

def mytime(t):
    gevent.sleep(t) #NOTE: not time.sleep()
    print " i have slept for ",t,"secs"

jobs = [gevent.spawn(mytime, i) for i in reversed(range(10))]
gevent.joinall(jobs)

出力

 i have slept for  0 secs
 i have slept for  1 secs
 i have slept for  2 secs
 i have slept for  3 secs
 i have slept for  4 secs
 i have slept for  5 secs
 i have slept for  6 secs
 i have slept for  7 secs
 i have slept for  8 secs
 i have slept for  9 secs

大きいほど、生成される順序に関係なくi、後でmytime(i)出力mytime(i)が生成されます。

time.sleep()最初にモンキーパッチを適用すると、次のように使用できます。

import gevent.monkey
gevent.monkey.patch_time()

import time
于 2012-02-07T15:17:18.863 に答える