简介

在 Python 的异步编程世界中,await 是一个极为重要的关键字。它为处理异步操作提供了一种简洁且直观的方式,极大地提升了程序在处理 I/O 密集型任务时的效率。理解并掌握 await 的使用,对于编写高性能、响应式的 Python 程序至关重要。

目录

  1. 基础概念
  2. 使用方法
  3. 常见实践
  4. 最佳实践
  5. 小结
  6. 参考资料

基础概念

异步编程

异步编程允许程序在执行某些耗时操作(如 I/O 操作)时,不阻塞其他代码的执行。这样,程序可以在等待操作完成的同时,继续处理其他任务,从而提高整体的运行效率。

协程

协程是一种轻量级的并发模型,它允许程序在不同的执行点之间暂停和恢复。在 Python 中,协程通过 async def 定义的异步函数来创建。例如:

async def my_coroutine():
    print("Coroutine started")
    await asyncio.sleep(1)
    print("Coroutine resumed")

await 关键字

await 只能在 async def 定义的异步函数内部使用。它用于暂停异步函数的执行,直到等待的异步操作完成。await 后面通常跟着一个可等待对象,例如 asyncio.sleep() 返回的对象。

使用方法

简单示例

import asyncio

async def greet():
    print("Hello, ")
    await asyncio.sleep(1)
    print("world!")

async def main():
    await greet()

if __name__ == "__main__":
    asyncio.run(main())

在这个例子中,greet 是一个异步函数,await asyncio.sleep(1) 会暂停 greet 函数的执行 1 秒钟,然后继续执行后面的代码。asyncio.run(main()) 用于运行异步程序。

多个 await 操作

import asyncio

async 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 task1()
    await task2()

if __name__ == "__main__":
    asyncio.run(main())

这里,main 函数按顺序等待 task1task2 完成。每个任务在执行 await asyncio.sleep() 时会暂停,其他任务可以继续执行。

常见实践

并发执行任务

使用 asyncio.gather 可以并发执行多个异步任务。

import asyncio

async def task1():
    await asyncio.sleep(2)
    return "Task 1 result"

async def task2():
    await asyncio.sleep(1)
    return "Task 2 result"

async def main():
    results = await asyncio.gather(task1(), task2())
    print(results)

if __name__ == "__main__":
    asyncio.run(main())

asyncio.gather 会同时启动 task1task2,并等待它们都完成,最后返回所有任务的结果。

异步迭代器

在处理异步数据流时,可以使用异步迭代器。

import asyncio

async def async_generator():
    for i in range(3):
        await asyncio.sleep(1)
        yield i

async def main():
    async for value in async_generator():
        print(value)

if __name__ == "__main__":
    asyncio.run(main())

async for 用于遍历异步生成器,在每次迭代时等待生成器产生下一个值。

最佳实践

错误处理

在使用 await 时,要正确处理可能出现的异常。

import asyncio

async def risky_task():
    await asyncio.sleep(1)
    raise ValueError("Something went wrong")

async def main():
    try:
        await risky_task()
    except ValueError as e:
        print(f"Caught exception: {e}")

if __name__ == "__main__":
    asyncio.run(main())

资源管理

在异步操作中,要注意资源的正确获取和释放。例如,在处理数据库连接时:

import asyncio
import aiomysql

async def main():
    conn = await aiomysql.connect(host='127.0.0.1', port=3306, user='root', password='password', db='test')
    try:
        async with conn.cursor() as cur:
            await cur.execute("SELECT 1")
            result = await cur.fetchone()
            print(result)
    finally:
        conn.close()
        await conn.wait_closed()

if __name__ == "__main__":
    asyncio.run(main())

小结

await 是 Python 异步编程中的核心机制,它使得异步代码的编写更加简洁和直观。通过暂停异步函数的执行,await 允许程序在等待 I/O 操作完成时继续处理其他任务,从而提高程序的整体效率。在实际应用中,要注意正确使用 await 处理异步操作,包括并发任务、错误处理和资源管理等方面。

参考资料