原文链接:https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001407503089986d175822da68d4d6685fbe849a0e0ca35000

Python通过yield提供了对协程的基本支持,但是不完全。而第三方的gevent为Python提供了比较完善的协程支持。

gevent是第三方库,通过greenlet实现协程,其基本思想是:

当一个greenlet遇到IO操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO。

由于切换是在IO操作时自动完成,所以gevent需要修改Python自带的一些标准库,这一过程在启动时通过monkey patch完成:

from gevent import monkey; monkey.patch_socket()
import geventdef f(n):for i in range(n):print gevent.getcurrent(), ig1 = gevent.spawn(f, 5)
g2 = gevent.spawn(f, 5)
g3 = gevent.spawn(f, 5)
g1.join()
g2.join()
g3.join()

运行结果:

<Greenlet at 0x10e49f550: f(5)> 0
<Greenlet at 0x10e49f550: f(5)> 1
<Greenlet at 0x10e49f550: f(5)> 2
<Greenlet at 0x10e49f550: f(5)> 3
<Greenlet at 0x10e49f550: f(5)> 4
<Greenlet at 0x10e49f910: f(5)> 0
<Greenlet at 0x10e49f910: f(5)> 1
<Greenlet at 0x10e49f910: f(5)> 2
<Greenlet at 0x10e49f910: f(5)> 3
<Greenlet at 0x10e49f910: f(5)> 4
<Greenlet at 0x10e49f4b0: f(5)> 0
<Greenlet at 0x10e49f4b0: f(5)> 1
<Greenlet at 0x10e49f4b0: f(5)> 2
<Greenlet at 0x10e49f4b0: f(5)> 3
<Greenlet at 0x10e49f4b0: f(5)> 4

可以看到,3个greenlet是依次运行而不是交替运行。

要让greenlet交替运行,可以通过gevent.sleep()交出控制权:

def f(n):for i in range(n):print gevent.getcurrent(), igevent.sleep(0)

执行结果:

<Greenlet at 0x10cd58550: f(5)> 0
<Greenlet at 0x10cd58910: f(5)> 0
<Greenlet at 0x10cd584b0: f(5)> 0
<Greenlet at 0x10cd58550: f(5)> 1
<Greenlet at 0x10cd584b0: f(5)> 1
<Greenlet at 0x10cd58910: f(5)> 1
<Greenlet at 0x10cd58550: f(5)> 2
<Greenlet at 0x10cd58910: f(5)> 2
<Greenlet at 0x10cd584b0: f(5)> 2
<Greenlet at 0x10cd58550: f(5)> 3
<Greenlet at 0x10cd584b0: f(5)> 3
<Greenlet at 0x10cd58910: f(5)> 3
<Greenlet at 0x10cd58550: f(5)> 4
<Greenlet at 0x10cd58910: f(5)> 4
<Greenlet at 0x10cd584b0: f(5)> 4

3个greenlet交替运行,

把循环次数改为500000,让它们的运行时间长一点,然后在操作系统的进程管理器中看,线程数只有1个。

当然,实际代码里,我们不会用gevent.sleep()去切换协程,而是在执行到IO操作时,gevent自动切换,代码如下:

from gevent import monkey; monkey.patch_all()
import gevent
import urllib2def f(url):print('GET: %s' % url)resp = urllib2.urlopen(url)data = resp.read()print('%d bytes received from %s.' % (len(data), url))gevent.joinall([gevent.spawn(f, 'https://www.python.org/'),gevent.spawn(f, 'https://www.yahoo.com/'),gevent.spawn(f, 'https://github.com/'),
])

运行结果:

GET: https://www.python.org/
GET: https://www.yahoo.com/
GET: https://github.com/
45661 bytes received from https://www.python.org/.
14823 bytes received from https://github.com/.
304034 bytes received from https://www.yahoo.com/.

从结果看,3个网络操作是并发执行的,而且结束顺序不同,但只有一个线程。

小结

使用gevent,可以获得极高的并发性能,但gevent只能在Unix/Linux下运行,在Windows下不保证正常安装和运行。(亲测windows下面可以正常运行,原作写文章较早,可能当时还不支持)

由于gevent是基于IO切换的协程,所以最神奇的是,我们编写的Web App代码,不需要引入gevent的包,也不需要改任何代码,仅仅在部署的时候,用一个支持gevent的WSGI服务器,立刻就获得了数倍的性能提升。具体部署方式可以参考后续“实战”-“部署Web App”一节。

python3之协程(4)---gevent实现协程操作相关推荐

  1. 协程的概念及Python中利用第三方库gevent使用协程

    提到程序的并发操作,大多数人程序员首先想到的进程或者线程.我们先复习一下进程和线程的概念.   进程: 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的 ...

  2. python 协程池gevent.pool_进程池\线程池,协程,gevent

    目录 1. 进程池与线程池 2. 协程 3. gevent 4. 单线程下实现并发的套接字通信 首先写一个基于多线程的套接字 服务端: from socket import * from thread ...

  3. Python浅谈gevent实现协程

    每日一怼:垃圾桶都收到花了,你却没有 认识gevent之前我们先来认识一下协程,什么是协程? 在笔者的看来就是在A程序与B程序的反复调用执行. 当A程序执行结束后调用执行B程序,B程序结束后调用A程序 ...

  4. 协程池gevent实现糗事百科爬取

    标题 -协程池gevent实现糗事百科爬取 import gevent.monkey gevent.monkey.patch_all() from gevent.pool import Pool im ...

  5. python携程gevent_python gevent 协程

    简介 没有切换开销.因为子程序切换不是线程切换,而是由程序自身控制,没有线程切换的开销,因此执行效率高, 不需要锁机制.因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断 ...

  6. python3之协程(3)---greenlet实现协程操作

    原文链接:https://www.cnblogs.com/xybaby/p/6337944.html 正文 在前面的文章中提到python原生的generator是semicoroutine,而gre ...

  7. c++ 协程_理解Python协程(Coroutine)

    由于GIL的存在,导致Python多线程性能甚至比单线程更糟. GIL: 全局解释器锁(英语:Global Interpreter Lock,缩写GIL),是计算机程序设计语言解释器用于同步线程的一种 ...

  8. linux的进程/线程/协程系列5:协程的发展复兴与实现现状

    协程的发展复兴与实现现状 前言 本篇摘要: 1. 协同制的发展史 1.1 协同工作制的提出 1.2 自顶向下,无需协同 1.3 协同式思想的应用 2. 协程的复兴 2.1 高并发带来的问题 2.2 制 ...

  9. python协程库_python中协程的详解(附示例)

    本篇文章给大家带来的内容是关于python中协程的详解(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 协程,又称微线程,纤程.英文名Coroutine 协程看上去也是子程序 ...

最新文章

  1. VMM2012应用指南之4-向VMM中添加Hyper-V主机与应用服务器
  2. windows下启动/关闭Sybase数据库服务器
  3. HDU - 1079 Calendar Game(博弈打表sg函数)
  4. Nginx实现404页面的几种方法
  5. Android——Activity去除标题栏和状态栏
  6. python常用模块用法_python笔记之常用模块用法分析
  7. php操作access数据库类代码
  8. python进阶到高阶大全(强烈推荐)
  9. latex生成pdf中文标签乱码pdf复制乱码
  10. TCP/IP常见英文缩写
  11. Java根据word模板生成word文件
  12. 群体遗传学瓶颈效应bottleneck effect
  13. 沟通的艺术:看人入里,看出人外 - part 1
  14. ROC阳性结果还是阴性结果?
  15. ssh 反向代理连接内网服务器并配置开机自启动(解决autossh无法开机自启动)
  16. pandas数据类型转为str
  17. uniapp中使用拷贝,复制粘贴功能,uniapp,隐藏软键盘
  18. 判断ios系统、qq浏览器,iosqq内置浏览器,微信内置浏览器
  19. 存储术语中的LUN概念
  20. linux 安装 T400 无线网卡驱动

热门文章

  1. Redis工具类封装讲解和实战
  2. ThreadLocal的第二种用法 part2
  3. 动态代理源码分析,实现自己的动态代理
  4. 通过反射运行配置文件内容
  5. Object类Objects类总结
  6. API Gateway简介
  7. 单点登录Redis存储Session及SessionId问题说明与集群实战-2
  8. 华为云服务器芯片,云服务器芯片
  9. oracle 创建表中又有表,oracle创建表
  10. oraclek导出表_全兼容Oracle?扒一扒浪潮K-DB是咋做的?