我不太了解如何从apscheduler中的预定作业中访问返回值。这项工作需要每天在不同的时间运行,我需要今天工作的回报值来安排明天的工作。
此链接(how to get return value from apscheduler jobs)似乎是此问题的最佳先前答案。它建议向调度程序添加一个侦听器。我已经添加了一个侦听器,但是我不确定如何访问它的返回值。我可以访问连接到调度程序的侦听器,但是无法访问它们的输出。当计划的作业运行时,将在下面的代码中显示侦听器job_runs()。
此外,我知道我需要访问一个JobExecutionEvent(https://apscheduler.readthedocs.io/en/latest/modules/events.html#module-apscheduler.events),该事件保存该函数的返回值。
首先,我要访问的函数是run_all(),在其中执行了一堆操作,但是对于测试用例,我只返回True。
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.events import EVENT_JOB_EXECUTED, EVENT_JOB_ERROR, JobExecutionEvent
from datetime import datetime, timedelta
import logging
def run_all():
return True
def job_runs(event): # listener function
if event.exception:
print('The job did not run')
else:
print('The job completed @ {}'.format(datetime.now()))
def job_return_val(event): # listener function
return event.retval
然后,我设置调度程序,添加侦听器,然后添加作业。将触发器设置为在将作业添加到计划程序后1分钟运行该功能。
scheduler = BackgroundScheduler()
scheduler.add_listener(job_runs, EVENT_JOB_EXECUTED | EVENT_JOB_ERROR)
scheduler.add_listener(job_return_val, EVENT_JOB_EXECUTED)
cron_args = datetime_to_dict(datetime.now() + timedelta(minutes=1))
job = scheduler.add_job(run_all, "cron", **cron_args)
接下来,我启动计划程序并打印计划的作业。此外,我设置了日志记录,因此我知道调度程序在哪里。
test = scheduler.start()
scheduler.print_jobs()
logging.basicConfig()
logging.getLogger('apscheduler').setLevel(logging.DEBUG)
启用日志记录后,计划程序会报告作业正在运行,并且已从计划程序中删除,正如我期望的那样。 job_runs()将正确的输出打印到控制台。通过断点,我知道调用了job_return_val()。但是,我不知道它将返回的值发送到哪里。该函数似乎是在另一个名为APScheduler的线程中调用的。我对线程了解不多,但这很有意义。但是,我不知道该线程的输出何时返回到主线程。
最后,我尝试使用可从调度程序和作业的属性访问的代码,job_id,jobstore和Scheduled_run_time实例化JobExceptionEvent,但是JobExceptionEvent似乎并不了解该事件已在调度程序中运行。由于上一段中所述的线程,这似乎也很有意义。
任何有助于解决此问题的好方法!
答案 0 :(得分:1)
您现在可以使用全局变量。举个例子:
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.triggers.cron import CronTrigger
def fn():
'''Increase `times` by one and print it.'''
global times
times += 1
print(times)
sched = BlockingScheduler()
times = 0
# Execute fn() each second.
sched.add_job(fn, trigger=CronTrigger(second='*/1'))
sched.start()
答案 1 :(得分:0)
在任何地方都没有使用listener的返回值(请参见code),因此无论如何都没有返回任何值。如果您需要根据上一个作业的值(通过事件对象在侦听器中获取)安排另一个作业,则必须在该侦听器中正确执行。
编辑:要说明如何做到(并证明可能),请参见以下示例代码:
from datetime import datetime
import time
from apscheduler.events import EVENT_JOB_ERROR, EVENT_JOB_EXECUTED
from apscheduler.schedulers.background import BackgroundScheduler
def tick():
print('Tick! The time is: %s' % datetime.now())
def tack():
print('Tack! The time is: %s' % datetime.now())
def listener(event):
if not event.exception:
job = scheduler.get_job(event.job_id)
if job.name == 'tick':
scheduler.add_job(tack)
if __name__ == '__main__':
scheduler = BackgroundScheduler()
scheduler.add_listener(listener, EVENT_JOB_EXECUTED | EVENT_JOB_ERROR)
scheduler.add_job(tick, 'interval', seconds=5)
scheduler.start()
try:
while True:
time.sleep(1)
except (KeyboardInterrupt, SystemExit):
scheduler.shutdown()
输出:
(venv) pasmen@nyx:~/tmp/x$ python test.py
Tick! The time is: 2019-04-03 19:51:29.192420
Tack! The time is: 2019-04-03 19:51:29.195878
Tick! The time is: 2019-04-03 19:51:34.193145
Tack! The time is: 2019-04-03 19:51:34.194898
Tick! The time is: 2019-04-03 19:51:39.193207
Tack! The time is: 2019-04-03 19:51:39.194868
Tick! The time is: 2019-04-03 19:51:44.193223
Tack! The time is: 2019-04-03 19:51:44.195066
...
答案 2 :(得分:0)
您需要执行stateful jobs feature。