私は 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)
_
だから私はスレッドにパッチを当てていません。
スレッドが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'
たとえば、次のようにThread
をGreenlet
に置き換えると、スレッドベースのクラスをそのままにしておくことができます。
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):
...
その場合、希望どおりに機能します。