python学习笔记 协程

在学习异步IO模型前,先来了解协程

协程又叫做微线程,Coroutine

子程序或者成为函数,在所有语言中都是层级调用,比如a调用b,b调用c。c执行完毕返回,b执行完毕返回,最后a执行完毕返回

所以子程序是通过栈来实现的,一个线程就是执行一个子程序

子程序调用总是一个入口一次返回,调用顺序是明确的,而协程的调用和子程序是不同的。

协程看上去是子程序,但在执行过程中可以在子程序内部中断,转而执行别的子程序,在适当的时候返回执行

注意在一个子程序中断去执行其他子程序不是函数调用,类似于CPU的中断,比如子程序A,B

def A():
    print(‘1‘)
    print(‘2‘)
    print(‘3‘)

def B():
    print(‘x‘)
    print(‘y‘)
    print(‘z‘)

假设由协程执行,在执行A的过程中,可以随时中断,去执行B,B也可能在执行过程中中断再去执行A,结果可能是:

1
2
x
y
3
z

但是在A中是没有调用B的,所以协程的调用比函数理解要难一些

看起来A,B的执行像是多线程,但协程的特点是在于一个线程执行,和多线程相比,有什么优势

最大的优势就是协程极高的执行效率。因为子程序切换不是线程切换,而是由程序自身来控制,因此没有现成切换的开销,线程数量越多协程性能优势越明显

第二个优势就是不需要多线程的锁机制,因为只有一个线程,也不存在写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,

所以执行效率比多线程高很多

因为协程是一个县城执行,那么利用多核CPU你,最简单的办法就是多进程+协程,即充分利用多核,又充分发挥协程的高效率,获得极高的性能,

python多协程的支持是通过generator实现的。

在generator中,我们不但可以通过for循环来迭代,还可以不断调用next()获取yield语句返回的下一个值

但是python的yield不但可以返回一个值,它还可以接受调用者发出的参数

来看例子:

传统的生产者消费者模型是一个线程写消息一个线程取消息,通过锁机制控制队列和等待,但一不小心就可能死锁

如果改用协程,生产者生产消息后,直接通过yield跳转到消费者跳转到消费者开始执行,贷消费者执行完毕后,切换生产者继续生产,效率极高

def consumer():
    r = ‘‘
    while True:
        n = yield r
        if not n:
            return
        print(‘[CONSUMER] Consuming %s...‘ % n)
        r = ‘200 OK‘

def produce(c):
    c.send(None)
    n = 0
    while n < 5:
        n = n + 1
        print(‘[PRODUCER] Producing %s...‘ % n)
        r = c.send(n)
        print(‘[PRODUCER] Consumer return: %s‘ % r)
    c.close()

c = consumer()
produce(c)
[PRODUCER] Producing 1...
[CONSUMER] Consuming 1...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 2...
[CONSUMER] Consuming 2...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 3...
[CONSUMER] Consuming 3...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 4...
[CONSUMER] Consuming 4...
[PRODUCER] Consumer return: 200 OK
[PRODUCER] Producing 5...
[CONSUMER] Consuming 5...
[PRODUCER] Consumer return: 200 OK

n = yield r 并不是赋值语句,相当于:

if produce return n
if consume return r

如果是produce调用send的话,就相当于在consumer中为n赋值 如果是consume调用yield r的话,就相当于在produce中为r赋值

c.send(None) 用于启动一个生成器,如果参数不传None的话会报错。 但是也只用于启动生成器,并不会调用yield 也就是说,当执行send(None) 从produce转到consume时,只执行到yield r的上一句


注意到consumer函数是一个generator,把一个consumer传入produce后:

  1. 首先调用c.send(None)启动生成器;
  2. 然后,一旦生产了东西,通过c.send(n)切换到consumer执行;
  3. consumer通过yield拿到消息,处理,又通过yield把结果传回;
  4. produce拿到consumer处理的结果,继续生产下一条消息;
  5. produce决定不生产了,通过c.close()关闭consumer,整个过程结束。

整个流程无锁,由一个线程执行,produceconsumer协作完成任务,所以称为“协程”,而非线程的抢占式多任务。

最后套用Donald Knuth的一句话总结协程的特点:

“子程序就是协程的一种特例。”

时间: 2024-10-14 09:36:39

python学习笔记 协程的相关文章

Python 学习笔记 - 协程

Python里面控制并发,除了多线程和多进程,还可以使用协程(CoRoutine).他是在一个线程内通过程序员人为的指定来进行切换 例1:通过switch()可以人为来回切换到另外一个函数:当所有函数执行完毕,最后输出print(10) #!/usr/bin/env python # -*- coding:utf-8 -*- # Author:Alex Li from greenlet import greenlet def test1():     print(12)     gr2.swit

python学习笔记-(十四)进程&amp;协程

一. 进程 1. 多进程multiprocessing multiprocessing包是Python中的多进程管理包,是一个跨平台版本的多进程模块.与threading.Thread类似,它可以利用multiprocessing.Process对象来创建一个进程.该进程可以运行在Python程序内部编写的函数.该Process对象与Thread对象的用法类似. 创建一个Process实例,可用start()方法启动. join()方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步.

Python学习笔记基础篇——总览

Python初识与简介[开篇] Python学习笔记——基础篇[第一周]——变量与赋值.用户交互.条件判断.循环控制.数据类型.文本操作 Python学习笔记——基础篇[第二周]——解释器.字符串.列表.字典.主文件判断.对象 Python学习笔记——基础篇1[第三周]——set集合 Python学习笔记——基础篇2[第三周]——计数器.有序字典.元组.单(双)向队列.深浅拷贝.函数.装饰器 Python学习笔记——基础篇[第四周]——迭代器&生成器.装饰器.递归.算法.正则表达式 Python

Python学习笔记进阶篇——总览

Python学习笔记——进阶篇[第八周]———进程.线程.协程篇(Socket编程进阶&多线程.多进程) Python学习笔记——进阶篇[第八周]———进程.线程.协程篇(异常处理) Python学习笔记——进阶篇[第八周]———进程.线程.协程篇(多线程与进程池) Python学习笔记——进阶篇[第九周]———线程.进程.协程篇(队列Queue和生产者消费者模型) Python学习笔记——进阶篇[第九周]———协程 Python学习笔记——进阶篇[第九周]———MYSQL操作

OpenCV之Python学习笔记

OpenCV之Python学习笔记 直都在用Python+OpenCV做一些算法的原型.本来想留下发布一些文章的,可是整理一下就有点无奈了,都是写零散不成系统的小片段.现在看 到一本国外的新书<OpenCV Computer Vision with Python>,于是就看一遍,顺便把自己掌握的东西整合一下,写成学习笔记了.更需要的朋友参考. 阅读须知: 本文不是纯粹的译文,只是比较贴近原文的笔记:         请设法购买到出版社出版的书,支持正版. 从书名就能看出来本书是介绍在Pytho

python学习笔记12-模块使用

python学习笔记12-模块使用 模块os,sys 什么是模块? 模块os,sys 模块是Python组织代码的一种基本方式 一个Python脚本可以单独运行,也可以导入到另外一个脚本运行,用import hello语句来导入,不用加入.py 什么是Python的 包? Python的模块可以按照目录组织为包 创建一个包的步骤: 创建一个名字为包名的目录 在改目录下创建一个__init__.py文件 根据需要,在该目录下存放脚本文件或已编译的扩展及子包 import pack.m1,pack.

python学习笔记2—python文件类型、变量、数值、字符串、元组、列表、字典

python学习笔记2--python文件类型.变量.数值.字符串.元组.列表.字典 一.Python文件类型 1.源代码 python源代码文件以.py为扩展名,由pyton程序解释,不需要编译 [[email protected] day01]# vim 1.py #!/usr/bin/python        print 'hello world!' [[email protected] day01]# python 1.py hello world! 2.字节代码 Python源码文件

Python学习笔记--未经排版

Python 学习笔记 Python中如何做到Print() 不换行 答:Print("输出内容",end='不换行的分隔内容'),其中end=后面为2个单引号 注:在Python 2.x中,Print "输出内容", 即在输出内容后加一逗号 Python中 is 和 == 的区别 答:Python中的对象包含三要素:id.type.value 其中id用来唯一标识一个对象,type标识对象的类型,value是对象的值 is判断的是a对象是否就是b对象,是通过id来

Python学习笔记_Python对象

Python学习笔记_Python对象 Python对象 标准类型 其他内建类型 类型对象和type类型对象 Python的Null对象None 标准类型操作符 对象值的比较 对象身份比较 布尔类型 标准类型的内建函数 typeObj cmpobj1 obj2 strobj reprobj typeobj isinstanceobj 标准类型的分类 存储模型 更新模型 访问模型 不支持的类型 Python学习笔记_Python对象 首先来理解一个通俗的含义,什么是对象?其实对象无论在什么语言里面