Python 异步编程入门:理解 asyncio 和 await

03-18 15阅读

在现代软件开发中,异步编程已经成为处理高并发、I/O 密集型任务的关键技术之一。Python 作为一门广泛使用的编程语言,也提供了强大的异步编程支持,尤其是在 Python 3.4 之后引入了 asyncio 库,使得异步编程变得更加简单和直观。本文将深入探讨 Python 中的异步编程,介绍 asyncioawait 的基本概念,并通过代码示例演示如何使用它们来编写高效的异步程序。

1. 什么是异步编程?

在传统的同步编程模型中,程序按照顺序执行,每一步操作都会阻塞程序的执行,直到操作完成。例如,当程序执行一个网络请求时,它会等待服务器返回响应后才能继续执行下一步操作。这种阻塞式的编程模型在处理耗时操作时效率较低,尤其是在需要处理大量并发请求的场景中。

异步编程则是一种非阻塞的编程模型,程序可以在等待耗时操作完成的同时继续执行其他任务。这种方式可以显著提高程序的并发性能,尤其是在处理 I/O 密集型任务(如网络请求、文件读写等)时。

2. Python 中的异步编程

Python 提供了 asyncio 库来支持异步编程。asyncio 是 Python 标准库中的一个模块,它提供了一组工具来编写异步代码,包括事件循环、协程、任务和未来对象等。通过 asyncio,开发者可以轻松地编写高效的异步程序。

2.1 事件循环(Event Loop)

事件循环是 asyncio 的核心组件,它负责调度和执行异步任务。事件循环会不断地检查任务队列中的任务,并在任务完成时执行相应的回调函数。开发者可以通过 asyncio.get_event_loop() 获取当前的事件循环,并通过 loop.run_until_complete() 来运行异步任务。

2.2 协程(Coroutine)

协程是 Python 中用于实现异步编程的关键概念。协程是一种特殊的函数,它可以在执行过程中暂停并等待其他任务完成。在 Python 中,协程通过 async def 关键字定义,并通过 await 关键字来暂停执行,等待其他协程或异步操作完成。

2.3 await 关键字

await 关键字用于暂停协程的执行,直到指定的异步操作完成。await 后面通常跟着一个 awaitable 对象,如协程、任务或未来对象。当 await 遇到一个 awaitable 对象时,协程会暂停执行,并将控制权返回给事件循环,事件循环会继续调度其他任务。当 awaitable 对象完成后,协程会从暂停的地方继续执行。

3. 异步编程示例

下面通过一个简单的示例来演示如何使用 asyncioawait 编写异步程序。

3.1 简单的异步程序

import asyncioasync def say_hello():    print("Hello")    await asyncio.sleep(1)    print("World")async def main():    await say_hello()# 获取事件循环并运行主协程asyncio.run(main())

在这个示例中,say_hello 是一个协程,它首先打印 "Hello",然后通过 await asyncio.sleep(1) 暂停 1 秒钟,最后打印 "World"。main 协程调用了 say_hello 协程,并通过 asyncio.run(main()) 来运行主协程。

3.2 并发执行多个协程

在异步编程中,我们通常需要同时执行多个协程,以提高程序的并发性能。asyncio 提供了 asyncio.gather() 函数来并发执行多个协程。

import asyncioasync def task1():    print("Task 1 started")    await asyncio.sleep(2)    print("Task 1 completed")async def task2():    print("Task 2 started")    await asyncio.sleep(1)    print("Task 2 completed")async def main():    await asyncio.gather(task1(), task2())# 获取事件循环并运行主协程asyncio.run(main())

在这个示例中,task1task2 是两个协程,它们分别暂停 2 秒和 1 秒。main 协程通过 asyncio.gather() 并发执行这两个协程。由于 task2 的暂停时间较短,它会先于 task1 完成。

3.3 使用 asyncio.create_task() 创建任务

除了使用 asyncio.gather(),我们还可以通过 asyncio.create_task() 来创建任务并并发执行。

import asyncioasync def task1():    print("Task 1 started")    await asyncio.sleep(2)    print("Task 1 completed")async def task2():    print("Task 2 started")    await asyncio.sleep(1)    print("Task 2 completed")async def main():    t1 = asyncio.create_task(task1())    t2 = asyncio.create_task(task2())    await t1    await t2# 获取事件循环并运行主协程asyncio.run(main())

在这个示例中,main 协程通过 asyncio.create_task() 创建了两个任务 t1t2,并通过 await 等待它们完成。task1task2 会并发执行,task2 会先于 task1 完成。

4. 异步编程中的异常处理

在异步编程中,异常处理同样重要。asyncio 提供了多种方式来处理协程中的异常。

4.1 使用 try-except 捕获异常

与同步编程类似,我们可以在协程中使用 try-except 来捕获并处理异常。

import asyncioasync def faulty_task():    print("Faulty task started")    await asyncio.sleep(1)    raise ValueError("Something went wrong")async def main():    try:        await faulty_task()    except ValueError as e:        print(f"Caught an exception: {e}")# 获取事件循环并运行主协程asyncio.run(main())

在这个示例中,faulty_task 协程在暂停 1 秒后抛出了一个 ValueError 异常。main 协程通过 try-except 捕获并处理了这个异常。

4.2 使用 asyncio.wait() 处理多个任务的异常

当并发执行多个任务时,我们可以使用 asyncio.wait() 来捕获并处理任务中的异常。

import asyncioasync def task1():    print("Task 1 started")    await asyncio.sleep(2)    print("Task 1 completed")async def task2():    print("Task 2 started")    await asyncio.sleep(1)    raise ValueError("Task 2 failed")async def main():    tasks = [asyncio.create_task(task1()), asyncio.create_task(task2())]    done, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_EXCEPTION)    for task in done:        if task.exception():            print(f"Task failed: {task.exception()}")# 获取事件循环并运行主协程asyncio.run(main())

在这个示例中,task2 协程在执行过程中抛出了一个 ValueError 异常。main 协程通过 asyncio.wait() 捕获了这个异常,并打印了错误信息。

5. 总结

异步编程是 Python 中处理高并发、I/O 密集型任务的重要技术。通过 asyncioawait,开发者可以轻松地编写高效的异步程序。本文介绍了 asyncio 的基本概念,并通过代码示例演示了如何使用 asyncioawait 来编写异步程序。希望本文能帮助你更好地理解 Python 中的异步编程,并在实际项目中应用这些技术。

免责声明:本文来自网站作者,不代表CIUIC的观点和立场,本站所发布的一切资源仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。客服邮箱:ciuic@ciuic.com

目录[+]

您是本站第231名访客 今日有32篇新文章

微信号复制成功

打开微信,点击右上角"+"号,添加朋友,粘贴微信号,搜索即可!