python3.x Day6 协程
协程:
#定义来自牛人alex博客
协程,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程:协程是一种用户态的轻量级线程。
协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此:
协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。 使用协程的目的:就是为了最大限度使用CPU,把IO操作解耦,提高程序运行速度 协程的好处:
无需线程上下文切换的开销
无需原子操作锁定及同步的开销
"原子操作(atomic operation)是不需要synchronized",所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。原子操作可以是一个步骤,也可以是多个操作步骤,但是其顺序是不可以被打乱,或者切割掉只执行部分。视作整体是原子性的核心。
方便切换控制流,简化编程模型
高并发+高扩展性+低成本:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理。 缺点:
无法利用多核资源:协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,协程需要和进程配合才能运行在多CPU上.当然我们日常所编写的绝大部分应用都没有这个必要,除非是cpu密集型应用。
进行阻塞(Blocking)操作(如IO时)会阻塞掉整个程序 greenlet是封装好了的协程
gevent 是进一步封装了greenlet greenlet还需要通过greenlet.greenlet(func)生成greenlet类实例,只能通过gr1.swich()方法手动切换方法执行。
gevent通过gevent.spawn(func,args)生成greenlet类实例,通过gevent.joinall([])装载Greenlet实例,即可启动各个方法,并实现自动的遇到IO就切换
一般在整个当前程序前需要from gevent import monkey引入monkey包,这是个补丁,里边有monkey.patch_all()方法,是明确标记所有IO操作,遇到就切换,
主要是像socket、urllib中的IO操作不会被gevent直接发现时使用这个补丁就能发现了。
gevent需要自行安装pip install gevent
- 必须在只有一个单线程里实现并发
- 修改共享数据不需加锁
- 用户程序里自己保存多个控制流的上下文栈
- 一个协程遇到IO操作自动切换到其它协程
源生的协程
import time
import queue
def consumer(name):
print("--->starting eating baozi...")
while True:
new_baozi = yield
print("[%s] is eating baozi %s" % (name,new_baozi))
#time.sleep(1) def producer(): r = con.__next__()
r = con2.__next__()
n = 0
while n < 5:
n +=1
con.send(n)
con2.send(n)
print("\033[32;1m[producer]\033[0m is making baozi %s" %n ) if __name__ == '__main__':
con = consumer("c1")
con2 = consumer("c2")
p = producer()
利用模块greenlet写协程,简单一些了
#用greenlet来写个简单的协程,大家猜一下运行结果 import greenlet #导入greenlet协程包 def green_func1(): #定义第一个协程用的方法
print(12)
gr2.switch() #切换到协程gr2,保存现场,再度切换回来时,从这里开始
print(34)
gr2.switch() #切换到协程gr2,保存现场,再度切换回来时,从这里开始 def green_func2(): #定义第二个协程用的方法
print(56)
gr1.switch() #切换回协程gr1,保存现场,再度切换回来时,从这里开始
print(78) gr1=greenlet.greenlet(green_func1) #定义第一个协程,装入方法green_func1方法,并启动协程gr1
gr2=greenlet.greenlet(green_func2) #定义第二个协程,装入方法green_func2方法,并启动协程gr2 gr1.switch() #手动切换到协程gr1开始执行。因为没有执行过,所以切换时,从函数开头执行
来个自动的切换吧,这才是真正的写法:
#写个协程抓个网页看看
import gevent,time #引入协程模块
from urllib import request
from gevent import monkey #引入协程模块下的monkey补丁模块
monkey.patch_all() #使用monkey模块下的patch_all()方法,作用是:在每个urllib模块的IO操作前增加标记,来明确协程切换时机 def f_get(url): #定义使用协程的方法,
print("GET %s"%url)
resp=request.urlopen(url)
data=resp.read()
print("%d bytes recevied from %s"%(len(data),url)) urls=[
"https://www.baidu.com/",
"https://github.com/",
"https://hub.docker.com/",
"https://www.yahoo.com/"
] print("同步获取:")
ss_time=time.time()
for u in urls:
f_get(u)
print("同步耗时:%s"%(time.time()-ss_time)) print("协程异步获取:")
async_time=time.time()
gevent.joinall([ #定义协程的启动,需要传入一个gevent.spawn(其实就是Greenlet类的实例)列表
gevent.spawn(f_get,"https://www.baidu.com/"),
gevent.spawn(f_get,"https://github.com/"),
gevent.spawn(f_get,"https://hub.docker.com/"),
gevent.spawn(f_get,"https://www.yahoo.com/")
])
print("协程异步耗时:%s"%(time.time()-async_time)) print("循环生成Greenlet实例变成列表协程异步获取:")
gl=[]
for uu in urls:
gl.append(gevent.spawn(f_get,uu))
async_time=time.time()
gevent.joinall(gl)#定义协程的启动,需要传入一个gevent.spawn(其实就是Greenlet类的实例)列表
print("协程异步耗时:%s"%(time.time()-async_time))
python3.x Day6 协程的更多相关文章
- Python3的原生协程(Async/Await)和Tornado异步非阻塞
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_113 我们知道在程序在执行 IO 密集型任务的时候,程序会因为等待 IO 而阻塞,而协程作为一种用户态的轻量级线程,可以帮我们解决 ...
- 运筹帷幄决胜千里,Python3.10原生协程asyncio工业级真实协程异步消费任务调度实践
我们一直都相信这样一种说法:协程是比多线程更高效的一种并发工作方式,它完全由程序本身所控制,也就是在用户态执行,协程避免了像线程切换那样产生的上下文切换,在性能方面得到了很大的提升.毫无疑问,这是颠扑 ...
- 小议Python3的原生协程机制
此文已由作者张耕源授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 在最近发布的 Python 3.5 版本中,官方正式引入了 async/await关键字.在 asyncio ...
- python3 - 多线程和协程速率测试对比
多线程和协程都属于IO密集型,我通过以下用例测试多线程和协程的实际速率对比. 实例:通过socket客户端以多线程并发模式请求不同服务器端(这里服务器端分2种写法:第一种服务器通过协程实现,第二种服务 ...
- Python3 协程相关 - 学习笔记
什么是协程 协程的优势 Python3中的协程 生成器 yield/send yield + send(利用生成器实现协程) 协程的四个状态 协程终止 @asyncio.coroutine和yield ...
- 再议Python协程——从yield到asyncio
协程,英文名Coroutine.前面介绍Python的多线程,以及用多线程实现并发(参见这篇文章[浅析Python多线程]),今天介绍的协程也是常用的并发手段.本篇主要内容包含:协程的基本概念.协程库 ...
- 关于Python的协程问题总结
协程其实就是可以由程序自主控制的线程 在python里主要由yield 和yield from 控制,可以通过生成者消费者例子来理解协程 利用yield from 向生成器(协程)传送数据# 传统的生 ...
- Python3 与 C# 并发编程之~ 协程篇
3.协程篇¶ 去年微信公众号就陆陆续续发布了,我一直以为博客也汇总同步了,这几天有朋友说一直没找到,遂发现,的确是漏了,所以补上一篇 在线预览:https://github.lesschina.c ...
- python3通过gevent.pool限制协程并发数量
协程虽然是轻量级的线程,但到达一定数量后,仍然会造成服务器崩溃出错.最好的方法通过限制协程并发数量来解决此类问题. server代码: #!/usr/bin/env python # -*- codi ...
随机推荐
- NOIp2017真题模拟赛 By cellur925
果然我还是最菜的==不接受反驳 (先考了day2喵喵喵) Day2 T1:奶酪 期望得分:100分 实际得分:100分 考察:并查集 思路:这题其实之前做过了==.思路还是比较清晰的,读入时预处理出可 ...
- django接受表单
from django.shortcuts import render from django.shortcuts import HttpResponse import os # Create you ...
- RAID基础
磁盘类型 类型 IDE Integrated Drive Electronics SATA Srial ATA SCSI Small Computer System Interface FC Fibe ...
- AJPFX总结heap和stack有什么区别?
栈是后进先出的线性表结构,存取速度比堆快.创建对象的时候new一个对象,引用存在栈上具体的内容存在堆上. 栈与堆都是Java用来在RAM中存放数据的地方.与C++不同,Java自动管理栈和堆,程序员不 ...
- 微信小程序 可用性一览
1. 调试vConsole微信小程序通过vConsole的形式观察控制台打印.打印到vConsole控制台的是由 JSON 转化的字符串.这还是可以起到调试作用的. Source Map当es6 转 ...
- asp.net 中文部分显示问号
很神奇的事情,今天部署了一个网站,页面从数据读取新闻后,有些新闻标题全部显示问题号,有几个新闻能正确显示汉字,然后查看新闻页面又能正常显示汉字. 解决办法: 在异常的页面上加上 < %@ COD ...
- 在git远程仓创建项目之后,提交本地项目的使用方法
命令介绍 git 用户配置 git config --global user.name "张三" git config --global user.email "zhag ...
- mySQL ODBC 在windows 64位版上的驱动问题
1,问题的起源 某次编辑一个asp文件,其中访问mysql数据库的连接字符串如下: "driver={mysql odbc 3.51 driver};server=localhost;uid ...
- 腾讯AI开放平台的接口调用指南
最近无意发现腾讯AI开放平台上提供了大量好玩的人工智能云服务,而且是完全免费的.只需要用QQ号登录即可.这么好的东西,作为一个程序员,当然要试试了! 从上图可以看出腾讯AI开放平台提供的人工智能服务主 ...
- 事件捕获 & 事件冒泡
<body> <div id="div1"> <div id="div2"> <div id="div3&q ...