You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python asyncio协程何时真正让出执行权?

Asyncio协程执行权让出的疑问解答

问题场景

我在研究Python的asyncio模块时,了解到需要通过await协程获取结果,且await时当前协程会把执行权交给事件循环,让其他就绪协程运行。结合以下代码示例,有两个疑问:

async def parse_data(idx,pool):
    await compute_and_fetch_data()
    # Do some work


async def compute_and_fetch_data(idx, pool):
    # 这里是CPU密集型计算任务,比如复杂运算并生成查询语句
    
    # 示例中硬编码查询语句
    query = "SELECT * FROM customers" 
    async with pool.acquire() as conn:
        async with conn.cursor() as cur:
            await cur.execute(query)
            result = await cur.fetchall()
            logger.info(f"Fetched result for query {idx+1} successfully.")
            return result

async def main():
    pool = await aiomysql.create_pool(host='localhost', user='user', password='password', db='laundry')
    asyncio.gather(parse_data(1, pool))

asyncio.run(main())

具体疑问

  1. 在parse_data协程中执行到await compute_and_fetch_data()时,是立即让出执行权给事件循环,还是先执行compute_and_fetch_data里的CPU密集型计算,直到该协程遇到数据库查询的await(耗时IO操作)时才让出执行权?
  2. 如果是后者,那“当前协程在遇到await关键字时让出执行权”的说法是否仍然成立?

解答

  • 执行权不会立即让出:当parse_data执行到await compute_and_fetch_data()时,它会暂停自身执行,转而启动compute_and_fetch_data协程的执行。此时事件循环并不会立刻接管,而是先跑完compute_and_fetch_data中所有非await的同步代码——也就是你写的CPU密集型计算部分,直到compute_and_fetch_data内部遇到第一个await(比如async with pool.acquire()里隐含的await操作,或者后面的await cur.execute(query)),这时候整个当前执行链才会把执行权交还给事件循环,让其他就绪协程运行。

  • 原说法仍然成立,但要准确理解:“当前协程遇到await时让出执行权”的表述没错,但这里的“当前协程”指的是正在运行的那个协程。当parse_data发起await时,它只是暂停自己,把执行权转移给被await的compute_and_fetch_data;而compute_and_fetch_data作为此时的“当前协程”,在自己内部遇到await时,才会触发执行权让出给事件循环。整个过程中,每一次await都是当前运行的协程在遇到它时暂停并交出执行权,只是外层协程的await是把执行权转给了子协程,而非直接给事件循环而已。


内容的提问来源于stack exchange,提问作者Rahul Gusai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 11:16:08