协程

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

协程是啥

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

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

协程和线程差异

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

import timedef task_1():while True:print("---1----")time.sleep(0.1)yielddef task_2():while True:print("---2----")time.sleep(0.1)yielddef main():t1 = task_1()t2 = task_2()# 先让t1运行一会,当t1中遇到yield的时候,再返回到24行,然后# 执行t2,当它遇到yield的时候,再次切换到t1中# 这样t1/t2/t1/t2的交替运行,最终实现了多任务....协程while True:next(t1)next(t2)if __name__ == "__main__":main()

假的多任务是并发,同一时刻只执行一个任务

greenlet为了更好使用协程来完成多任务,python中的greenlet模块对其封装,从而使得切换任务变的更加简单安装方式使用如下命令安装greenlet模块:sudo pip3 install greenlet
#coding=utf-8from greenlet import greenlet
import timedef 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--
...省略...

greenlet

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

安装方式

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

sudo pip3 install greenlet
#coding=utf-8from greenlet import greenlet
import timedef 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--
...省略...

greenlet对yield进行了封装

gevent对greenlet进行再次封装

import gevent
import timedef f1(n):for i in range(n):print(gevent.getcurrent(), i)# time.sleep(0.5)gevent.sleep(0.5)def f2(n):for i in range(n):print(gevent.getcurrent(), i)# time.sleep(0.5)gevent.sleep(0.5)def f3(n):for i in range(n):print(gevent.getcurrent(), i)# time.sleep(0.5)gevent.sleep(0.5)print("----1---")
g1 = gevent.spawn(f1, 5)
print("----2---")
g2 = gevent.spawn(f2, 5)
print("----3---")
g3 = gevent.spawn(f3, 5)
print("----4---")
g1.join()
g2.join()
g3.join()

gevent

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

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

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

安装

pip3 install gevent

1. gevent的使用

import geventdef 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 geventdef 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. 给程序打补丁(gevent这样使用)

from gevent import monkey
import gevent
import random
import timedef 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

协同最大的意义是延时的时间执行其它的子程序

进程是资源分配的单元,线程执行代码,一个线程只能执行一件事,

协同依赖于线程,线程依赖于进程

进程资源切换消耗最大,线程次之,协同最小(协同切换任务相当于切换了函数)

黑马程序员传智播客python 协程greenlet gevent学习笔记相关推荐

  1. 想进入黑马程序员——传智播客学习

    前些天突然有感自己即将毕业了,小小的感触了一番.反思反思自己这几年大学的所作所为,确实学到的东西太少了,本来是学计算机网络方面的,现在都偏离了本行,搞起了软件方面,可是软件方面的基础也不扎实,面临的各 ...

  2. JavaWeb程序设计任务教程(黑马程序员 传智播客)测一测 编写一个Servlet,实现统计网站被访问次数的功能

    详细解释已在注释中给出 package 统计网站被访问次数;import java.io.*;import javax.servlet.*; import javax.servlet.http.*;p ...

  3. 黑马程序员-传智播客资料中的面试题

    ---------------------- ASP.Net+Unity开发. .Net培训.期待与您交流! ---------------------- 生一个int数组,长度为100,并向其中随机 ...

  4. 传智播客 python_传智播客python视频教程下载

    传智播客python视频教程下载 Python 简介: Python 是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言. Python 的设计具有很强的可读性,相比其他语言经常使用英文关 ...

  5. 传智python基础 就业_2017传智播客python基础班+就业班

    2017传智播客python基础班+就业班 本课程包含了Python的基础语法和核心编程,以及Python应用中流行的数据库.前端,Web框架,爬虫框架及其分布式策略等技术,包含了丰富的项目案例.适合 ...

  6. 传智播客python2018_Python视频教程下载-2018传智播客Python视频教程下载-西西软件下载...

    2018传智播客Python视频教程带给大家一款非常全面的Python视频教程,这里有课件和源码,还有海量基础课视频教程,汇聚了众多实践案例和面向对象的编程实践操作,无论你是零基础学员,或者资深Pyt ...

  7. python传智播客王铭东_传智播客Python学科的王铭东老师讲的怎么样 |

    传智播客Python学科的王铭东老师讲的怎么样 | python高级编程 视频教程2020-09-20 16:40:21人已围观 python好学吗? Python相比于其程语言更容易学习,但是想学精 ...

  8. 传智播客python培训怎么样

    文内容针对的是Python 2.7,因为3的编码已经有了很大的改善并且实际原理一样,更改一下操作命令即可.在本篇文章中,不谈复杂的理论,就传智播客总结的经验,教你字符处理八字真言:确定编码,同类交互. ...

  9. 长沙理工计算机竞赛黑马,2018年传智播客首届“黑马杯”高校编程大赛圆满落幕...

    原标题:2018年传智播客首届"黑马杯"高校编程大赛圆满落幕 传智播客首届"黑马杯"高校编程大赛于2018年9月10日正式举办.本次大赛是面向高校大学生开放的I ...

  10. 传智播客python培训班 青岛

    2021年,随着我国数字化脚步加快,企业和市场对于数字化技术人才的需求不断攀升,IT互联网培训机构担当起人才培养的重要任务.众多IT培训机构在强大市场需求面前也加足马力向前奔跑,本文将解析2021年I ...

最新文章

  1. 计算机视觉不可能凉!
  2. AI复活「她」!用GPT-3复刻逝去未婚妻,美国小哥让挚爱以数字形态永生
  3. 在TFS中通过程序动态创建Bug并感知Bug解决状态
  4. 第一次来,试发一帖!--ASP.NET 2.0 中的SqlCacheDependency特性
  5. 【c++基础】ifstream的构造函数
  6. LetCode: 150. 逆波兰表达式求值
  7. 27. 移除元素 golang
  8. 7宗命案,潜逃23年,大数据还是认出了她
  9. 有趣的数学计算  1/9801 (结果 00,01,02,03。。。97)(使用到 BigDecimal )
  10. statspack系列7
  11. 管理信息系统复习总结(保姆级)
  12. Microsoft Visual C++ Build Tools下载/解决Visual C++ 14.0 is required问题
  13. spring boot 拦截 以及Filter和interceptor 、Aspect区别
  14. 如何是matlab中的折线图变得更加的光滑?
  15. mysql中 符号什么意思_MySQL中的 || 符号是什么意思?
  16. laravel 浏览器谷歌network返回报错html
  17. mysql安装,以及初始化密码
  18. backtrader回测框架实例
  19. Python3,9行批量提取PDF文件的指定内容,这种操作,保证人见人爱....
  20. 货币竞争,不是货币战争

热门文章

  1. Day_04 显示条纹 图案
  2. MFC中将view内容保存为bmp
  3. java 链表插入排序,insertion Sort List (链表的插入排序) leecode java
  4. 关于C#从一个List复制到另一个List的简便写法。
  5. unity打开excel表格_Unity3D读取之(二)——读取Excel文件内容
  6. java 装配_spring Java显示装配
  7. 几个linux中有趣的游戏
  8. 解决Request method 'GET' not supported问题
  9. 忽略mysql库的同步
  10. RMAN 学习过程之四,备份演练进阶篇