使用gevent猴子补丁与线程使线程串行工作

26 投票
2 回答
28836 浏览
提问于 2025-04-17 12:34

我正在使用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 个回答

0

如果你把代码中的 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):
    ...

这样的话,它就会按照你的想法正常工作了。

33

当在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'

撰写回答