python apscheduler不一致

时间:2016-01-20 09:52:12

标签: python scheduler blocking web.py apscheduler

我在 web.py 框架内使用 python apscheduler 运行调度程序。 函数 runserver 应该每天早上9点运行但是它不一致。 它运行的时间很长,但偶尔会跳过一天。

代码:

import web
from apscheduler.schedulers.blocking import BlockingScheduler #Blocking Scheduler

#URLs
urls = (
    '/startscheduler/','index',
    )

Nightlysched = BlockingScheduler()

@Nightlysched.scheduled_job('cron', hour=9)
def runserver():
    print 2+2 #doing some calculations here

#Main function to run the cron JOB
if __name__ == "__main__":
    Nightlysched.start() #stating the job
    app = web.application(urls, globals())
    app.run() 

将调度程序配置为每天在9.a.m运行的正确方法是什么?

2 个答案:

答案 0 :(得分:4)

APScheduler有宽限期,在此期间允许作业运行。如果由于某种原因调度程序繁忙和/或主机负载过高,APScheduler可能无法及时启动作业。

在这种情况下,如果在宽限期内无法启动作业,则该作业将被丢弃(如果已初始化Python日志记录,将记录解释性消息)。

取决于实际的根本原因:

  • 如果调度程序未能及时安排作业,您可以使用misfire_grace_time=None告诉APScheduler尽快安排作业,而不是丢弃它。
  • 默认情况下,只允许同时运行每个作业的一个实例。确保上一次运行已完成。通过在添加作业时使用max_instances关键字参数,可以设置调度程序将允许并发运行的特定作业的最大实例数。在这种情况下,您可能还需要使用coalesce=False。只有在工作时间超过24小时(在您的情况下)并且您接受两个工作实例可以同时运行时才执行此操作。
  • 如果有太多的作业在运行,但机器负载不是太高,则意味着您可以获得比并发运行的作业更多的作业。您可以尝试增加APScheduler executor 用于运行作业的线程池的大小(这取决于您的设置,请检查:http://apscheduler.readthedocs.org/en/latest/userguide.html)。

总之,我首先尝试misfire_grace_period

@Nightlysched.scheduled_job('cron', hour=9, misfire_grace_time=None)

但请注意,正如@Alex所提到的,我不明白为什么您的代码有效,因为对Nightlysched.start()的调用应该阻止并阻止您的Web应用程序运行。我想这是粘贴的代码,并不能真正代表您正在运行的内容。对我来说,看起来你应该使用像BackgroundScheduler这样的非阻塞调度程序。

答案 1 :(得分:0)

为了顺利执行,您还可以尝试 simple-scheduler。为什么?

  • 即使在<执行时间
  • 期间也能工作
  • 使用轻量级多处理
  • 适用于事件和递归函数
  • 可以同时安排任意数量的工作,而且不会错过任何一个。
  • 默认在后台工作(因此无需单独的代码,因此易于集成,例如烧瓶)
  • 可以使用不同的作业名称再次安排相同的功能
  • 如果执行失败,您可以自己设置重试次数
  • 每次尝试之间的持续时间也由您控制

示例:

from simple_scheduler.recurring import recurring_scheduler
from multiprocessing import Process

def f1():
    print("Hi")
    
def f2():
    print("...")

def run_processes():
    p1 = Process(target = f1)
    p1.start()
    p2 = Process(target = f2)
    p2.start()
    p1.join()
    p2.join()
    print("finished")

recurring_scheduler.add_job(target=run_processes,
                            period_in_seconds=5,
                            job_name="run_processes")
recurring_scheduler.job_summary()
recurring_scheduler.run()
recurring_scheduler.job_summary()