协程

协程,又称微线程,纤程。英文名Coroutine。

协程是啥

协程是python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元(理解为需要的资源)。 为啥说它是一个执行单元,因为它自带CPU上下文。这样只要在合适的时机, 我们可以把一个协程 切换到另一个协程。 只要这个过程中保存或恢复 CPU上下文那么程序还是可以运行的。

通俗的理解:在一个线程中的某个函数,可以在任何地方保存当前函数的一些临时变量等信息,然后切换到另外一个函数中执行,注意不是通过调用函数的方式做到的,并且切换的次数以及什么时候再切换到原来的函数都由开发者自己确定

协程和线程差异

在实现多任务时, 线程切换从系统层面远不止保存和恢复 CPU上下文这么简单。 操作系统为了程序运行的高效性每个线程都有自己缓存Cache等等数据,操作系统还会帮你做这些数据的恢复操作。 所以线程的切换非常耗性能。但是协程的切换只是单纯的操作CPU的上下文,所以一秒钟切换个上百万次系统都抗的住。

简单实现协程

利用yield关键字(其实质就是一个生成器,有关于生成器的详细解析:python生成器详解)

import time
​
def test1():while True:print("----test1---")yieldtime.sleep(0.5)
​
def test2():while True:print("----test2---")yieldtime.sleep(0.5)
​
def main():t1 = test1()t2 = test2()while True:next(t1)next(t2)
​
if __name__ == "__main__":main()

运行结果:

----test1---
----test2---
----test1---
----test2---
----test1---
----test2---
----test1---
----test2---
----test1---
----test2---
----test1---
----test2---
...省略...

greenlet

为了更好使用协程来完成多任务,python中的greenlet模块对其封装,从而使得切换任务变的更加简单

安装方式

使用如下命令安装greenlet模块:

sudo pip3 install greenlet#coding=utf-8
​
from greenlet import greenlet
import time
​
def test1():while True:print "---A--"gr2.switch()time.sleep(0.5)
​
def test2():while True:print "---B--"gr1.switch()time.sleep(0.5)
​
gr1 = greenlet(test1)
gr2 = greenlet(test2)
​
#切换到gr1中运行
gr1.switch()

运行效果

---A--
---B--
---A--
---B--
---A--
---B--
---A--
---B--
...省略...

gevent

greenlet已经实现了协程,但是这个还的人工切换,是不是觉得太麻烦了,不要捉急,python还有一个比greenlet更强大的并且能够自动切换任务的模块gevent

其原理是当一个greenlet遇到IO(指的是input output 输入输出,比如网络、文件操作等)操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。

由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO

安装

pip3 install gevent

1. gevent的使用

import gevent
​
def f(n):for i in range(n):print(gevent.getcurrent(), i)
​
g1 = gevent.spawn(f, 5)
g2 = gevent.spawn(f, 5)
g3 = gevent.spawn(f, 5)
g1.join()
g2.join()
g3.join()

运行结果

<Greenlet at 0x10e49f550: f(5)> 0
<Greenlet at 0x10e49f550: f(5)> 1
<Greenlet at 0x10e49f550: f(5)> 2
<Greenlet at 0x10e49f550: f(5)> 3
<Greenlet at 0x10e49f550: f(5)> 4
<Greenlet at 0x10e49f910: f(5)> 0
<Greenlet at 0x10e49f910: f(5)> 1
<Greenlet at 0x10e49f910: f(5)> 2
<Greenlet at 0x10e49f910: f(5)> 3
<Greenlet at 0x10e49f910: f(5)> 4
<Greenlet at 0x10e49f4b0: f(5)> 0
<Greenlet at 0x10e49f4b0: f(5)> 1
<Greenlet at 0x10e49f4b0: f(5)> 2
<Greenlet at 0x10e49f4b0: f(5)> 3
<Greenlet at 0x10e49f4b0: f(5)> 4

可以看到,3个greenlet是依次运行而不是交替运行

2. gevent切换执行

import gevent
​
def f(n):for i in range(n):print(gevent.getcurrent(), i)#用来模拟一个耗时操作,注意不是time模块中的sleepgevent.sleep(1)
​
g1 = gevent.spawn(f, 5)
g2 = gevent.spawn(f, 5)
g3 = gevent.spawn(f, 5)
g1.join()
g2.join()
g3.join()

运行结果

<Greenlet at 0x7fa70ffa1c30: f(5)> 0
<Greenlet at 0x7fa70ffa1870: f(5)> 0
<Greenlet at 0x7fa70ffa1eb0: f(5)> 0
<Greenlet at 0x7fa70ffa1c30: f(5)> 1
<Greenlet at 0x7fa70ffa1870: f(5)> 1
<Greenlet at 0x7fa70ffa1eb0: f(5)> 1
<Greenlet at 0x7fa70ffa1c30: f(5)> 2
<Greenlet at 0x7fa70ffa1870: f(5)> 2
<Greenlet at 0x7fa70ffa1eb0: f(5)> 2
<Greenlet at 0x7fa70ffa1c30: f(5)> 3
<Greenlet at 0x7fa70ffa1870: f(5)> 3
<Greenlet at 0x7fa70ffa1eb0: f(5)> 3
<Greenlet at 0x7fa70ffa1c30: f(5)> 4
<Greenlet at 0x7fa70ffa1870: f(5)> 4
<Greenlet at 0x7fa70ffa1eb0: f(5)> 4

3. 给程序打补丁

from gevent import monkey
import gevent
import random
import time
​
def coroutine_work(coroutine_name):for i in range(10):print(coroutine_name, i)time.sleep(random.random())
​
gevent.joinall([gevent.spawn(coroutine_work, "work1"),gevent.spawn(coroutine_work, "work2")
])

运行结果

work1 0
work1 1
work1 2
work1 3
work1 4
work1 5
work1 6
work1 7
work1 8
work1 9
work2 0
work2 1
work2 2
work2 3
work2 4
work2 5
work2 6
work2 7
work2 8
work2 9

 
from gevent import monkey
import gevent
import random
import time
​
# 有耗时操作时需要
monkey.patch_all()  # 将程序中用到的耗时操作的代码,换为gevent中自己实现的模块
​
def coroutine_work(coroutine_name):for i in range(10):print(coroutine_name, i)time.sleep(random.random())
​
gevent.joinall([gevent.spawn(coroutine_work, "work1"),gevent.spawn(coroutine_work, "work2")
])

 

运行结果

work1 0
work2 0
work1 1
work1 2
work1 3
work2 1
work1 4
work2 2
work1 5
work2 3
work1 6
work1 7
work1 8
work2 4
work2 5
work1 9
work2 6
work2 7
work2 8
work2 9

转载于:https://www.cnblogs.com/wangcoo/p/10018460.html

python中协程实现的本质以及两个封装协程模块greenle、gevent相关推荐

  1. Python中使用逻辑与运算符“and”判断两个比较条件是否满足时编辑器提示“Simplify chained comparison ”的解决方法

    Python中使用逻辑与运算符"and"判断两个比较条件是否满足时编辑器提示"Simplify chained comparison ", 如下图所示: 这是提 ...

  2. python中求差的函数_Python编程基础11:函数和模块

    一.函数和模块概述 (一)函数概述 函数可以看成是语句的集合,通过函数调用来执行其包含的语句.函数可以返回一个计算结果,根据每次函数调用的参数,可以返回不同的计算结果.Python利用函数提高代码的重 ...

  3. python中的且的符号and用两个和用一个的区别_Python 中的 or and 运算,看这一篇就够...

    问题出现: Python 中的 or,and 运算,可以写出比较复杂的演算表达式: 看了一些大神的演算规则解释,觉得不是很好理解,有些人甚至理解错了规则. 这里聊一下自己的理解. 其他人是怎么做的: ...

  4. python中的from后面一个点或者两个点是什么意思

    问题如上,我们在使用python导入包或者库的时候有时候会遇到包前面有一个点或者两个点的情况. 如上图,from后面的程序word_unify_dict前面有一个原点,这个原点其实就表示当前程序所在的 ...

  5. python中对excel工作表的基础操作:xlrd、xlwt模块笔记

    模块介绍 (1)什么是xlrd模块? python操作excel主要用到xlrd和xlwt这两个库,即xlrd是读excel,xlwt是写excel的库. (2)为什么使用xlrd模块? 在UI自动化 ...

  6. python中循环语句只有for和while两种_Python循环语句之while,for语句详解

    下面为大家分享一篇Python 循环语句之 while,for语句详解,具有很好的参考价值,希望对大家有所帮助.一起过来看看吧 Python中有两种循环,分别为:for循环和while循环. for循 ...

  7. python中pip不可用_python – pip无法确认SSL证书:SSL模块不可用

    我正在尝试在我的Raspberry Pi Zero W上为Python 3.6安装RPi.GPIO,但不知何故它不会连接到python.org网站.我安装了2.7,3.0和3.6的pip,所以当我去做 ...

  8. 关于如何将python中多维数组的数字保留两位有效数字

    基于GBDT回归模型的案例 #1.读取数据 import numpy as np import pandas as pd df=pd.read_excel('信用评分卡模型.xlsx') print( ...

  9. python中从1加到100的两种写法

    方法一:while循环 a=1 b=0 while a<=100:b+=aa+=1 print(b) 方法二:range语句 a=0 for i in range(1,101):a+=i pri ...

最新文章

  1. C#使用log4net记录日志
  2. python多线程爬虫界面_多线程网页爬虫 python 实现
  3. python学习详解_Python学习入门到精通:Python列表讲解
  4. c语言如何获取按键,c语言获得键盘的按键
  5. Keil | 解决Keil与VScode配合使用时,代码与注释位置不一样的问题。
  6. Asp.NET的DESAES加密算法(转载)
  7. mysql脚本中如何写判断_mysql中如何写判断语句
  8. onmounted vue3_Vue2和Vue3使用层面上的区别总结
  9. jsp el表达式无法正常显示解决方法
  10. fcm基本原理_fcm聚类算法原理及应用
  11. Typora+picgo+gitee图片外链失效,Typora历史笔记无法显示图片
  12. arcgis engine已知图幅号获取比例尺
  13. 逍遥模拟器安装xposed installer
  14. Cors跨域(二):实现跨域Cookie共享的三要素
  15. 宏碁掠夺者Predator首款RGB内存条即将发售,特挑三星B-Die颗粒
  16. 微信直播小程序端集成源代码
  17. Pycharm 报错 Environment location directory is not empty的解决方法
  18. php 保留小数点两位不四舍五入 bcdiv()
  19. springboot导出excel(easyexcel和poi 列下拉及表格锁定)
  20. 【海南赛区】​2022高教社杯全国大学生数学建模竞赛获奖人员名单公示

热门文章

  1. java分哪几部分_JVM 是由哪几部分组成的?
  2. abb样本-感应电机与发电机手册_发电机工作原理图解
  3. python3 sleep 并发_Python3并发写文件与Python对比
  4. linux服务器重启后阵列卡分区没了,服务器数据丢失了怎么恢复/分区丢失恢复教程...
  5. docker tomcat 多开 实例_给妈妈讲什么是docker
  6. u盘复制不进去东西_限制电脑只能识别自己指定的U盘
  7. node JS獲取GPS_Node.js 14 正式发布:V8 引擎升级,新增异步本地存储 API
  8. mysql创建非聚集索引_聚集索引和非聚集索引的区别
  9. 【行业趋势】人工智能凭什么“教育”人
  10. 【caffe解读】 caffe从数学公式到代码实现5-caffe中的卷积