async def 是 Python 中用于定义异步函数(也称为协程函数)的关键字,它是异步编程(Asynchronous Programming)的核心。下面我将详细解释它的用法、适用场景以及注意事项。


一、async def 的基本用法

1. 定义异步函数

使用 async def 来定义一个异步函数(协程函数):

async def my_async_function():
    return "Hello"

2. 调用异步函数

异步函数不能直接像普通函数那样调用,而是需要通过事件循环(Event Loop)来运行。常见的方式有:

  • 使用 asyncio.run()(Python 3.7+):

import asyncio

async def main():
    result = await my_async_function()
    print(result)

asyncio.run(main())
  • 在另一个异步函数中用 await 调用:

async def main():
    result = await my_async_function()
    print(result)

3. await 关键字

在异步函数内部,用 await 来等待另一个异步操作完成(如网络请求、文件读写等):

async def fetch_data():
    # 模拟一个耗时的IO操作
    await asyncio.sleep(2)
    return "Data fetched"

二、适用场景

1. IO 密集型任务(高并发场景)

异步编程适用于需要处理大量 IO 操作(如网络请求、数据库查询、文件读写)的场景,因为在这些操作等待响应时,CPU 可以转去执行其他任务,从而提升效率。

典型例子

  • Web 服务器(如 FastAPI、Sanic)

  • 爬虫(并发请求多个URL)

  • 微服务间的通信

  • 数据库连接池

2. 高并发但低计算需求的场景

例如:同时处理成千上万个客户端连接(如聊天服务器、实时数据传输)。


三、不适用场景

1. CPU 密集型任务

如果任务需要大量计算(如数学计算、图像处理),异步编程并不会提升性能,因为 Python 的全局解释器锁(GIL)会限制多线程并行,而异步编程本质上仍然是单线程(通过任务切换实现并发)。
 对于 CPU 密集型任务,应该使用多进程(multiprocessing)。

2. 简单或低并发的程序

如果程序没有高并发需求,使用异步编程反而会增加代码复杂度,此时同步代码更直接。


四、实际代码示例

示例1:并发请求多个URL

import aiohttp
import asyncio

async def fetch_url(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            return await response.text()

async def main():
    urls = ["http://example.com", "http://example.org"]
    tasks = [fetch_url(url) for url in urls]
    results = await asyncio.gather(*tasks)  # 并发执行
    for result in results:
        print(result[:100])  # 打印部分内容

asyncio.run(main())

示例2:FastAPI 中的异步路由

from fastapi import FastAPI
import asyncio

app = FastAPI()

@app.get("/")
async def read_data():
    # 模拟异步数据库查询
    await asyncio.sleep(1)
    return {"message": "Hello World"}

五、常见误区

  1. 忘记加 await
    异步函数如果不加 await,实际上不会执行(只会返回一个协程对象)。

    # 错误:没有实际执行
    result = my_async_function()
    
    # 正确
    result = await my_async_function()
  2. 在同步函数中调用异步函数
    不能直接在同步函数中使用 await,必须通过事件循环调用(如 asyncio.run())。

  3. 阻塞事件循环
    避免在异步函数中调用同步的阻塞操作(如 time.sleep()),应该用异步版本(如 asyncio.sleep())。


六、总结

场景 推荐方式
IO 密集型高并发  async/await
CPU 密集型  用多进程
简单脚本  同步代码更直接

掌握 async def 后,你可以结合 aiohttp(异步HTTP)、aiomysql(异步MySQL)等库构建高性能应用。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐