使用schedule绑定列表时间值做定时调度时输出时间重复的问题排查
错误原因定位
你的脚本能在两个预设时间点正常触发任务,说明调度规则本身是对的,异常出在任务执行时的变量读取逻辑:
- 核心问题是Python闭包的晚绑定特性:
for循环里使用的n是模块全局变量,所有绑定到schedule的job函数,在注册时并不会把当时循环遍历到的n值固定下来,而是等函数真正被调用执行的时候,才去读取当前n的最终值。 - 当你把
times_input列表遍历完成后,循环变量n就停在了列表的最后一个元素'03:26'。所以不管哪个时间点的任务被触发,job读取到的n永远是这个最终值,最终导致两次打印的输出完全一样。 - 附带的无效代码:
job函数里写的global times_input没有任何实际作用,因为函数内部从来没有对times_input做赋值修改,这个声明完全多余。
修复方案
利用schedule库自带的任务参数传递能力,在注册任务的当下就把对应时间值固化到任务上下文中,从根源上避开共享循环变量的问题:
- 给
job函数增加一个入参,用来接收对应调度时间值 - 注册调度任务时,把当前循环的时间值作为实参传给
job函数
修复后的完整参考代码:
import schedule import time times_input = [ item for item in input( "Times (hh:mm) script will work. Space to add a new time (Eg: 10:30 15:59 23:12):\n:> " ).split() ] print(times_input) def job(run_time): print(f"I'm working...{run_time}") for n in times_input: # 把当前循环的n作为参数绑定到对应调度任务 schedule.every().day.at(n).do(job, n) while True: schedule.run_pending() time.sleep(1)
修复说明
schedule.every().day.at(n)这行逻辑本身没有问题,因为at()方法在调用时就把传入的时间字符串存成了固定的调度规则,所以两个时间点的触发是完全准确的。- 之前的问题只是
job函数在执行时读取了全局共享的循环变量,现在通过参数绑定的方式,每个任务都独立持有自己对应的时间值,触发时就会输出正确的对应时间。
内容的提问来源于stack exchange,提问作者barroso
相关产品推荐
相关产品推荐

