Python中 async await 使用汇总

在 Python 中,async 和 await 是 异步编程 的核心关键字,基于 asyncio 库实现协程(Coroutine),适用于高并发 I/O 密集型任务。以下是它们的 使用总结 和 典型场景:


一、核心概念

关键字作用
async 声明一个函数为 异步函数(协程),调用时返回协程对象,而非直接执行。
await 在异步函数中 挂起当前协程,等待另一个协程或异步操作完成。

二、基础语法

1. 定义异步函数

async def fetch_data():
    print("Start fetching")
    await asyncio.sleep(2)  # 模拟I/O操作
    print("Done fetching")
    return {"data": 123}

2. 调用异步函数

import asyncio

async def main():
    result = await fetch_data()  # 等待协程完成
    print(result)

asyncio.run(main())  # 运行入口

输出:

Start fetching
(等待2秒)
Done fetching
{'data': 123}

三、使用场景

1. 高并发网络请求

import aiohttp  # 异步HTTP库

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)  # 并发执行
    print(results)

2. 数据库异步操作

async def get_user(db, user_id):
    user = await db.fetch("SELECT * FROM users WHERE id = $1", user_id)
    return user

3. 与Web框架集成(如FastAPI)

from fastapi import FastAPI
import asyncio

app = FastAPI()

@app.get("/data")
async def get_data():
    await asyncio.sleep(1)  # 模拟异步操作
    return {"message": "Async data"}

4. 定时任务或事件循环

async def periodic_task():
    while True:
        print("Running task...")
        await asyncio.sleep(60)  # 每分钟执行一次

asyncio.create_task(periodic_task())  # 后台运行

四、关键注意事项

  1. await 必须在 async 函数内使用

    # 错误示例
    def sync_func():
        await fetch_data()  # SyntaxError
  2. 区分阻塞与非阻塞操作

    • 可 await 的操作:asyncio.sleep()aiohttp.get(), 异步数据库查询等。

    • 不可 await 的阻塞操作:time.sleep(), 同步文件读写(需用 asyncio.to_thread 或专用异步库)。

  3. 并发执行多个任务

    • asyncio.gather():并行运行多个协程,等待所有完成。

    • asyncio.create_task():后台启动协程,不阻塞当前代码。

  4. 错误处理

    async def safe_fetch():
        try:
            return await fetch_data()
        except Exception as e:
            print(f"Error: {e}")

五、性能对比(同步 vs 异步)

场景同步代码(线程/阻塞)异步代码(协程)
1000次网络请求 高内存消耗(线程切换开销) 低内存消耗(单线程并发)
响应时间 慢(线性等待) 快(重叠I/O等待时间)
适用场景 CPU密集型任务 I/O密集型任务(如HTTP、DB)

六、进阶技巧

  1. async def async_gen():
        for i in range(3):
            await asyncio.sleep(1)
            yield i
    
    async for item in async_gen():
        print(item)
  2. 超时控制

    try:
        await asyncio.wait_for(fetch_data(), timeout=3.0)
    except asyncio.TimeoutError:
        print("Timeout!")
  3. 同步与异步代码互调

    • 同步 → 异步:用 asyncio.run()(仅限入口)。

    • 异步 → 同步:用 asyncio.to_thread() 或 loop.run_in_executor()


七、总结

  • 何时用 async/await

    • 需要高并发处理 I/O 操作(如API调用、数据库查询)。

    • 避免线程/进程的开销(如C10k问题)。

    • 与异步生态兼容(如FastAPI、aiohttp、asyncpg)。

  • 何时不用?

    • 纯CPU密集型任务(用多进程 multiprocessing)。

    • 旧代码库或依赖同步库(需逐步迁移)。

掌握 async/await 可以显著提升I/O密集型应用的吞吐量,但需注意避免混合阻塞调用!

posted @ 2025-06-16 20:28  郭慕荣  阅读(401)  评论(0)    收藏  举报