前言:协程又称微线程,英文名coroutine。协程是用户态的一种轻量级线程,是由用户程序自己控制调度。基于这一原理,协程能在单线程下实现并发。我们知道进程是操作系统分配资源的基本单位,线程是CPU任务调度和执行的最小单位。线程之间的切换是由于线程A遇到了等待操作(比如I/O阻塞)或者计算时间过长,由操作系统控制切换到另一线程B。而协程在遇到阻塞的时候,通过用户程序切换到另一协程,这个切换过程由程序控制,所以对操作系统来说是无感知的。相比较来说通过程序切换,比操作系统层面的切换,开销要小的多的多。

协程的优点

无需线程上下文切换的开销

无需原子操作(不会被线程调度机制打断的操作)锁定以及同步的开销

方便切换控制流,简化编程模型

适合高并发处理场景

协程的缺点

无法利用多核资源:协程的本质是单线程,需要和进程配合才能运行在多CPU上

进行阻塞(Blocking)操作(如I/O时)会阻塞掉整个程序

一、Gevent 基本使用

Gevent是一种协程的Python网络库,基于Greenlet封装了libevent事件循环的高层同步API。它让我们在不改变编程习惯的同时,用同步的方式写异步I/O的代码。使用Gevent编程性能确实要比用传统的线程高。

importgeventfrom gevent importmonkey

monkey.patch_all()importtime,datetimedeftest(tm):

time.sleep(tm)print('时间:{}'.format(datetime.datetime.now()))if __name__ =='__main__':

task=[]#分配10个任务

for i in range(10):

task.append(gevent.spawn(test,5))#阻塞主线程,直到所有协程运行完成

gevent.joinall(task)

二、monkey.patch_all

用过 gevent 的开发者都知道,在开头导入monkey.patch_all(),非常重要,会自动将 python 的一些标准模块替换成 gevent 框架,这个补丁其实存在着一些坑:

monkey.patch_all(),网上一般叫猴子补丁。如果使用了这个补丁,gevent 直接修改标准库里面大部分的阻塞式系统调用,包括 socket、ssl、threading 和 select 等模块,而变为协作式运行。有些地方使用标准库会由于打了补丁而出现奇怪的问题(比如会影响 multiprocessing 的运行)

和一些第三方库不兼容(比如不能兼容 kazoo)。若要运用到项目中,必须确保其他用到的网络库明确支持Gevent。

在实际情况中协程和进程的组合非常常见,两个结合可以大幅提升性能,但直接使用猴子补丁会导致进程运行出现问题。其实可以按以下办法解决,将 thread 置成 False,缺点是无法发挥 monkey.patch_all() 的全部性能:

importgeventfrom gevent importmonkey

monkey.patch_all(thread=False, socket=False, select=False)

三、Pool 限制并发

协程虽然是轻量级线程,但并发数达到一定量级后,会把系统的文件句柄数占光。所以需要通过 Pool 来限制并发数。

importgeventfrom gevent.pool importPoolfrom gevent importmonkey

monkey.patch_all()importtime,datetimedeftest(tm):

time.sleep(tm)print('时间:{}'.format(datetime.datetime.now()))if __name__ =='__main__':

task=[]#限制最大并发

pool = Pool(5)#分配100个任务,最大并发数为5

for i in range(100):

task.append(pool.spawn(test,5))

gevent.joinall(task)

运行结果:

时间:2020-11-20 17:08:15.625334时间:2020-11-20 17:08:15.625334时间:2020-11-20 17:08:15.625334时间:2020-11-20 17:08:15.625334时间:2020-11-20 17:08:15.625334时间:2020-11-20 17:08:20.626347时间:2020-11-20 17:08:20.626347时间:2020-11-20 17:08:20.626347时间:2020-11-20 17:08:20.626347时间:2020-11-20 17:08:20.626347时间:2020-11-20 17:08:25.627630时间:2020-11-20 17:08:25.627630时间:2020-11-20 17:08:25.627630时间:2020-11-20 17:08:25.627630时间:2020-11-20 17:08:25.627630。。。

结语:gevent 虽“好”,“好”是指编程方便,只要在开头使用 monkey.patch_all(),就能让你的同步代码享受到异步的性能。但坑也是存在的,所以复杂的业务场景不推荐使用 gevent,可以使用python 标准库中的 asyncio。

python gevent pool_python 协程编程之gevent相关推荐

  1. python并发框架 gevent_python并发编程之gevent协程(四)

    协程的含义就不再提,在py2和py3的早期版本中,python协程的主流实现方法是使用gevent模块.由于协程对于操作系统是无感知的,所以其切换需要程序员自己去完成. 系列文章 基于生成器的简单协程 ...

  2. Python并发之协程gevent基础(5)

    1,gevent介绍 gevent是第三方库,通过 greenlet 实现 coroutine,创建.调度的开销比 线程(thread) 还小,因此程序内部的 执行流 效率高. gevent 实现了 ...

  3. Python并发之协程gevent基础

    基本示例 from gevent import monkey monkey.patch_all() # 记住一定放在第一行,这里是打补丁的意思,time模块在使用协程gevent模块的时候,必须打补丁 ...

  4. python从网址爬图片协程_python 用 gevent 协程抓取海量网页

    python作为爬虫利器,抓网页的方式简洁明了.爬成百上千的网页,都可以很快爬完,但是如果网页数量上万呢?速度就不能忍受了. 这是一段爬取页面的函数,用了requests库:1 2 3 4 5impo ...

  5. Python浅谈gevent实现协程

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

  6. python3之协程(4)---gevent实现协程操作

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

  7. 网络编程基础--协程--greenlet切换---gevent自动识别 IO ---

    协程: 1 单线程来实现并发---协程: 协程:是单线程下的并发,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程, 即协程是由用户程序自己控制调度的 只 ...

  8. python中的协程(二)

    协程 1.协程: 单线程实现并发 在应用程序里控制多个任务的切换+保存状态 优点: 应用程序级别速度要远远高于操作系统的切换 缺点: 多个任务一旦有一个阻塞没有切,整个线程都阻塞在原地,该线程内的其他 ...

  9. python并发之协程_python并发编程之协程

    一 引子 本节的主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只有一个)情况下实现并发,为此我们需要先回顾下并发的本质:切换+保存状态 cpu正在运行一个任务,会在两种情况下切走去 ...

最新文章

  1. R语言all函数、any函数判断逻辑向量(logical vector)实战
  2. 广告基本知识-在线广告的市场
  3. linux 下启动mysql
  4. 重写navigationController的push方法后,出现卡顿现象
  5. oracle Merge 函数
  6. gis里创建要素面板怎么打开_周末技术流 | 基于GIS的地形可视化分析
  7. 小程序 | 基于WAMP的新闻网小程序开发(体验全栈式开发微信小程序)
  8. 业界:绿盟发布基于攻击链的威胁感知系统
  9. PowerDesigner 设计数据表(笔记)
  10. SpringCloud实战(三)集成Open-Feign实现远程⽅法调⽤
  11. 《⑨也懂系列:MinGW安装教程Ver.2》著名C/C++编译器GCC的Windows版本
  12. 机器学习入门-用Java实现简单感知机
  13. 充气泵方案设计-汽车打气泵PCBA
  14. linux ubuntu因为没有正常关机,导致开机出现gun grub
  15. 锐捷(三)清除交换机的虚拟化(VSU)配置
  16. 二叉平衡树(AVL树)详细理解
  17. office2010/2013/2016安装过程提示问题Office 16 Click-to-Run Extensibility Component
  18. 一文看懂:Android-Q版本在安全方面进行了哪些系统性改进
  19. java des 加密 单倍长_明明白白使用DES加密算法
  20. [原创]隐身斗篷简介及仿真

热门文章

  1. 浅析如何衡量程序员的生产效率
  2. 看上旷视又要投了?全面拆解阿里AI布局 | 人工智能观察
  3. js室内地图开发_室内地图 JavaScript API
  4. 高等数学学习笔记——第三十讲——柯西中值定理与洛必达法则
  5. Linux locate 作用,linux中的locate命令的详细解释
  6. 爬取boss直聘上面的数据遇见的问题解析,是真不难!
  7. Python实现一篇txt文章的词频统计:文件读取+字典
  8. 第1.4章 elasticsearch删除字段
  9. 功能安全之故障(fault),错误(error),失效(failure)
  10. 公式法和枚举法求满射函数的个数