玩转python(6)协程

多任务系统一般都需要解决一个问题:多个任务如何调度。抢占式调度就是一种很常见的任务调度机制。以单核模式下的进程调度为例,一个进程处于运行状态,其他的处于就绪队列,等到当前运行的进程放弃CPU的使用权,系统将CPU立刻分配给新到达的进程,由于任务的执行顺序是不确定的,看上去就像一堆任务在竞争CPU的使用权,所以这种多任务运行方式叫做“多任务竞争”。与之对应的是非抢占式调度。当前任务会持续执行下去直到因为某些原因主动放弃CPU的使用权,各个任务的执行顺序是确定的,就像在互相协作,所以这种多任务运行方式也叫做“多任务协作”。协程就是一种典型的多任务协作解决方案。协程是指一个过程,这个过程与调用方协作,产出由调用方提供的值。它的运行流程大致如下:

  1. 协程A开始执行。
  2. 协程A执行到某一步,暂停执行,执行权转移到协程B。
  3. 协程B执行一段时间后交还执行权。
  4. 协程A恢复执行。

那么生成器是如何与协程扯上关系的呢?在一个生成器中,yield item这行代码会产出一个值,提供给next()的调用方;此外,还会作出让步,暂停执行生成器,让调用方继续工作,直到需要使用另一个值时再调用next()。调用方会从生成器中拉取值。如果只能产出值,生成器显然用处不大。在python2.5之后的版本中,生成器API 中增加了send()方法。生成器的调用方可以使用send()方法发送数据,发送的数据会成为生成器函数中yield表达式的值。这样生成器既能接收数据,又能产出数据,可以作为协程使用。下面是一个简单的协程实例:

def fun():
    r = ‘‘
    while True:
        n = yield r
        if not n:
            return
        print(‘fun test %s...‘ % n)
        r = ‘200 OK‘

协程在执行到n = yield r这个表达式时,首先输出r,然后将接收到的数据赋给n。然后向下执行直到遇到下一个yield语句,循环往复。接下来我们来看看这个协程是怎么工作的~

c = fun()
next(c)
c.send(‘1‘)

测试结果如下:

input:1

尽管fun()中有一个死循环,但是遇到yield,协程就会让出执行权。而且协程有个亮点,它没有涉及到上下文切换,所有的过程都是在用户空间进行的,协程的创建开销也很小,所以完全没有创建线程时的各种考虑。因此如果有多个任务,并且我们知道如何安排任务协作的情况下,协程无疑是一个好选择。

原文地址:https://www.cnblogs.com/bugsheep/p/9117688.html

时间: 2024-11-07 23:05:28

玩转python(6)协程的相关文章

深入理解Python中协程的应用机制: 使用纯Python来实现一个操作系统吧!!

本文参考:http://www.dabeaz.com/coroutines/   作者:David Beazley 缘起: 本人最近在学习python的协程.偶然发现了David Beazley的coroutine课程,花了几天时间读完后,为了加深理解就把其中个人认为最为精华的部分摘下来并加上个人理解写了本篇博客. 扯一些淡: 既然要搞一个操作系统,那我们就先来设一个目标吧!就像找女朋友,我们不可能随随便便的是个女的就上,肯定要对女方有一定的要求,比如肤白貌美气质佳…… 所以,我们对这个' 姑娘

python gevent 协程

简介 没有切换开销.因为子程序切换不是线程切换,而是由程序自身控制,没有线程切换的开销,因此执行效率高, 不需要锁机制.因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多 Python对协程的支持还非常有限,用在generator中的yield可以一定程度上实现协程. yield 传统的生产者-消费者模型是一个线程写消息,一个线程取消息,通过锁机制控制队列和等待,但一不小心就可能死锁. 如果改用协程,生产者生产消息后,直接通过y

python中协程

协程是python中除了进程和线程之外又一种能够实现多任务的方式,又称为微线程,纤程,它相比于线程需要的资源更少. 在python种协程是通过generator实现的.通过yield保存当前运行的状态然后切换到另一个协程执行.普通的生产者-消费这模式是一个线程写消息,一个线程才能读取消息,因此需要控制队列的写入与读取数据.而改用协程可以在生产者生产消息后直接通过yield跳转到消费者开始执行,执行完毕后在切换到生产者,如此反复,效率极高. 在图中,我们可以看出通过next的方法使得生成器中的任务

【Python】协程

协程,又称微线程,纤程.英文名Coroutine. 协程的概念很早就提出来了,但直到最近几年才在某些语言(如Lua)中得到广泛应用. 子程序,或者称为函数,在所有语言中都是层级调用,比如A调用B,B在执行过程中又调用了C,C执行完毕返回,B执行完毕返回,最后是A执行完毕. 所以子程序调用是通过栈实现的,一个线程就是执行一个子程序. 子程序调用总是一个入口,一次返回,调用顺序是明确的.而协程的调用和子程序不同. 协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,在适当

Python之协程函数

Python之协程函数 什么是协程函数:如果一个函数内部yield的使用方法是表达式形式的话,如x=yield,那么该函数成为协程函数. def eater(name): print('%s start to eat food' %name) food_list=[] while True: food=yield food_list print('%s get %s ,to start eat' %(name,food)) food_list.append(food) print('done')

关于Python的协程问题总结

协程其实就是可以由程序自主控制的线程 在python里主要由yield 和yield from 控制,可以通过生成者消费者例子来理解协程 利用yield from 向生成器(协程)传送数据# 传统的生产者-消费者是一个线程写消息,一个线程取消息,通过锁机制控制队列和等待,但一不小心就可能死锁.# 如果改用协程,生产者生产消息后,直接通过yield跳转到消费者开始执行,待消费者执行完毕后,换回生产者继续生产,效率极高 def consumer(): r = '' while True: n = y

Python与协程从Python2—Python3

协程,又称微线程.纤程,英文名Coroutine:用一句话说明什么是线程的话:协程是一种用户态的轻量级线程. Python对于协程的支持在python2中还比较简单,但是也有可以使用的第三方库,在python3中开始全面支持,也成为python3的一个核心功能,很值得学习. 协程介绍 协程,又称微线程.纤程,英文名Coroutine:用一句话说明什么是线程的话:协程是一种用户态的轻量级线程. 协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先

玩转python(7)python多协程,多线程的比较

前段时间在做一个项目,项目本身没什么难度,只是数据存在一个数据接口服务商那儿,这就意味着,前端获取数据需要至少两次http请求,第一次是前端到后端的请求,第二次是后端到数据接口的请求.有时,后端接收到前端的一次请求后,可能需要对多个接口进行请求,按照传统串行执行请求的方法,用户体验肯定是非常糟糕了,而且对计算资源也是极大的浪费,正好前段时间学习了协程和线程的知识,所以我花了一些时间,对几种可行方案进行了测试对比.一开始我使用真正的网络io进行测试,发现这种方法受网络环境影响比较大,为了公平起见,

python之协程与IO操作

协程 协程,又称微线程,纤程.英文名Coroutine. 协程的概念很早就提出来了,但直到最近几年才在某些语言(如Lua)中得到广泛应用. 子程序,或者称为函数,在所有语言中都是层级调用,比如A调用B,B在执行过程中又调用了C,C执行完毕返回,B执行完毕返回,最后是A执行完毕. 所以子程序调用是通过栈实现的,一个线程就是执行一个子程序. 子程序调用总是一个入口,一次返回,调用顺序是明确的.而协程的调用和子程序不同. 协程看上去也是子程序,但执行过程中,在子程序内部可中断,然后转而执行别的子程序,

Python之协程的实现

1.Python里面一般用gevent实现协程协程, 而协程就是在等待的时候切换去做别的操作,相当于将一个线程分块,充分利用资源 (1)低级版协程的实现 import gevent def test1(): print(1,2) gevent.sleep(0)#执行到这里的时候切换去函数test2 print(3,4) def test2(): print(5,6) gevent.sleep(0) print(7,8) gevent.joinall( [gevent.spawn(test1),g