web-dev-qa-db-ja.com

スレッドでgeventモンキーパッチを使用すると、スレッドが連続して機能します

私は gevent を使用しており、すべてにモンキーパッチを適用しています。
モンキーパッチにより、スレッドが連続して機能するようです。

私のコード:

_import threading
from gevent import monkey; monkey.patch_all()

class ExampleThread(threading.Thread):
    def run(self):
        do_stuff()  # takes a few minutes to finish
        print 'finished working'

if __name__ == '__main__':
    worker = ExampleThread()
    worker.start()
    print 'this should be printed before the worker finished'
_

そのため、スレッドは期待どおりに機能していません。
しかし、monkey.patch_all()を削除すると、正常に機能しています。
問題は、geventを使用するためにmonkey.patch_all()が必要なことです(上記のコードに示されています)

私の解決策:

私は変更しました

_monkey.patch_all() 
_

_monkey.patch_all(thread=False)
_

だから私はスレッドにパッチを当てていません。

22
yossi

スレッドがgeventでモンキーパッチを適用されると、コルーチンとして動作します。これは、他のコルーチンが実行できるようにするには、明示的に制御を譲る必要があることを意味します。

これを行う方法は、パッチが適用されたブロッキング操作を呼び出すことです(これにより自動的に生成されます)または gevent.sleep

#!/usr/bin/env python
from gevent import monkey, sleep
monkey.patch_all()
import threading

class ExampleThread(threading.Thread):
    def run(self):
        for i in xrange(10):
            print 'working'
            sleep()

if __name__ == '__main__':
    worker = ExampleThread()
    worker.start()
    print 'this will be printed after the first call to sleep'
27
jcollado

たとえば、次のようにThreadGreenletに置き換えると、スレッドベースのクラスをそのままにしておくことができます。

from gevent import monkey
from gevent import Greenlet
from threading import Thread


class ThreadLikeGreenlet(Greenlet):
    def __init__(self, name=None, target=None, args=(), kwargs=()):
        super().__init__(target, *args, **dict(kwargs))
        self.name = name

def is_gevent_patched():
    return monkey.is_module_patched('threading')

if is_gevent_patched():
    Thread = ThreadLikeGreenlet  # substitute Thread with Greenlet

class ExampleThread(Thread):
    ...

その場合、希望どおりに機能します。

0
Bob