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 ...
随机推荐
- poj1850 Code【组合数学】By cellur925
题意: * 按照字典序的顺序从小写字母 a 开始按顺序给出序列 (序列中都为升序字符串)* a - 1* b - 2* ...* z - 26* ab - 27* ...* az - 51* bc - ...
- macOS 将【允许从以下位置下载的应用】设置为:任意来源
用管理员帐号进入Terminal: 1) 输入:sudo spctl --master-disable ,回车: 2) 重新进入该设置页面即可看到已生效:
- Hexo瞎折腾系列(3) - 添加GitHub彩带和GitHub Corner
页面右上角添加GitHub彩带 你可以在这里找到一共12种样式的GitHub彩带,复制其中的超链代码. 在themes\next\layout\_layout.swig目录下找到头部彩带相关的代码: ...
- 用jQuery获取到一个类名获取到的是一个数组 ,如果对数组中的每个进行相应的操作可以这样进行
$(".userImg").each(function(){ $(this).click(function(){ var imgid = $(this).attr("id ...
- Python递归和迭代
递归 在函数内部,调用函数自身的编程技巧称为递归( recursion).递归函数结构清晰,很直观的理解计算过程,但也有严重缺点:相对于普通循环而言,递归运行效率较低,经过很多冗余的计算,递归会消耗大 ...
- Codeforces Round #544 (Div. 3) B.Preparation for International Women's Day
链接:https://codeforces.com/contest/1133/problem/B 题意: 给n个数,和一个k,在n个数中选几对数,保证没对数相加可以整除k. 求最大能选几个数. 思路: ...
- POJ3417(树上差分)
会卡vector. ; int n, m, Ans; ], to[maxn * ], tot; int vis[maxn], f[maxn]; int d[maxn], sum[maxn]; vect ...
- UVa 12186 Another Crisis 工人的请愿书
c表示某上司上报的最少请愿下属,k表示总下属c=0.01T*k=kT/100(0.01T*k是整数)c=[0.01T*k]+1=[kT/100]+1(0.01T*k不是整数) kT=100 c=1 k ...
- HDU 1220 B - Cube
http://acm.hdu.edu.cn/showproblem.php?pid=1220 一开始的做法是,先暴力算出一个面,就是n * n的面,能有多少对.记作face 然后从上开始算下来,最上一 ...
- linux给文件或目录添加apache权限
系统环境:ubuntu11.10/apache2/php5.3.6 在LAMP环境中,测试一个简单的php文件上传功能时,发现/var/log/apache2/error.log中出现如下php警告: ...