python-多任务编程05-协程(coroutine)
协程是python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元(理解为需要的资源)。 为啥说它是一个执行单元,因为它自带CPU上下文。这样只要在合适的时机, 我们可以把一个协程 切换到另一个协程。 只要这个过程中保存或恢复 CPU上下文那么程序还是可以运行的。
通俗的理解:在一个线程中的某个函数,可以在任何地方保存当前函数的一些临时变量等信息,然后切换到另外一个函数中执行,注意不是通过调用函数的方式做到的,并且切换的次数以及什么时候再切换到原来的函数都由开发者自己确定
通过yield实现基础协程
yield的特点就是能够执行方法函数时,暂停执行,然后再继续往下执行,这样就能够实现方法的切换执行
import time def dancing():
for i in range(5):
print('正在跳舞。。。。%d' % i)
yield
time.sleep(0.1) def singing():
for i in range(5):
print('正在唱歌。。。。%d' % i)
yield
time.sleep(0.1) def main():
dance = dancing()
sing = singing()
for i in range(5):
next(dance)
next(sing)
time.sleep(0.1) if __name__ == '__main__':
main()
运行结果为:

通过greenlet实现协程
python中的greenlet模块对yield进行封装,从而使得切换任务变的更加简单,使用前先安装:pip install greenlet
greenlet中先创建对象,然后调用switch()方法开始执行程序
import time
from greenlet import greenlet def dancing():
for i in range(10):
print('正在跳舞。。。。。%d' % i)
sing.switch()
time.sleep(0.1) def singing():
for i in range(10):
print('正在唱歌。。。。。%d' % i)
dance.switch()
time.sleep(0.1) # 创建全局greenlet对象
dance = greenlet(dancing)
sing = greenlet(singing) def main():
# 调用执行dance
print('开始执行dance')
dance.switch() if __name__ == '__main__':
main()
运行结果为:

通过gevent实现协程
greenlet已经实现了协程,但是需要手动通过调用switch进行切换,而gevent模块比greenlet更强大的并且能够自动切换任务。
其原理是当一个greenlet遇到IO(指的是input output 输入输出,比如网络、文件操作等)操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。
使用前先安装:pip install gevent
gevent的基础使用案例
1.普通的耗时操作写法需要转化为gevent模块中的耗时操作,如time.sleep转化为gevent.sleep
2.使用join()开始执行对象中对应的方法并等待方法执行完成
import gevent
import time def dancing(n):
for i in range(n):
print('正在跳舞...%d' % i)
# time.sleep(0.2)
# 普通的耗时操作,如time.sleep、socket.recv()、socket.connect()等
# 这些代码需要手动转换为gevent模块中对应的方法,才能被gevent认为是耗时操作
# 当gevent遇到了认可的耗时操作后,就会自动切换通过gevent创建的对象
# 若没有遇到耗时操作,则按顺序执行gevent对象
gevent.sleep(0.5) def singing(n):
for i in range(n):
print('正在唱歌...%d' % i)
# time.sleep(0.2)
gevent.sleep(0.5) def main():
print('--------main开始-------')
# 创建对象,这时并没有执行方法里面的代码
dance = gevent.spawn(dancing, 5)
sing = gevent.spawn(singing, 6)
# join()开始执行对象中对应的方法并等待方法执行完成
# 在执行方法的过程中,遇到耗时操作,则自动会切换执行gevent对象中的其他方法。
dance.join()
sing.join()
print('-------main结束--------') if __name__ == '__main__':
main()
运行结果为:

gevent的常用简洁写法
1.导入gevent中的monkey,可以将程序中的普通耗时操作转换为gevent中认可的耗时操作
2.使用gevent.joinall让程序更加简洁
import gevent
from gevent import monkey
import time # 有耗时操作时,需要执行这句话
# 能将普通的耗时操作转换为gevent中的耗时操作,这样就不用手动把耗时操作全都替换成gevent中对应的耗时操作了
monkey.patch_all() def work(name, num):
for i in range(num):
print('%s正在执行。。。。%d' % (name, i))
time.sleep(0.2) def main():
dance = gevent.spawn(work, '小明', 5)
sing = gevent.spawn(work, '小花', 6)
gevent.joinall([dance, sing]) if __name__ == '__main__':
main()
运行结果为:

python-多任务编程05-协程(coroutine)的更多相关文章
- 32 python 并发编程之协程
一 引子 本节的主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只有一个)情况下实现并发,为此我们需要先回顾下并发的本质:切换+保存状态 cpu正在运行一个任务,会在两种情况下切走去 ...
- 四 python并发编程之协程
一 引子 本节的主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只有一个)情况下实现并发,为此我们需要先回顾下并发的本质:切换+保存状态 cpu正在运行一个任务,会在两种情况下切走去 ...
- 第十篇.5、python并发编程之协程
一 引子 本节的主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只有一个)情况下实现并发,为此我们需要先回顾下并发的本质:切换+保存状态 cpu正在运行一个任务,会在两种情况下切走去 ...
- 第 12 章 python并发编程之协程
一.引子 主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只用一个)情况下实现并发,并发的本质:切换+保存状态 cpu正在运行一个任务,会在两种情况下切走去执行其他的任务(切换由操作 ...
- 37、python并发编程之协程
目录: 一 引子 二 协程介绍 三 Greenlet 四 Gevent介绍 五 Gevent之同步与异步 六 Gevent之应用举例一 七 Gevent之应用举例二 一 引子 本节的主题是基于单线程来 ...
- python网络编程之协程
本节的主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只有一个)情况下实现并发,为此我们需要先回顾下并发的本质:切换+保存状态 cpu正在运行一个任务,会在两种情况下切走去执行其他的 ...
- python并发编程之协程(实践篇)
一.协程介绍 协程:是单线程下的并发,又称微线程,纤程.一句话说明什么是线程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的. 对于单线程下,我们不可避免程序中出现io操作,但如果我们 ...
- python并发编程之协程知识点
由线程遗留下的问题:GIL导致多个线程不能真正的并行,CPython中多个线程不能并行 单线程实现并发:切换+保存状态 第一种方法:使用yield,yield可以保存状态.yield的状态保存与操作系 ...
- python 并发编程之协程
一.协程 协程: 单线程下的并发,又称 微线程.协程是一种用户态的的轻量级线程,即协程是由用户程序自己控制调度的. 协程的本质就是在单线程下,由用户自己控制一个任务,遇到 io 阻塞就切换另外一个 ...
- python并发编程之协程
---恢复内容开始--- 一.join方法 (1)开一个主线程 from threading import Thread,currentThread import time def walk(): p ...
随机推荐
- Python 简明教程 --- 11,Python 元组
微信公众号:码农充电站pro 个人主页:https://codeshellme.github.io 软件工程的目标是控制复杂度,而不是增加复杂性. -- Dr. Pamela Zave 目录 我们在上 ...
- 入门大数据---Hive的搭建
本博客主要介绍Hive和MySql的搭建: 学习视频一天就讲完了,我看完了自己搭建MySql遇到了一堆坑,然后花了快两天才解决完,终于把MySql搭建好了.然后又去搭建Hive,又遇到了很多坑,就这 ...
- Laravel 如何在blade文件中使用Vue组件
Laravel 如何在blade文件中使用Vue组件 1. 安装laravel/ui依赖包 composer require laravel/ui 2.生成vue基本脚手架 php artisan u ...
- Spring Boot入门系列(十六)使用pagehelper实现分页功能
之前讲了Springboot整合Mybatis,然后介绍了如何自动生成pojo实体类.mapper类和对应的mapper.xml 文件,并实现最基本的增删改查功能.接下来要说一说Mybatis 的分页 ...
- python在循环中追加字典
1. 在循环中用append增加key值,最终生成全是key值的list: 2. 在循环中用append增加value值,最终生成全是value值的list: 3. 最后用zip将两个list合并成一 ...
- dart快速入门教程 (8)
9.dart中的库 9.1.自定义库 自定义库我们在前面已经使用过了,把某些功能抽取到一个文件,使用的时候通过import引入即可 9.2.系统内置库 以math库为例: import "d ...
- 《UNIX环境高级编程》(APUE) 笔记第十章 - 信号
10 - 信号 GitHub 地址 1. 信号 信号是 软中断 ,信号提供了一种处理异步事件的方法. 当造成信号的事件发生时,为进程 产生 一个信号(或向进程 发送 一个信号).事件 可以是硬件异常( ...
- Linux下C++动态加载so 调用方法
Windows 下的C++动态加载DLL调用方法 文献参考 http://man7.org/linux/man-pages/man0/dlfcn.h.0p.html http://man7.org/l ...
- django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.13 or newer is required; you have 0.9.2的最佳处理方法,亲测可用
django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.13 or newer is required; you have 0.9.2 ...
- (私人收藏)商务报告工作汇报PPT模板
商务报告工作汇报PPT模板 https://pan.baidu.com/s/1tWPU6zUTVcV4TIhScoSrEwsjd0