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

浅谈Python库之asyncio

一、asyncio的介绍

  • asyncio是 Python 中用于编写异步 I/O(输入 / 输出)代码的库。它是在 Python 3.4 版本中引入的,主要基于协程(coroutine)的概念构建。在传统的同步编程中,程序在执行 I/O 操作(如读取文件、网络请求)时会被阻塞,等待操作完成后才能继续执行下一行代码。而asyncio允许程序在等待 I/O 操作时,将执行权交给其他任务,从而实现高效的并发执行。
  • 例如,在一个网络爬虫程序中,需要同时向多个网站发送请求获取数据。如果使用同步方式,每次请求都要等待前一个请求完成后才能开始,这会浪费大量时间在等待响应上。而使用asyncio,可以同时发起多个请求,当一个请求在等待服务器响应时,程序可以去处理其他请求,从而大大提高效率。

二、asyncio的特点

  • 异步非阻塞 I/O
    • asyncio的核心特点是实现了异步非阻塞的 I/O 操作。这意味着当一个 I/O 操作(如网络读取或写入、文件读取等)被发起后,程序不会等待这个操作完成,而是继续执行其他代码。当 I/O 操作完成时,通过事件循环(Event Loop)来通知相应的协程继续执行后续的操作。
    • 比如,在一个服务器应用程序中,当接收一个客户端的连接请求后,使用asyncio可以在等待客户端发送数据的过程中,同时处理其他已经连接的客户端的数据收发,而不是像传统的阻塞式 I/O 那样,一个客户端连接就会阻塞服务器对其他客户端的处理。
  • 基于协程的并发模型
    • 它以协程作为基本的并发单元。协程是一种轻量级的用户态线程,相比于传统的线程,协程的创建和切换成本更低。在asyncio中,协程通过async/await语法来定义和暂停 / 恢复执行。协程可以在等待 I/O 操作或者其他协程完成时暂停自己的执行,将执行权交给事件循环,当条件满足时又可以被事件循环唤醒继续执行。
    • 例如,有两个协程coroutine1coroutine2coroutine1在执行过程中发起了一个网络请求并等待响应,此时它可以通过await暂停执行,事件循环会切换到coroutine2执行,当网络请求的响应返回时,coroutine1又可以被唤醒继续处理响应数据。
  • 高效的事件循环机制
    • asyncio有一个高效的事件循环来管理和调度协程的执行。事件循环会不断地检查各种 I/O 事件(如套接字可读、可写等)以及定时器事件等,根据事件的状态来决定唤醒哪些协程执行。这个事件循环是单线程的,但通过异步 I/O 和协程的配合,可以实现类似多线程的并发效果,并且避免了多线程带来的一些复杂性,如锁竞争、上下文切换开销等。
    • 例如,在一个简单的异步 TCP 服务器中,事件循环会持续监听客户端的连接请求,当有新的连接时,它会创建一个新的协程来处理这个连接,并且在整个过程中不断地协调各个协程的执行,确保服务器能够高效地处理多个客户端的通信。

三、asyncio的使用

定义协程

  • 使用async关键字来定义协程函数。例如:
import asyncio

async def my_coroutine():
    print("Coroutine started")
    await asyncio.sleep(1)  # 模拟一个异步操作,暂停1秒
    print("Coroutine ended")
  • 在这个例子中,my_coroutine是一个协程函数。await asyncio.sleep(1)表示暂停协程的执行 1 秒,这个暂停期间,事件循环可以去执行其他协程。

运行协程

  • 协程函数需要通过事件循环来运行。通常有两种方式:
  • 方式一:直接运行协程(在 Python 3.7+)
asyncio.run(my_coroutine())

这种方式是最简单的,asyncio.run()函数会创建一个事件循环,运行协程,然后关闭事件循环。

方式二:手动创建和使用事件循环(适用于更复杂的场景)

loop = asyncio.get_event_loop()
try:
    loop.run_until_complete(my_coroutine())
finally:
    loop.close()

首先通过asyncio.get_event_loop()获取事件循环对象,然后使用loop.run_until_complete()来运行协程,直到协程完成。最后需要通过loop.close()关闭事件循环。

多个协程并发运行

  • 可以使用asyncio.gather()来同时运行多个协程。例如:
async def coroutine1():
    print("Coroutine 1 started")
    await asyncio.sleep(2)
    print("Coroutine 1 ended")

async def coroutine2():
    print("Coroutine 2 started")
    await asyncio.sleep(1)
    print("Coroutine 2 ended")

async def main():
    await asyncio.gather(coroutine1(), coroutine2())

asyncio.run(main())

在这个例子中,coroutine1coroutine2是两个协程,asyncio.gather()函数会并发地运行这两个协程。main协程通过await asyncio.gather()来等待这两个协程都完成。整个程序的执行顺序是先启动coroutine1coroutine2,然后coroutine2会先完成(因为它的等待时间asyncio.sleep(1)更短),最后coroutine1完成。


http://www.kler.cn/a/455094.html

相关文章:

  • 双闭环直流调速系统
  • 【模电刷题复习--选择】
  • Etcd注册中心基本实现
  • 基于BiTCN双向时间卷积网络实现电力负荷多元时序预测(PyTorch版)
  • LeetCode-最长回文子串(005)
  • Merry Christmas HTML
  • springboot499基于javaweb的城乡居民基本医疗信息管理系统(论文+源码)_kaic
  • layui多图上传,tp8后端接收处理
  • 【蓝桥杯】奇怪的捐赠
  • 【Artificial Intelligence篇】AI 携手人类:共铸未来创作新纪元
  • 去除 el-input 输入框的边框(element-ui@2.15.13)
  • 【模块系列】STM321.69TFT屏幕
  • windows C#-在查询中返回元素属性的子集
  • 原型链(Prototype Chain)入门
  • ITK-基于itkUnaryFunctorImageFilter实现图像反转
  • PDF书籍《手写调用链监控APM系统-Java版》第1章 开篇介绍
  • 前端 学习
  • Alma linux部署gitlab
  • Java 中 List 源码解析:深度剖析与实现
  • 机器学习1-简单神经网络
  • Go主协程如何等其余协程完再操作
  • 废品回收小程序:助力企业转型发展
  • Vue3 +Element-Plus el-select下拉菜单样式(局部生效)
  • vue 中 keep-alive 详解
  • C# 窗体应用程序嵌套web网页,基于谷歌浏览器内核(含源码)
  • 《机器学习》——利用OpenCV库中的KNN算法进行图像识别