Python 中理解 asyncio 的极简入门-1

360影视 国产动漫 2025-05-23 17:42 2

摘要:关于 asyncio 的文章和课程已经有很多了,为什么还要再写一篇呢?这篇文章的目标是用简单直接的方式解释 Python 中的异步编程概念。本文通过简单的示例探索 Python 的 asyncio API,帮助开发者快速上手。

关于 asyncio 的文章和课程已经有很多了,为什么还要再写一篇呢?这篇文章的目标是用简单直接的方式解释 Python 中的异步编程概念。本文通过简单的示例探索 Python 的 asyncio API,帮助开发者快速上手。

我在自己的项目中使用了 asyncio,并且很喜欢它用很少的代码就能实现并发的方式。希望你也会有同样的感受。

Python 的 asyncio 是一种基于协程的并发模型,它提供了一种优雅的构造,用于编写并发 Python 代码,而无需使用线程。设计并发解决方案的思维方式与传统的基于线程的方法不同。我们知道,线程(threading)主要用于处理 I/O 密集型任务,而多进程(multiprocessing)则适用于 CPU 密集型任务。

如果你曾经用 JavaScript 编程,所有的 ES6 和 Node.js 程序都在事件循环中执行。Python 通过允许开发者创建自定义循环以及在这些循环上调度函数,实现了相同的功能。

Python 的 asyncio 标准库允许开发者在开发并发程序时使用 async/await 语法。

asyncio 通常非常适合用于 I/O 密集型和高结构化的网络代码。

常见的 I/O 密集型处理用例包括:

指标收集系统聊天室实时在线游戏Python 中的流式处理

通常,Python 程序通过运行函数来处理输入值。类似地,在 asyncio 中,需要创建一种特殊的函数,称为协程(co-routines)使普通函数成为协程的关键是 async 关键字。让我们来看一个简单的加法函数,它将两个整数相加并返回结果。

# A normal functiondef add(x: int, y: int): return x + y# A co-routineasync def add(x: int, y: int): return x + y

当你用 async 关键字将一个函数标记为特殊函数时,事件循环就可以将这个函数作为协程(co-routines)执行。

import asyncio# A co-routineasync def add(x: int, y: int): return x + y# An event looploop = asyncio.get_event_loop# Pass the co-routine to the loopresult = loop.run_until_complete(add(3, 4))print(result) # Prints 7

在代码片段中,我们通过调用 asyncio.get_event_loop 方法创建一个新的事件循环。它返回一个可以执行协程的新循环。run_until_complete 方法隐含了三件事:

启动循环执行作为参数传递的协程(co-routines)停止循环

run_until_complete 方法返回协程完成后的值。这是一个创建协程并在事件循环上调度它的简单示例。

在下一节中,我们将看到如何调度多个协程。

如果我们多次调用 run_until_complete,这相当于以同步方式运行事件循环两次。因此,在下面的程序中,result1 和 result2 是同步发生的。

import asyncio # 导入 asyncio 模块,它提供了异步编程的基础设施# 定义一个协程函数# 协程是一种特殊的函数,可以在执行过程中暂停并稍后恢复async def add(x: int, y: int): return x + y # 简单的加法运算# 创建事件循环# 事件循环是异步编程的核心,它管理和调度所有协程的执行# 注意:这种方式在较新版本的 Python 中已被弃用,建议使用 asyncio.runloop = asyncio.get_event_loop# 依次执行两个协程# run_until_complete 方法接收一个协程并阻塞运行,直到协程执行完毕result1 = loop.run_until_complete(add(3, 4))result2 = loop.run_until_complete(add(5, 5))

在程序中,事件循环启动,然后执行第一个协程并停止。这个过程会重复执行第二个协程。这类似于两个函数依次运行的普通同步调用。处理过程如图所示:

如果我们需要将多个协程作为一批异步地调度到同一个事件循环上,可以这样做:

import asyncio # 导入 asyncio 模块,提供异步编程支持# 定义一个协程函数# 协程是可以在执行过程中暂停并稍后恢复的特殊函数async def add(x: int, y: int): return x + y # 简单的加法运算,返回两个数的和# 获取事件循环# 注意:这种方式在较新版本的 Python 中已被弃用,建议使用 asyncio.runloop = asyncio.get_event_loop# 创建一个调度协程的函数# 这个函数本身也是一个协程,可以使用 await 等待其他协程完成async def get_results: # 使用 await 关键字等待 add 协程完成并获取结果 # await 会暂停当前协程的执行,直到被等待的协程返回结果 result1 = await add(3, 4) result2 = await add(5, 5) print(result1, result2) # 打印结果:7 10 loop.stop # 停止事件循环的运行# 将 get_results 协程作为任务添加到事件循环中# create_task 会立即返回,不会等待协程完成# 任务会在事件循环运行时被调度执行loop.create_task(get_results)# 阻塞调用,会一直运行直到被 loop.stop 中断# run_forever 会持续运行事件循环,直到显式调用 stop 方法try: loop.run_foreverfinally: # 无论事件循环如何结束(正常退出或发生异常),都确保关闭事件循环 # close 会释放事件循环占用的资源,是良好的编程习惯 loop.close

上面的算法很简单:

获取事件循环使用 loop.run_forever 方法运行事件循环。该行会阻塞,直到有人调用 loop.stop 方法。一旦在未来调用了 loop.stop 方法,loop.close 将停止事件循环。从协程 get_results 创建一个任务,并将其调度到事件循环上。当 get_results 执行时,它使用 await 关键字将另外两个协程调度到循环上。await 语句会立即运行协程并返回结果。最后,在获取两个协程的结果后,我们停止事件循环(stop)。

整个过程如下图所示:

下一篇文章继续探讨 asyncio API 的开发实践,包括 asyncio 库提供的包装方法 asyncio.run、协程与任务的区别等等。

来源:架构笔记一点号

相关推荐