如何使用gevent避免在python中阻塞代码?

2024-04-28 14:00:50 发布

您现在位置:Python中文网/ 问答频道 /正文

我在玩gevent,我试图理解为什么我的代码被阻塞,以及如何修复它。

我有一个greenlet池,每个greenlet都与一个从远程精简服务器收集数据的精简客户端进行通信。出于练习的目的,精简服务器总是需要>;1s来返回任何数据。 当我生成greenlet并运行join时,它们并不是并行执行,而是一个接一个地执行。我的理解是,这是因为我的代码是“阻塞”的,因为当我运行monkey.patch_all()时,所有的greenlet神奇地并行运行。

那么,我该如何让代码不阻塞自己,而不是让猴子修补所有东西,不了解它在做什么呢?

我不明白的一个例子:

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()

输出

Hello 1345477112
Hello 1345477113
Hello 1345477114
Hello 1345477115
Hello 1345477116

我知道我可以使用gevent.sleep,但是如何使该功能在正常时间内不被阻塞。sleep?

谢谢


Tags: 数据代码import服务器hellotimemaindef
1条回答
网友
1楼 · 发布于 2024-04-28 14:00:50

greenlet从不并行运行,它们都共享同一个进程和同一个线程,因此,一次最多只能运行其中一个。

greenlet是绿色的,因为它们是共同的例程(“co”来自合作),因此,甚至不能说它们是并发运行的,因为您需要协调它们的运行。Gevent在幕后为您完成大部分工作,并从libevent(或libev)知道greenlet准备运行什么。根本没有先发制人的权利。

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

因此,关于您的问题:如果您不想对现有代码进行monkey修补,则必须手动替换对gevent等价物的每个阻塞调用,以便gevent可以安排取消调用greenlet并选择另一个运行。

编辑:关于节俭使用gevent而不修补所有漏洞:我不知道是否值得。

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

import socket

致:

from gevent import socket

但是,您的节俭库将依赖于gevent,如果您更新了节俭库,则需要重新应用修补程序。

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

我实际上是在用Gevent的节俭,为了简单起见,我选择用monkey修补整个东西。

相关问题 更多 >