使用Gevents异步生成函数

Rah*_*hul 5 python asynchronous gevent

我正在接受Gevents(用于asych功能的python库)并编写了一个非常小的程序来了解它是如何工作的,但结果非常令人费解.以下是代码

import gevent 
import time 


def mytime(t):
    time.sleep(t)
    print " i have slept for ",t,"secs"

x = range (0,10)
x.reverse()

for i in x :
    jobs = [ gevent.spawn(mytime , i) ] 
gevent.joinall(jobs)
Run Code Online (Sandbox Code Playgroud)

无论我跑多少次,我得到的输出

 i have slept for  9 secs
 i have slept for  8 secs
 i have slept for  7 secs
 i have slept for  6 secs
 i have slept for  5 secs
 i have slept for  4 secs
 i have slept for  3 secs
 i have slept for  2 secs
 i have slept for  1 secs
 i have slept for  0 secs
Run Code Online (Sandbox Code Playgroud)

有一个类似的例子,作为gevent 教程的一部分呈现.

异步功能非常明显.我所做的就是在代码中添加一个睡眠功能.输出应该是这样的吗?

     i have slept for  6 secs
     i have slept for  8 secs
     i have slept for  5 secs
     i have slept for  9 secs
     i have slept for  7 secs
     i have slept for  0 secs
     i have slept for  3 secs
     i have slept for  2 secs
     i have slept for  1 secs
     i have slept for  4 secs
Run Code Online (Sandbox Code Playgroud)

Ivo*_*Ivo 9

您对该教程的反应似乎表明您错过了它试图展示的部分内容.

在教程代码的异步部分中,任务以随机顺序完成的主要原因是因为它们已经睡了一段随机时间.

它们仍然在代码的同步部分中随机休眠一段时间,但由于每个任务在前一个任务完成后执行,它们也按顺序完成.

您和异步教程的代码之间的区别在于您睡眠了一段预定的时间,因此您的任务应该以预定的方式完成这段时间.

但是,最后,如果你是观察者,你会发现它们按照你可能期望的相反顺序完成.

为什么是这样?

因为您已将阻止代码插入到示例中.阻止代码是time.sleep().当某些东西被阻塞时,这意味着它已经为自己抓取了所有执行,并且在它完成之前不会让任何其他东西(例如,你的其他greenlet)运行.

由于这是每个函数唯一的"工作",它可以使代码再次同步.

在编写这些类型的程序时,您希望尽可能使阻塞代码不存在.您必须意识到可能始终编写可能阻塞的代码,并且您通常希望尽可能经常地找到非阻塞替代方案.

Gevent提供了非阻塞版本time.sleep()- gevent.sleep().您将注意到教程代码使用的内容.你也能够修补那个功能.目前,您通常更喜欢使用gevent的版本.

查看monkey_patch修补程序列表,应该为您提供一个很好但非详尽的概述,通常会阻止正常事物的类型.

编辑:您的作业创建循环中也有不正确的逻辑.

更好的是 -

jobs = []
for i in x:
    jobs.append(gevent.spawn(mytime, i))
Run Code Online (Sandbox Code Playgroud)

或者更简单地说,只是:

jobs = [gevent.spawn(mytime, i) for i in x]
Run Code Online (Sandbox Code Playgroud)