当前位置: 首页 > news >正文

python 异步编程之协程

最近在学习python的异步编程,这里就简单记录一下,免得日后忘记。

首先,python异步实现大概有三种方式,多进程,多线程和协程;多线程和多进程就不用多说了,基本上每种语言都会有多进行和多线程的功能;而python异步编程的特点主要是协程。

多进程,多线程和协程其实从本质上来说都是为了提升程序的运行效率,节省资源;因此,三者没用好坏之分,只是不同的场景适合不同的任务。

比如多进程,计算机是以进程为单位进行资源划分的,每一个进程都有其独立的资源管理;而多线程是共享一份进程资源,而线程是CPU调度的最小单位。最后就是协程,协程首先是单线程的,只不过在一些耗时的任务中,单线程会等待任务的完成然后再执行下一步,而协程的作用就是提升单线程的执行效率,在等待的过程中可以继续执行别的任务。

为什么会有协程的出现? 

在传统的异步编程中,大都使用多进程或多线程进行任务的管理与调度,但进程和线程有一个很大的问题就是上下文切换,不论是进程还是线程;但CPU在切换上下文的时候,需要把当前线程或进程的资源进行存储——也就是入栈,而这是需要消耗系统资源的;因此为了提升资源的利用效率,协程就出现了;协程由于是单线程的,因此其就避免了线程切换的资源开销,而由于协程能够在等待任务执行的过程中去执行其它任务,因此其就间接实现了“伪多线程”,也叫做微线程。

那协程是怎么实现的呢?

在python之前的版本中,协程是通过greenlet和yield关键字实现的;而随着python3.4的发布,asyncio被引入进来,而且在之后的版本中又引入了await/async关键字,这使得python协程编程变得更简单,更高效。

在asyncio异步工具包中,有几个关键的词,协程-coroutine,任务-task,event loop-事件循环;

asyncio就是通过事件循环实现的协程,而协程和任务是其两个关键对象;协程对应两种情况——协程函数和协程对象,而async就是用来定义协程对象的;由async定义的函数就是协程函数。

而await关键字是用来,等待任务执行,并通知事件循环来进行任务调度。

async def hello():print("开始")print(f"started at {time.strftime('%X')}")await asyncio.sleep(10)print("协程")
asyncio.run(hello())

以上就是最简单的协程代码,但这里并没有实现真正的协程,函数还是会休眠十秒之后才会结束。

要想实现真正的协程,task-任务的作用就出现了;

async def fun():print("函数")await asyncio.sleep(3)print("函数完成")async def main():# await asyncio.sleep(3)print("主函数")print(f"started at {time.strftime('%X')}")task1 = asyncio.create_task(fun())task2 = asyncio.create_task(fun())await asyncio.gather(task1, task2)print(f"started at {time.strftime('%X')}")asyncio.run(main())

函数fun是一个协程函数,而在主函数中会使用asyncio.create_task函数创建两个任务,而asyncio.gather把两个任务纳入到事件循环的管理中,然后通过ayncio.run函数执行事件循环。

如下图所示,在同步编程中单线程执行fun函数,应该需要3+3六秒的时间才能执行完成;而使用了协程之后,只用了3秒就执行完成。

这就是协程的作用。

在python使用协程编程的过程中,主要使用的就是await/async和asyncio工具包;async用来定义协程函数,await配合async处理协程对象,asyncio用来调度和管理协程对象。

await只能在async关键字定义的函数或对象中使用。

使用async/await来创建协程函数,使用asyncio来创建任务,再用asyncio来执行任务。

http://www.lryc.cn/news/486123.html

相关文章:

  • 现代密码学|古典密码学例题讲解|AES数学基础(GF(2^8)有限域上的运算问题)| AES加密算法
  • 算法沉淀一:双指针
  • Word_小问题解决_1
  • 基于opencv制作GUI界面
  • 微服务即时通讯系统的实现(客户端)----(2)
  • QT使用libssh2库实现sftp文件传输
  • 【Linux】进程的优先级
  • python实现十进制转换二进制,tkinter界面
  • 电子应用设计方案-12:智能窗帘系统方案设计
  • 力扣 回文链表-234
  • 采样率22050,那么CHUNK_SIZE 一次传输的音频数据大小设置多少合适?unity接收后出现卡顿的问题的思路
  • 网络初识--Java
  • K8S单节点部署及集群部署
  • GPIO相关的寄存器(重要)
  • OpenCV基础
  • 两行命令搭建深度学习环境(Docker/torch2.5.1+cu118/命令行美化+插件),含完整的 Docker 安装步骤
  • Redis做分布式锁
  • lambdaQueryWrapper详细解释
  • 【工控】线扫相机小结 第三篇
  • golang中的init函数
  • 理解和选择Vue的组件风格:组合式API与选项式API详解
  • Java基础——高级技术
  • 什么是SSL VPN?其中的协议结构是怎样的?
  • 程序员高频率面试题-整理篇
  • 第二十二章 TCP 客户端 服务器通信 - TCP设备的OPEN和USE命令关键字
  • CSS 语法规范
  • Linux开发常用命令
  • Linux第92步_如何编写“设备树”下的platform设备驱动
  • 从零开始学习 sg200x 多核开发之 eth0 MAC 地址修改
  • JMeter与大模型融合应用之JMeter日志分析服务化实战应用