首页 > 数据库 > 数据库开发技术 > Python协程、异步IO与asyncio
Python,作为一门流行的编程语言,不仅具备清晰简洁的语法和强大的生态系统,还在异步编程领域拥有丰富而灵活的工具,其中包括协程、异步IO以及asyncio库。本文将深入探讨这些概念的本质,解释它们的原理,并通过实际示例演示如何应用它们,帮助我们更好地理解和利用Python的异步编程能力。
Python协程:
协程是一种轻量级的线程,用于非阻塞异步编程。
通过async和await关键字定义,使得函数可以在执行中暂停和恢复。
协程可以用于处理高并发的I/O密集型任务,而无需使用多线程或多进程的复杂性。
通常与异步IO一起使用,以实现高效的非阻塞IO操作。
异步IO:
异步IO是一种编程模型,用于处理非阻塞IO操作,以提高程序的并发性能。
它允许一个程序同时处理多个IO操作,而不需要等待每个IO操作完成。
在Python中,异步IO通常与协程一起使用,以实现高效的非阻塞IO编程。
asyncio:
asyncio是Python标准库中的异步IO库,用于编写基于协程的异步程序。
它提供了事件循环(event loop),用于调度和执行协程任务。
asyncio包含了许多工具和函数,用于处理异步IO操作,例如网络通信、文件IO等。
asyncio是Python中异步编程的核心库,可以用于构建高性能的异步应用程序,如Web服务器、聊天应用程序等。
协程是一种轻量级的线程,它允许函数在执行过程中暂停并恢复。与常规函数不同,协程具有多个入口点,可以在函数内部的任何位置暂停和继续执行。Python的协程通过async和await关键字来定义和管理。
在Python中,协程的基本概念如下:
async def:通过在函数定义前添加async关键字,可以将普通函数变成协程函数。协程函数可以在执行过程中暂停。
await:await关键字用于在协程中等待另一个协程或异步操作完成。当执行到await语句时,协程将暂停,直到等待的操作完成。
下面是一个简单的协程示例,演示了如何使用协程来实现异步任务:
import asyncioasync def hello(arg):print("Hello : ",arg)if arg == "SRE 1":await asyncio.sleep(2)else:await asyncio.sleep(1)print("World : ",arg)print("bingo!!")async def main():await asyncio.gather(hello("SRE 1"), hello("SRE 2"), hello("SRE 3"))asyncio.run(main())
运行可以看到日志
Hello : SRE 1Hello : SRE 2Hello : SRE 3World : SRE 2bingo!!World : SRE 3bingo!!World : SRE 1bingo!!
在这个示例中,hello函数是一个协程,通过await asyncio.sleep(1)来模拟一个耗时的操作。main函数使用await asyncio.gather()来同时运行多个协程。
异步IO是一种编程模型,用于处理非阻塞的IO操作。它使程序能够在执行IO操作时继续执行其他任务,而不必等待IO操作完成。
异步IO的核心概念包括:
非阻塞IO:异步IO允许执行非阻塞的IO操作,这意味着程序在等待IO完成时不会被阻塞。
事件循环:异步IO通常使用事件循环来管理协程和异步任务的调度。事件循环负责将协程放入等待IO的队列,并在IO完成时恢复它们的执行。
以下示例演示了如何使用异步IO进行文件读取操作:
import asyncio# 定义一个异步函数,模拟一个非阻塞的IO操作async def non_blocking_io_operation(arg):print("开始非阻塞IO操作")if arg == "task1":await asyncio.sleep(2) # 模拟IO操作,这里使用await来模拟异步操作else:await asyncio.sleep(5)print(f"完成调用:{arg} 的非阻塞IO操作")# 创建一个事件循环async def main():# 将非阻塞IO操作放入事件循环中task1 = asyncio.create_task(non_blocking_io_operation("task1"))task2 = asyncio.create_task(non_blocking_io_operation("task2"))# 等待所有任务完成await task1print("完成task1 IO执行!")await task2print("完成task2 IO执行!")# 启动事件循环if __name__ == "__main__":asyncio.run(main())
执行输出日志
开始非阻塞IO操作开始非阻塞IO操作完成调用:task1 的非阻塞IO操作完成task1 IO执行!完成调用:task2 的非阻塞IO操作完成task2 IO执行!
asyncio 是异步 I/O 的缩写。它是一个 Python 库,允许我们使用异步编程模型运行代码。这让我们可以同时处理多个 I/O 操作,同时仍然允许我们的应用程序保持响应能力。
Python 3.4 引入了 asyncio 库,Python 3.5 生成了 async 和await 关键字以方便地使用它。这些新增功能允许所谓的异步编程。
asyncio库的基本概念包括:
事件循环(Event Loop):事件循环是异步程序的核心,负责调度协程和处理异步任务的完成。
asyncio.run():这个函数用于运行主协程,它在Python 3.7及更高版本中可用。
asyncio.create_task():用于创建并调度协程任务。
以下示例展示了如何使用asyncio库来并发执行多个协程任务:
import asyncioasync def task1():print("into task1 ....")await asyncio.sleep(2)print("Task 1 completed")async def task2():print("into task2 ...")await asyncio.sleep(1)print("Task 2 completed")async def main():task1_handle = asyncio.create_task(task1())task2_handle = asyncio.create_task(task2())await task1_handleawait task2_handleasyncio.run(main())
在这个示例中,我们使用asyncio.create_task()创建了两个协程任务,并且可以并发执行它们。await关键字用于等待任务完成。
事件循环是 asyncio 应用程序的核心,负责处理所有正在运行的任务。事件循环支持多任务处理。当一个函数被挂起时,控制权返回到循环,然后循环找到另一个函数来启动或恢复。

loop = asyncio.get_event_loop()loop.run_until_complete(my_coroutine())loop.close()
示例
import asyncioimport timeasync def cor1():print("cor 1 started")for i in range(5):await asyncio.sleep(1.5)print("cor1", i)async def cor2():print("cor 2 started")for i in range(8):await asyncio.sleep(1)print("cor2", i)loop = asyncio.get_event_loop()cors = asyncio.wait([cor1(), cor2()])loop.run_until_complete(cors)
运行可以得到输出
cor 2 startedcor 1 startedcor2 0cor1 0cor2 1cor1 1cor2 2cor2 3cor1 2cor2 4cor1 3cor2 5cor2 6cor1 4cor2 7
任务用于同时调度协程。我们使用函数 create_task() 创建一个任务。使用此函数将协程包装到任务中。
示例
import asyncioimport timeasync def main():# 使用 asyncio.create_task() 方法创建任务task1 = asyncio.create_task(foo('task 1 run'))task2 = asyncio.create_task(foo('task 2 run'))print(f"started at {time.strftime('%X')}")# 等待所有任务执行完成await task1await task2print(f"finished at {time.strftime('%X')}")async def foo(text):print(text)await asyncio.sleep(1)asyncio.run(main())
得到输出
started at 17:35:47task 1 runtask 2 runfinished at 17:35:48
为了执行并发执行,我们使用函数 Gather 如下。可等待的 asyncio.gather(*aws, return_exceptions=False)
该函数采用任意数量的可等待项(协程、任务等)作为参数。
示例
import asyncio# 定义一个异步函数,用于打印文本并在每次打印后等待一段时间async def printing(task, text):while True:print(task, text)try:await asyncio.sleep(0.50) # 等待0.50秒,模拟异步操作except asyncio.CancelledError:break # 如果收到取消请求,跳出循环结束任务async def main():try:# 使用 asyncio.wait_for 设置一个超时时间为 3 秒,同时并发运行三个打印任务await asyncio.wait_for(asyncio.gather(printing("A", "task 1"),printing("B", "task 2"),printing("C", "task 3")), 3 # 超时时间设置为 3 秒)except asyncio.TimeoutError:print("Time over") # 如果超时,打印 "Time over" 提示asyncio.run(main())
得到输出
A task 1B task 2C task 3A task 1B task 2C task 3A task 1B task 2C task 3A task 1B task 2C task 3A task 1B task 2C task 3A task 1B task 2C task 3Time over_GatheringFuture exception was never retrievedfuture: <_GatheringFuture finished exception=CancelledError()>concurrent.futures._base.CancelledError
异步编程提高了应用程序性能和响应能力。Python 提供了支持异步编程的不同库。Asyncio允许我们使用 async/await 语法编写并发代码。Asyncio 由协程、任务、流、子进程、异常等高级 API 和事件循环、Futures、传输和协议等低级 API 组成。
原文作者:五分钟学SRE;如有侵权,请联系管理员删除。