问题 何时在Gevent中使用Threadpool


我注意到Gevent有线程池对象。 有人可以向我解释何时使用threadpool以及何时使用常规池?什么是gevent.threadpool和gevent.pool之间的区别?


2928
2017-08-23 20:19


起源



答案:


如果你有一段python代码需要很长时间才能运行(秒)并且不会导致greenlets的转换。 (没有网络)所有其他greenlets / gevent工作将'饿死'并且没有计算时间,它看起来像你的应用程序'挂起'。

如果你把这个'重'任务放在Threadpool中,那么线程执行将确保其他greenlet不会饿死。但我相信如果你的代码在c库中花费了很多时间,那么它将没有任何效果。

以下是来自的例子 gevent例子。请注意,该示例使用time.sleep来阻止而不是gevent.sleep。

小费: 如果你有一个循环需要很长时间才能运行,你可以在循环中放入gevent.sleep(0)。每个循环其他greenlets将有机会运行。该 GEVENT缓慢循环中的.sleep(0)将确保其他greenlet不会饿死,应用程序显示响应

import time
import gevent
from gevent.threadpool import ThreadPool


pool = ThreadPool(3)
start = time.time()
for _ in xrange(4):
    pool.spawn(time.sleep, 1)
gevent.wait()
delay = time.time() - start
print 'Running "time.sleep(1)" 4 times with 3 threads. Should take about 2 seconds: %.3fs' % delay

9
2017-10-03 08:00



“但我相信,如果你的代码在c库中花费了很多时间,它将没有任何效果”你确定吗?你指的是C扩展还是 ctypes?因为如果您释放GIL(手动在C扩展中或自动为 ctypes 那么应用程序将受益于ThreadPool,不是吗? - MariusSiuram
是。 “如果你完全释放GIL”。我没有时间从每个C库中找到它...... - Stephan


答案:


如果你有一段python代码需要很长时间才能运行(秒)并且不会导致greenlets的转换。 (没有网络)所有其他greenlets / gevent工作将'饿死'并且没有计算时间,它看起来像你的应用程序'挂起'。

如果你把这个'重'任务放在Threadpool中,那么线程执行将确保其他greenlet不会饿死。但我相信如果你的代码在c库中花费了很多时间,那么它将没有任何效果。

以下是来自的例子 gevent例子。请注意,该示例使用time.sleep来阻止而不是gevent.sleep。

小费: 如果你有一个循环需要很长时间才能运行,你可以在循环中放入gevent.sleep(0)。每个循环其他greenlets将有机会运行。该 GEVENT缓慢循环中的.sleep(0)将确保其他greenlet不会饿死,应用程序显示响应

import time
import gevent
from gevent.threadpool import ThreadPool


pool = ThreadPool(3)
start = time.time()
for _ in xrange(4):
    pool.spawn(time.sleep, 1)
gevent.wait()
delay = time.time() - start
print 'Running "time.sleep(1)" 4 times with 3 threads. Should take about 2 seconds: %.3fs' % delay

9
2017-10-03 08:00



“但我相信,如果你的代码在c库中花费了很多时间,它将没有任何效果”你确定吗?你指的是C扩展还是 ctypes?因为如果您释放GIL(手动在C扩展中或自动为 ctypes 那么应用程序将受益于ThreadPool,不是吗? - MariusSiuram
是。 “如果你完全释放GIL”。我没有时间从每个C库中找到它...... - Stephan