协程:
#定义来自牛人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
  1. 必须在只有一个单线程里实现并发
  2. 修改共享数据不需加锁
  3. 用户程序里自己保存多个控制流的上下文栈
  4. 一个协程遇到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 协程的更多相关文章

  1. Python3的原生协程(Async/Await)和Tornado异步非阻塞

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_113 我们知道在程序在执行 IO 密集型任务的时候,程序会因为等待 IO 而阻塞,而协程作为一种用户态的轻量级线程,可以帮我们解决 ...

  2. 运筹帷幄决胜千里,Python3.10原生协程asyncio工业级真实协程异步消费任务调度实践

    我们一直都相信这样一种说法:协程是比多线程更高效的一种并发工作方式,它完全由程序本身所控制,也就是在用户态执行,协程避免了像线程切换那样产生的上下文切换,在性能方面得到了很大的提升.毫无疑问,这是颠扑 ...

  3. 小议Python3的原生协程机制

    此文已由作者张耕源授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 在最近发布的 Python 3.5 版本中,官方正式引入了 async/await关键字.在 asyncio ...

  4. python3 - 多线程和协程速率测试对比

    多线程和协程都属于IO密集型,我通过以下用例测试多线程和协程的实际速率对比. 实例:通过socket客户端以多线程并发模式请求不同服务器端(这里服务器端分2种写法:第一种服务器通过协程实现,第二种服务 ...

  5. Python3 协程相关 - 学习笔记

    什么是协程 协程的优势 Python3中的协程 生成器 yield/send yield + send(利用生成器实现协程) 协程的四个状态 协程终止 @asyncio.coroutine和yield ...

  6. 再议Python协程——从yield到asyncio

    协程,英文名Coroutine.前面介绍Python的多线程,以及用多线程实现并发(参见这篇文章[浅析Python多线程]),今天介绍的协程也是常用的并发手段.本篇主要内容包含:协程的基本概念.协程库 ...

  7. 关于Python的协程问题总结

    协程其实就是可以由程序自主控制的线程 在python里主要由yield 和yield from 控制,可以通过生成者消费者例子来理解协程 利用yield from 向生成器(协程)传送数据# 传统的生 ...

  8. Python3 与 C# 并发编程之~ 协程篇

      3.协程篇¶ 去年微信公众号就陆陆续续发布了,我一直以为博客也汇总同步了,这几天有朋友说一直没找到,遂发现,的确是漏了,所以补上一篇 在线预览:https://github.lesschina.c ...

  9. python3通过gevent.pool限制协程并发数量

    协程虽然是轻量级的线程,但到达一定数量后,仍然会造成服务器崩溃出错.最好的方法通过限制协程并发数量来解决此类问题. server代码: #!/usr/bin/env python # -*- codi ...

随机推荐

  1. Angular 项目开发中父子组件传参

    在项目开发中经常会遇到 组件之间传参的问题.今天总结下在使用angular的项目中父子组件传参的问题: 1.父组件向子组件传参: 然后在父组件中 然后在父组件的html中 然后就可以在子组件中使用了 ...

  2. elasticsearch映射 mapping

    mapping的格式个应用,主要是创建索引(数据库)的时候指明type 的field类型,然后elasticsearch可以自动解析

  3. video.py OpenCv例程阅读

    #!/usr/bin/env python ''' Video capture sample. Sample shows how VideoCapture class can be used to a ...

  4. Jenkins自动化部署——持续交付

    感谢之前带领过我的leader,让我能够知道什么是好的开发方法. 在很早之前就接触过敏捷开发.什么是敏捷开发,简单来说就是让软件可靠地,快速地发布出来的一种开发方法和技巧. 而敏捷开发中有许多的实践, ...

  5. Jmeter之聚合报告

    1.添加线程组,添加请求接口 2.设置线程组 3.线程组右击添加—>监听器—>聚合报告

  6. Lightoj 1044 - Palindrome Partitioning (DP)

    题目链接: Lightoj  1044 - Palindrome Partitioning 题目描述: 给一个字符串,问至少分割多少次?分割出来的子串都是回文串. 解题思路: 先把给定串的所有子串是不 ...

  7. set有关的函数的用法(The SetStack Computer UVA - 12096)

    #include<bits/stdc++.h> using namespace std; typedef set<int> Set; map<Set,int> ID ...

  8. sql 语句操作,修改字段中字符串的一部分

    update 表名 set 字段=replace(字段,‘替换的部分’,‘替换后的字符串’): update 表名 set A=replace( A, '海淀', '朝阳') where A like ...

  9. hdu4003/蓝桥杯 金属采集

    思路: 树形dp + 分组背包dp. 参考https://www.cnblogs.com/kuangbin/archive/2012/08/29/2661928.html 实现: #include & ...

  10. obj.style 和currentstyle 等区别

    版权声明:本文为博主原创文章,未经博主允许不得转载. 获取样式  obj.style   和currentstyle  等区别   obj.style只能获得内嵌样式(inline Style)就是写 ...