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

Python asyncio loop.call_soon为何会出现数据覆盖问题?

为什么多次用loop.call_soon提交异步函数时参数会被覆盖?

这是Python里lambda在循环中捕获变量的经典陷阱,和asyncio本身关系不大,咱们一步步拆解来看:

首先看你的异步代码片段:

async def calling_func(self):
    for k, v in self.test_data.items():
        print("Sending", k, v)
        self.loop.call_soon(lambda: asyncio.ensure_future(self.do_something(k, v)))

这里的lambda表达式并没有立即捕获当前迭代的k和v的值,而是捕获了变量k和v的引用。当事件循环调度这些lambda执行时,for循环已经跑完了所有迭代,k和v都停留在最后一次循环的结果(也就是'c'和3),所以三个异步任务执行时,都会用这组最后的值,就出现了你看到的重复输出。

再看同步版本的代码:

def calling_func_sync(self):
    for k, v in self.test_data.items():
        print("Sending_sync", k, v)
        self.loop.call_soon(self.do_something_sync, k, v)

这里直接把k和v作为参数传给call_soon,call_soon会立即保存这些参数的当前值,等调度执行时用的是当时传入的副本,所以每个任务都拿到了对应迭代的正确参数,输出自然正常。

解决方法

这里有几种常用的方式避免这个陷阱:

方法1:给lambda添加默认参数捕获当前值

修改异步部分的lambda,用默认参数绑定当前迭代的k和v——默认参数会在定义lambda时就求值,确保每个lambda拿到的是当前迭代的副本:

async def calling_func(self):
    for k, v in self.test_data.items():
        print("Sending", k, v)
        self.loop.call_soon(lambda k=k, v=v: asyncio.ensure_future(self.do_something(k, v)))

方法2:使用functools.partial绑定参数

用functools.partial包装要执行的函数和参数,同样能确保每个任务拿到正确的参数:

from functools import partial

async def calling_func(self):
    for k, v in self.test_data.items():
        print("Sending", k, v)
        task = partial(asyncio.ensure_future, self.do_something(k, v))
        self.loop.call_soon(task)

方法3:封装成内部函数

把循环内的调度逻辑放到一个小函数里,每次调用时传入k和v,避免引用问题:

async def calling_func(self):
    def schedule_task(k, v):
        asyncio.ensure_future(self.do_something(k, v))
    
    for k, v in self.test_data.items():
        print("Sending", k, v)
        self.loop.call_soon(schedule_task, k, v)

修改后运行代码,输出就会和同步版本一致:

Sending a 1
Sending b 2
Sending c 3
Values a 1
Values b 2
Values c 3
Sending_sync a 1
Sending_sync b 2
Sending_sync c 3
Values_sync a 1
Values_sync b 2
Values_sync c 3

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:26:00