如何从apscheduler获取返回值?

时间:2019-04-02 20:28:02

标签: python apscheduler

我不太了解如何从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似乎并不了解该事件已在调度程序中运行。由于上一段中所述的线程,这似乎也很有意义。

任何有助于解决此问题的好方法!

3 个答案:

答案 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