2017-05-04 11 views
0

私は2つのグリーンレットを持っています。最初のグリーンレットは7秒間のタイムアウトを開始してから、HTTPリクエストを終了するまでに5秒かかります。 2番目のグリーンレットは完了するまでに10秒かかるいくつかのCPUバウンドタスク(time.sleepでシミュレート)を実行しています。コード:私はこのコードを実行するとgevent:タイムアウト前にI/Oが完了しますが、タイムアウトが発生します。

from gevent import monkey; monkey.patch_socket() 

import time 

import gevent 
import requests 


def f1(): 
    try: 
     with gevent.Timeout(7): 
      print "f1: downloading our page in 5 seconds" 
      requests.get('http://httpbin.org/delay/5') 
    except gevent.Timeout: 
     print "Timed out." 
    else: 
     print "Finished!" 


def f2(): 
    print "f2: being greedy for 10 seconds" 
    time.sleep(10) 


if __name__ == '__main__': 
    g1 = gevent.spawn(f1) 
    g2 = gevent.spawn(f2) 
    gevent.joinall([g1, g2]) 

、タイムアウトが、私はHTTPリクエストが終了しました知っているにもかかわらず、トリガーます:

$ python test.py 
f1: downloading our page in 5 seconds 
f2: being greedy for 10 seconds 
Timed out. 

time.sleepコールが明らかにタイムアウトに責任があるが、私それがどれくらい時間がかかるか実際は気にしないでください。本当に制限したいのは、HTTPリクエストの期間でした。

タイムアウトがHTTP要求が行われていない場合にのみ発生するようにこのコードを書く方法はありますか?タイムアウトイベントの前にI/Oイベントを処理する方法はありますか?

答えて

0

NB - ブロッキングコール(CPUバインド関数のような)は、定義によってグリーンレットに割り当てられません。他のグリーンレットは実行されません。

ブロッキングタスクにはgevent.threadpool.ThreadPool、ノンブロッキングタスクにはグリーンレットのようなネイティブスレッドプールの組み合わせを使用してください。

例コードの動作は、コードがパッチ時間ではなく、すべてのグリーンレットを意味するイベントループ全体をブロックするため、time.sleep(10)がgeventにタイムアウトを引き起こしているためです。

これは期待通りに動作します:

from gevent import monkey 
monkey.patch_all() 

import time 

import gevent 
import requests 


def f1(): 
    try: 
     with gevent.Timeout(7): 
      print "f1: downloading our page in 5 seconds" 
      requests.get('http://httpbin.org/delay/5') 
    except gevent.Timeout: 
     print "Timed out." 
    else: 
     print "Finished!" 


def f2(): 
    print "f2: being greedy for 10 seconds" 
    time.sleep(10) 


if __name__ == '__main__': 
    g1 = gevent.spawn(f1) 
    g2 = gevent.spawn(f2) 
    gevent.joinall([g1, g2]) 

出力:

f1: downloading our page in 5 seconds 
f2: being greedy for 10 seconds 
Finished! 

も時間をパッチ適用を避けるためにgevent.sleepを使用することができます。

+0

私は 'event.sleep'を使用しています。これは、実際にイベントループ全体をブロックするCPUバインドタスクをシミュレートしようとしているためです。しかし、私は、最初のイベントループでこのようなことを行うべきではないかもしれないと思っています。おそらく、 'gevent.threadpool'が意味するものでしょう。 – jobo3208

+0

ブロッキング・タスクは、イベント・ループ全体をブロックするので、グリーンレットに属しません。ブロッキングまたはCPUバウンド関数にはスレッドプールを使用し、ノンブロッキングコールにはグリーンレットを組み合わせて使用​​します。 – danny

関連する問題