Использование патча Gevent Monkey с многопоточностью заставляет поток работать последовательно - PullRequest
20 голосов
/ 08 февраля 2012

Я использую 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(), он будет работать нормально.
Проблема в том, что мне нужен monkey.patch_all() для использования gevent (теперь показано в коде выше)

Мое решение:

Я изменил

monkey.patch_all() 

до

monkey.patch_all(thread=False)

поэтому я не исправляю нить.

Ответы [ 2 ]

25 голосов
/ 08 февраля 2012

Когда потоки пропатчены обезьянами в 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'
0 голосов
/ 08 июня 2018

Вы можете оставить свой класс на основе потоков на месте, если вы замените 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):
    ...

тогда он будет работать так, как вы хотите.

...