Python循环创建带可变参数的调度时参数传递异常问题
问题描述
下述脚本试图在两个指定时间配置调度任务,为每次运行传递独立参数,预期输出为1和2,但实际输出均为2,仅传递了最后一个变量。
import schedule, threading, time def run_script(n): # Check this output print(n) def run_threaded(job_func): job_thread = threading.Thread(target=job_func) job_thread.start() times = ["13:56", "13:56"] for n,row in enumerate(times, 1): schedule.every().day.at(row).do(run_threaded, lambda: run_script(n)) while True: schedule.run_pending() time.sleep(1)
若手动添加调度(不使用循环):
schedule.every().day.at("18:56").do(run_threaded, lambda: run_script(1)) schedule.every().day.at("18:56").do(run_threaded, lambda: run_script(2))
该方式可正常运行,但通过循环生成时结果不符,请问原因是什么?如何解决?
问题原因
这是Python中闭包的延迟绑定导致的问题。循环里的lambda并没有在定义时就捕获当前的n值,而是在实际被调用时才去查找n的当前值。当调度任务触发时,循环已经执行完毕,n的最终值是2,所以两个lambda都会使用这个最终值,导致输出都是2。
解决方法
有三种常见的解决方式:
1. 使用默认参数捕获当前值
在定义lambda时,通过默认参数的方式把当前的n值绑定进去,这样lambda在定义时就会保存当前的n值,而不是等到调用时再查找:
for n,row in enumerate(times, 1): schedule.every().day.at(row).do(run_threaded, lambda n=n: run_script(n))
2. 使用functools.partial固定参数
借助functools.partial来创建一个固定了参数的函数,避免闭包的延迟绑定问题:
from functools import partial # ... 其他代码不变 ... for n,row in enumerate(times, 1): schedule.every().day.at(row).do(run_threaded, partial(run_script, n))
3. 用嵌套函数捕获变量
创建一个嵌套函数,让它在每次循环时捕获当前的n值,返回对应的lambda:
# ... 其他代码不变 ... for n,row in enumerate(times, 1): def get_job_func(current_n): return lambda: run_script(current_n) schedule.every().day.at(row).do(run_threaded, get_job_func(n))
内容的提问来源于stack exchange,提问作者Roelof Coertze
相关产品推荐
相关产品推荐

