Python高级——协程
协程
协程与线程差异
在实现多任务时, 线程切换从系统层面远不止保存和恢复 CPU上下文这么简单。 操作系统为了程序运行的高效性每个线程都有自己缓存Cache等等数据,操作系统还会帮你做这些数据的恢复操作。 所以线程的切换非常耗性能。但是协程的切换只是单纯的操作CPU的上下文,所以一秒钟切换个上百万次系统都抗的住。
原理
协程是python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元(理解为需要的资源)。为什么说它是一个执行单元,因为它自带CPU上下文。这样只要在合适的时机, 我们可以把一个协程 切换到另一个协程。 只要这个过程中保存或恢复 CPU上下文那么程序还是可以运行的。
1.简单实现协程
例:
import timedef work1():while True:print('work1----------')yieldtime.sleep(0.5)def work2():while True:print('work2---')yieldtime.sleep(0.5)if __name__ == '__main__':w1 = work1()w2 = work2()while True:next(w1)next(w2)
将work函数用yield改写为生成器,并且可以保存暂停当前函数内容,下次执行时继续,使得work1和work2交替执行。
2.greenlet创建
例:
from 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()
开发者使用switch()方法手动切换协程,也实现了两个函数交替执行
3.gevent创建
自动调度的协程,识别耗时操作自动进行协程切换
gevent.spawn(函数名, 参数)
join:使主线程等待写执行完毕再结束
joinall(列表):让主线程等待协程执行完毕再结束
import geventdef work1():for i in range(5):print("work1 -----1")gevent.sleep(0.5)def work2():for i in range(5):print("work2 -----2")gevent.sleep(0.5)# 创建携程并指派任务
# g1 = gevent.spawn(work1)
# g2 = gevent.spawn(work2)
# 等待协程执行完成再关闭主线程
# g1.join()
# g2.join()
# 等价于
gevent.joinall([gevent.spawn(work1), gevent.spawn(work2)])
4.注意
gevent中不识别time.sleep()等方法,它有自己的sleep()方法,如果要用time.sleep()等方法,需要打猴子补丁:
from gevent import monkey
monkey.patch_all()
查看当前执行的协程名称:gevent.getcurrent()
5.案例(并发下载器):
import urllib.request
import geventdef img_download(url, file_name):try:img_file = urllib.request.urlopen(url)with open(file_name, "wb") as file:while True:img_data = img_file.read(1024)if img_data:file.write(img_data)else:breakexcept:print("文件%s下载异常" % file_name)else:print("文件%s下载成功" % file_name)if __name__ == '__main__':img_url1 = "http://img.mp.itc.cn/upload/20170716/8e1b835f198242caa85034f6391bc27f.jpg"img_url2 = "http://pic1.wed114.cn/allimg/180227/1023303521-1.gif"img_url3 = "http://image.uczzd.cn/11867042470350090334.gif?id=0&from=export"gevent.joinall([gevent.spawn(img_download, img_url1, "1.gif"),gevent.spawn(img_download, img_url2, "2.gif"),gevent.spawn(img_download, img_url3, "3.gif")])
进程、线程、协程区别
1.进程:资源分配的基本单位,重量级,单独分配内存
2.线程:任务调度的基本单位,本身不拥有资源,占有很少的运行资源
3.协程:微线程,在不创建新线程的基础上,执行多任务
Python高级——协程相关推荐
- python高级---协程---放飞自我
一:定义: 1:协程:微线程(比线程更小) 线程 和 进程 都是CPU调度 协程是开发者自己决定. 优点:效率高,不需要锁. 二:gevent使用: 1:导入库: pip3 install -i ge ...
- Python 的协程库 greenlet 和 gevent
greenlet 官方文档:https://greenlet.readthedocs.io/en/latest/ From:https://www.jianshu.com/u/3ab212f28d91 ...
- python gevent 协程
python gevent 协程 def func1():print("fun1开始运行")gevent.sleep(2) # 内部函数实现io操作print("func ...
- Python基础入门教程:使用 Python 3 协程快速获得一个代理池
Python基础入门教程:使用 Python 3 协程快速获得一个代理池 前言 在执行 IO 密集型任务的时候,程序会因为等待 IO 而阻塞.比如我们使用 requests 库来进行网络爬虫请求的话, ...
- python中协程与函数的区别_深入浅析python 协程与go协程的区别
进程.线程和协程 进程的定义: 进程,是计算机中已运行程序的实体.程序本身只是指令.数据及其组织形式的描述,进程才是程序的真正运行实例. 线程的定义: 操作系统能够进行运算调度的最小单位.它被包含在进 ...
- python中协程与函数的区别_python 协程与go协程的区别
进程.线程和协程 进程的定义: 进程,是计算机中已运行程序的实体.程序本身只是指令.数据及其组织形式的描述,进程才是程序的真正运行实例. 线程的定义: 操作系统能够进行运算调度的最小单位.它被包含在进 ...
- Python 的协程
前言 最近在看部分Python源码时, 发现了async 这个关键字. 查了一下发现了Python中的协程. 协程这玩意, 在GO中我用过啊, 简单说, 就是一个轻量级的线程嘛, 由语言自己来实现不同 ...
- python3 协程 写法_理解Python的协程(Coroutine)
由于GIL的存在,导致Python多线程性能甚至比单线程更糟. GIL: 全局解释器锁(英语:Global Interpreter Lock,缩写GIL),是计算机程序设计语言解释器用于同步线程的一种 ...
- python携程使用_简单了解python gevent 协程使用及作用
简介 没有切换开销.因为子程序切换不是线程切换,而是由程序自身控制,没有线程切换的开销,因此执行效率高, 不需要锁机制.因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断 ...
最新文章
- Javascript字符串及数组赋值区别
- UICollectionView的headerView、footerView使用以及与UITableView加载headerView、footerView的区别...
- python计算输入的两个数字,try...except...判断是否输入的是数字,如果是则相加
- HBASE+Solr实现详单查询--转
- element ui 批量删除之后动态更新列表_气象编程 | Python高效批量绘图方法
- C++访问权限与继承
- Docker 持久化存储
- [转] 一次Ajax查错的经历
- GHOSTXP_SP3电脑公司快速安装机版V2013
- ubuntu开机时网络图标不见了且不能上网
- Mysql学习总结(71)——MySQL 重复记录查询与删除总结
- win7日历加入农历_还是农历更亲切,春节制作一个带农历的日历,欢欢喜喜过新年...
- 维基解密:科技公司获得安全漏洞信息须答应几个条件
- mysql配置my.cnf文件,以及参数优化提升性能
- Spring Boot 集成 RabbitMQ 升级
- java正则表达式yyyymmdd_正则表达式校验YYYYMMDD日期格式
- cad化气路图_气路图符号cad下载
- xampp mysql3306_xmapp_mysql端口冲突解决---Port 3306 in use by......
- maya2018 + VS2017 C++编译环境搭建
- 使用Cronjobs的综合指南