如何避免使用gevent阻止python中的代码?

Mar*_*tin 12 python nonblocking gevent

我正在玩gevent,我试图理解为什么我的代码阻塞以及我如何解决它.

我有一个greenlets池,每个都与一个thrift客户端交谈,它从远程thrift服务器收集数据.出于练习的目的,thrift服务器总是采用> 1秒来返回任何数据.当我生成greenlets并运行join时,它们并不是全部并行执行,而是一个接一个地执行.我的理解是,这种情况正在发生,因为我的代码是"阻塞",因为当我运行时monkey.patch_all(),所有的greenlets都会神奇地并行运行.

那么我如何使代码非阻塞自己而不是猴子修补一切而不理解它在做什么?

这里有一个我不明白的例子:

import time

from gevent.pool import Pool

def hello():
    print 'Hello %d' % time.time()
    time.sleep(1) 

def main():
    pool = Pool(5)
    for _ in xrange(5):
        pool.spawn(hello)

    pool.join()

if __name__ == '__main__':
    main()
Run Code Online (Sandbox Code Playgroud)

产量

Hello 1345477112
Hello 1345477113
Hello 1345477114
Hello 1345477115
Hello 1345477116
Run Code Online (Sandbox Code Playgroud)

我知道我可以使用gevent.sleep,但如何使用常规time.sleep使该功能无阻塞?

谢谢

lve*_*lla 16

Greenlets从不并行运行,它们共享相同的进程和相同的线程,因此,它们中最多只有一个一次运行.

Greenlets是绿色的,因为它们是合作例程(来自合作的"co"),因此,甚至不能说它们同时运行,因为你需要协调它们的运行.Gevent在幕后为您完成了大部分工作,并且从libevent(或libev)中了解了哪些greenlet可以运行.根本就没有先发制人.

在您给出的示例中,time.sleep(2)将使进程在操作系统内部进入休眠状态,因此gevent的调度程序将无法运行,并且无法切换到另一个greenlet.

所以,关于你的问题:如果你不想修补现有的代码,你必须手动替换gevent等效的每个阻塞调用,以便gevent可以安排调用greenlet并选择另一个运行.

编辑:关于使用gevent与thrift没有猴子修补所有:我不知道它是否值得.

如果你想修改(fork)thrift的库,只需要更改文件TSocket.py,然后更改:

import socket
Run Code Online (Sandbox Code Playgroud)

至:

from gevent import socket
Run Code Online (Sandbox Code Playgroud)

但是你的thrift库将依赖于gevent,如果你更新了thrift,你将需要重新应用补丁.

您也可以子类化TSocket,更改方法open()以使用gevent的套接字,并使用它代替前者,但对我来说似乎更复杂.

我实际上是使用Thrift和Gevent,为了简单起见,我选择猴子修补整个东西.