目录

  • 十二、Python中协程
    • 12.1 协程的定义
    • 12.2 协程
    • 12.3 协程池
    • 12.4 总结

十二、Python中协程

12.1 协程的定义

协程(Coroutine):是一种比线程更加轻量级的存在,也称微线程,协程可以理解为一个特殊的函数,这个函数可以在某个地方挂起去执行别的,并且可以返回挂起处继续执行,线程数量越多协程的性能优势越明显,多进程和协程的组合能充分利用计算机的多核处理。

12.2 协程

Python对协程的支持常用的有yieldgreenlet gevent三种方式,进行协程的调用。

yeild 演示如下 -

from time import sleepdef study_math():for _ in range(5):print("study_math")yieldsleep(0.5)def study_chemisty():for _ in range(5):print("study_chemisty")yieldsleep(0.5)def main():study1 = study_math()study2 = study_chemisty()for _ in range(3):study1.__next__()study2.__next__()if __name__ == '__main__':main()

上面脚本的执行结果 -

study_math
study_chemisty
study_math
study_chemisty
study_math
study_chemisty

greenlet 演示如下 -

对协程进行简单封装,该模块需要重新安装,在cmd命令行长输入“pin install greenlet ”即可

from time import sleep
from greenlet import greenletdef study_math():for _ in range(3):print("study_math")glt2.switch()sleep(0.5)def study_chemisty():for _ in range(3):print("study_chemisty")glt1.switch()sleep(0.5)glt1 = greenlet(study_math)
glt2 = greenlet(study_chemisty)
glt1.switch()
glt2.switch()

上面脚本的执行结果 -

study_math
study_chemisty
study_math
study_chemisty
study_math
study_chemisty

gevent 演示如下 -

greenlet虽然实现协程,但需要手动切换,相当麻烦;这里提供gevent自动切换,在cmd命令行长输入“pin install gevent”即可。

在gevent协程中,协程只有遇到gevent指定类型的阻塞才能跳转到其他协程,因此,我们希望将普通的IO阻塞行为转换为可以触发gevent协程跳转的阻塞,以提高执行效率。

这里重点介绍 monkey 函数

from gevent import monkey
import gevent
from urllib.request import urlopenmonkey.patch_all()def f(url):print('GET: %s' % url)resp = urlopen(url)data = resp.read()print('%d bytes received from %s.' % (len(data), url))if __name__ == '__main__':gevent.joinall([gevent.spawn(f, 'https://www.tianya.cn'),gevent.spawn(f, 'https://www.yahoo.com/'),gevent.spawn(f, 'https://www.baidu.com/'),])

上面脚本的执行结果 -

GET: https://www.tianya.cn
GET: https://www.yahoo.com/
GET: https://www.baidu.com/
227 bytes received from https://www.baidu.com/.
7646 bytes received from https://www.tianya.cn.
3369 bytes received from https://www.yahoo.com/.

12.3 协程池

gevent 常用方法如下 -

名称 说明
gevent.spawn() 创建一个普通的Greenlet对象并切换
gevent.spawn_later(seconds=3) 延时创建一个普通的Greenlet对象并切换
gevent.spawn_raw() 创建的协程对象属于一个组
gevent.getcurrent() 返回当前正在执行的greenlet
gevent.joinall(jobs) 将协程任务添加到事件循环,接收一个任务列表
gevent.wait() 可以替代join函数等待循环结束,也可以传入协程对象列表
gevent.kill() 杀死一个协程
gevent.killall() 杀死一个协程列表里的所有协程
monkey.patch_all() 非常重要,自动将 python 的一些标准模块替换成 gevent 框架设置强制切换的时间
sys.setcheckinterval(n) 每n条执行尝试进行线程切换,n必须是int
sys.getswitchinterval() 默认5ms切换
名称 说明
job Greenlet(target0, 3) Greenlet对象创建
job.start() 将协程加入循环并启动协程
job.start_later(3) 延时启动
job.join() 等待任务完成
job.get() 获取协程返回的值
job.dead() 判断协程是否死亡
job.kill() 杀死正在运行的协程并唤醒其他的协程,这个协程将不会再执行
job.ready() 任务完成返回一个真值
job.successful() 任务成功完成返回真值,否则抛出错误
job.loop 时间循环对象
job.value 获取返回的值
job.exception 如果运行有错误,获取它异常信息
import gevent
from gevent import socket
from gevent.pool import PoolN = 1000
# limit ourselves to max 10 simultaneous outstanding requests
pool = Pool(2)
finished = 0def job(url):global finishedtry:try:ip = socket.gethostbyname(url)print("{url} = {ip}")except socket.gaierror as e:print(f"{url} failed with {e}")finally:finished += 1with open("urls.txt", 'r') as f:with gevent.Timeout(10, False):for x in f:line = x.rstrip('\r\n')pool.spawn(job, f"{line}")pool.join()print(f"finished within 10 seconds: {finished}/{N}")

12.4 总结

协程常用于IO密集型工作,例如网络资源请求等;而进程、线程常用于计算密集型工作,例如科学计算、人工神经网络等。

【Python】【入门篇】十二、Python中协程相关推荐

  1. Python入门篇(二)

    这篇主要是讲解类,Pythong类中私有属性.私有方法.动态添加属性.动态添加方法.多继承.静态方法写个存取款方法. 一.面向对象思想.简单的银行存取方法实现 class Bank:def __ini ...

  2. 老鱼Python数据分析——篇十二:使用selenium+BeautifulSoup获取淘股吧数据

    在淘股吧发现有位大牛每天都有数据整理,地址:湖南人的博客 所以直接下载他的博客文章即可. 分析发现,他复盘的数据都是使用的图片,所以只需要把博客文章里面的图片下载到本地. 第一步:分析首页数据: 通过 ...

  3. 多态(Python入门三十二)

    面向对象的三大特征之一(多态) - 多态是面向对象的三大特征之一        多态从字面上理解是多种形态        狗(狼狗.藏獒.哈士奇.古牧 ...)        一个对象可以以不同的形态 ...

  4. [Python图像处理] 四十二.Python图像锐化及边缘检测万字详解(Roberts、Prewitt、Sobel、Laplacian、Canny、LOG)

    该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门.OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子.图像增强技术.图像分割等,后期结合深度学习研究图像识别 ...

  5. 【python入门篇——16】Python函数详解(函数定义,参数种类、返回值、作用域等)

    一 函数 定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可 特性: 1.代码重用2.保持一致性3.可扩展性 二 函数的创建 2.1 格式: Pyt ...

  6. 快速入门 | 篇十二:正运动技术运动控制器U盘接口的使用​

    之前正运动技术与大家分享了,运动控制器的固件升级.ZBasic程序开发.ZPLC程序开发.与触摸屏通讯和输入/输出IO的应用.运动控制器数据与存储的应用.运动控制器ZCAN.EtherCAT总线的使用 ...

  7. python自学篇十[ 面向对象 (四) :王者荣耀小游戏+模拟一个简单的银行进行业务办理的类]

    python基础系列: python自学篇一[ Anaconda3安装 ] python自学篇二[ pycharm安装及使用 ] python自学篇三[ 判断语句if的使用 ] python自学篇四[ ...

  8. Python入门篇-生成器函数

    Python入门篇-生成器函数 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.生成器概述 1>.生成器generator 生成器指的是生成器对象,可以由生成器表达式得到, ...

  9. Python入门篇-数据结构堆排序Heap Sort

    Python入门篇-数据结构堆排序Heap Sort 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.堆Heap 堆是一个完全二叉树每个非叶子结点都要大于或者等于其左右孩子结点的 ...

最新文章

  1. Java并发编程:JMM和volatile关键字
  2. 一张心酸得不想起名字的照片,人艰就别拆了好吗 | 每日趣闻
  3. PlistBuddy简单使用
  4. 一文了解树在前端中的应用,掌握数据结构中树的生命线
  5. LeetCode 1209. 删除字符串中的所有相邻重复项 II(栈)
  6. LeetCode 77. 组合(回溯)
  7. php限制注册频率,php如何限制某个ip提交的次数
  8. dy96 .pw cc 05.php,05.php · 熟悉的陌生/php - Gitee.com
  9. {转}Java 字符串分割三种方法
  10. 使用PCL从CAD模型中提取不同视角下的点云
  11. 基于51单片机直流电机PWM控制器设计
  12. java模板引擎 jade_jade模板引擎
  13. java生成随机数的代码_java生成随机数的代码
  14. Elasticsearch(ES)创建索引
  15. Unity3D手游开发实践《腾讯桌球》客户端开发经验总结(转自GameRes游资网)
  16. 袁国宝:董明珠的小倔强!
  17. 图像分类经典卷积神经网络—SENet论文翻译(纯中文版)—Squeeze-and-Excitation Networks(挤压和激励网络)
  18. 电子签核系统的设计(一) - Requirements / Design
  19. Reference counted Objects (引用计数对象) - 文章翻译
  20. ghost系统后只有一个盘了别的分区的数据怎样恢复

热门文章

  1. IOS之RSA加密解密与后台之间的双向加密详解
  2. Mac 下解压NDK .bin文件
  3. 1-1 Aruba OS 8.x 双控制器冗余架构-Standalone 2020
  4. 写一个简单的Java界面程序
  5. 到底啥是平台,到底啥是中台?李鬼太多,不得不说(ZT)
  6. java程序实现给图片添加logo
  7. aj-report 报表设计器如何添加组件
  8. 中文日期格式转成英文日期格式
  9. 微信公众号消息推送【专属早安】,五分钟快速实现,不会编程也可以 【--网站已修复】
  10. 微博服务器为什么会宕机?这几年为什么极少再宕机了?