向APScheduler处理函数传参失败,已尝试多种语法仍未解决
解决APScheduler向处理函数传递参数的问题
我来帮你理清楚你踩的这些坑——其实都是APScheduler add_job方法的参数格式没搞对,还有lambda闭包的小陷阱在作怪,咱们逐个拆解:
先看你每个尝试的问题所在:
第一种写法的错误:
scheduler.add_job(tick, 'date', [datetimes, texti], run_date)APScheduler的
add_job里,位置参数必须通过args关键字来传递,你直接把列表丢在第三个参数位置,会被框架误解成其他参数(比如kwargs的输入),这才抛出了字典更新的错误。得显式指定args才行。第二种写法的错误:
scheduler.add_job(lambda: tick(datetimes, texti), 'date', run_date)这里有俩问题:一是
run_date没加关键字,被当成args传给了lambda,但你的lambda根本没接受参数,自然报参数数量不匹配;二是闭包陷阱——循环里的datetimes和texti是引用,等任务执行时循环早就结束了,所有任务都会用最后一次循环的变量值,完全不是你想要的当前td对应的数据。第三种写法的错误:
scheduler.add_job(tick, 'date', run_date, kwargs={'datetimes':run_date, 'texti':td.text})第三个参数的位置是
args,你传了run_date就相当于args=(run_date,),而kwargs又传了datetimes和texti,这样datetimes同时出现在args和kwargs里,参数冲突自然报错。
正确的写法示例
方法1:用args传递位置参数
显式指定args参数列表,同时用run_date关键字标注执行时间:
scheduler.add_job(tick, 'date', args=[datetimes, texti], run_date=run_date)
方法2:用kwargs传递关键字参数
如果函数参数有明确名称,用kwargs会更清晰,可读性更强:
scheduler.add_job(tick, 'date', kwargs={'datetimes': datetimes, 'texti': texti}, run_date=run_date)
方法3:修正lambda闭包陷阱的写法(如果一定要用lambda)
把当前循环的变量作为lambda的默认参数,这样每次循环都会捕获当前值,不会被后续循环覆盖:
scheduler.add_job(lambda d=datetimes, t=texti: tick(d, t), 'date', run_date=run_date)
完整修正后的Schedule_reminders函数
def Schedule_reminders(): with app.test_request_context(): if os.environ.get("WERKZEUG_RUN_MAIN") == "true": # 解决Flask调试模式下重复初始化问题 scheduler = BackgroundScheduler() tds = Td.query.all() for td in tds: run_date = td.date +' '+ td.time +':00' datetimes = run_date texti = td.text # 选下面任意一种正确写法即可 # 写法1:args传递位置参数 scheduler.add_job(tick, 'date', args=[datetimes, texti], run_date=run_date) # 写法2:kwargs传递关键字参数 # scheduler.add_job(tick, 'date', kwargs={'datetimes': datetimes, 'texti': texti}, run_date=run_date) # 写法3:修正闭包问题的lambda # scheduler.add_job(lambda d=datetimes, t=texti: tick(d, t), 'date', run_date=run_date) scheduler.start()
另外提一句:你用date触发器指定run_date的思路是对的,只要参数格式正确就能正常工作啦。
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

