Python 使用Gevents异步生成函数

Python 使用Gevents异步生成函数,python,asynchronous,gevent,Python,Asynchronous,Gevent,我当时正在经历Gevents(PythonLibraryforAsych功能),并编写了一个非常小的程序来理解它是如何工作的,但结果相当令人困惑。 下面是代码 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.spa

我当时正在经历Gevents(PythonLibraryforAsych功能),并编写了一个非常小的程序来理解它是如何工作的,但结果相当令人困惑。 下面是代码

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)
输出无论我运行多少次,我都会得到

 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
有一个类似的示例,作为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

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

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

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

您的代码和异步教程的代码之间的区别在于,您的睡眠时间是预先确定的,因此您的任务应该在以后以预先确定的方式完成

然而,最后,如果你善于观察,你会注意到它们的结束顺序与你期望的相反

为什么会这样

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

由于这是每个函数所做的唯一“工作”,因此它会使代码再次同步

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

Gevent提供了非阻塞版本的
time.sleep()
-
Gevent.sleep()
。您会注意到这就是教程代码所使用的。您也可以使用该功能。 目前,您通常更喜欢使用gevent的版本

查看
monkey\u patch
patch的内容列表,应该可以让您对通常阻塞的正常内容的类型有一个很好的、但并非详尽的概述

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

更好的是-

jobs = []
for i in x:
    jobs.append(gevent.spawn(mytime, i))
或者更简单地说,就是:

jobs = [gevent.spawn(mytime, i) for i in x]

您应该在此处使用
gevent.sleep()
而不是
time.sleep()
来获得正确的输出:

import gevent

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

jobs = [gevent.spawn(mytime, i) for i in reversed(range(10))]
gevent.joinall(jobs)
输出 越大的
i
越晚的
mytime(i)
产生输出,而不管
mytime(i)
的生成顺序如何

如果先对其进行monkeypatch,则可以使用
time.sleep()

import gevent.monkey
gevent.monkey.patch_time()

import time
import gevent.monkey
gevent.monkey.patch_time()

import time