zoukankan      html  css  js  c++  java
  • python中的轻量级定时任务调度库:schedule

    提到定时任务调度的时候,相信很多人会想到芹菜celery,要么就写个脚本塞到crontab中。不过,一个小的定时脚本,要用celery的话太“重”了。所以,我找到了一个轻量级的定时任务调度的库:schedule。
    schedule库是一个轻量级的定时任务方案,优势是使用简单,也不需要做什么配置;缺点是无法动态添加任务,也无法将任务持久化。
     
    库的安装还是最简单的pip install schedule,使用起来也是很容易理解的。我们从最简单的栗子看起:
    import schedule
    import time
     
    def job():
        print("I'm working...")
     
    schedule.every(10).minutes.do(job)
    schedule.every().hour.do(job)
    schedule.every().day.at("10:30").do(job)
    schedule.every(5).to(10).days.do(job)
    schedule.every().monday.do(job)
    schedule.every().wednesday.at("13:15").do(job)
     
    while True:
        schedule.run_pending()
        time.sleep(1)
    这是在pypi上面给出的示例。这个栗子简单到我不需要怎么解释。而且,通过这个栗子,我们也可以知道,schedule其实就只是个定时器。在while True死循环中,schedule.run_pending()是保持schedule一直运行,去查询上面那一堆的任务,在任务中,就可以设置不同的时间去运行。跟crontab是类似的。
     
    但是,如果是多个任务运行的话,实际上它们是按照顺序从上往下挨个执行的。如果上面的任务比较复杂,会影响到下面任务的运行时间。比如我们这样:
    import datetime
    import schedule
    import time
     
    def job1():
        print("I'm working for job1")
        time.sleep(2)
        print("job1:", datetime.datetime.now())
     
    def job2():
        print("I'm working for job2")
        time.sleep(2)
        print("job2:", datetime.datetime.now())
     
    def run():
        schedule.every(10).seconds.do(job1)
        schedule.every(10).seconds.do(job2)
     
        while True:
            schedule.run_pending()
            time.sleep(1)
    接下来你就会发现,两个定时任务并不是10秒运行一次,而是12秒。是的。由于job1和job2本身的执行时间,导致任务延迟了。
     
    其实解决方法也很简单:用多线程/多进程。不要幼稚地问我“python中的多线程不是没有用吗?”这是两码事。开了一条线程,就把job独立出去运行了,不会占主进程的cpu时间,schedule并没有花掉执行一个任务的时间,它的开销只是开启一条线程的时间,所以,下一次执行就变成了10秒后而不是12秒后。
     
    import datetime
    import schedule
    import threading
    import time
     
    def job1():
        print("I'm working for job1")
        time.sleep(2)
        print("job1:", datetime.datetime.now())
     
    def job2():
        print("I'm working for job2")
        time.sleep(2)
        print("job2:", datetime.datetime.now())
     
    def job1_task():
        threading.Thread(target=job1).start()
     
    def job2_task():
        threading.Thread(target=job2).start()
     
    def run():
        schedule.every(10).seconds.do(job1_task)
        schedule.every(10).seconds.do(job2_task)
     
        while True:
            schedule.run_pending()
            time.sleep(1)
    就是这么简单。
     
    唯一要注意的是,这里面job不应当是死循环类型的,也就是说,这个线程应该有一个执行完毕的出口。一是因为线程万一僵死,会是非常棘手的问题;二是下一次定时任务还会开启一个新的线程,执行次数多了就会演变成灾难。如果schedule的时间间隔设置得比job执行的时间短,一样会线程堆积形成灾难,所以,还是需要注意一下的。
     
    schedule这个库使用起来比较简单,内容不是很多。我这里介绍的大概用法基本上够用了,还想了解其他特性的话,可以参考官网:https://schedule.readthedocs.io/en/stable/
  • 相关阅读:
    Linkerd 2.10(Step by Step)—将 GitOps 与 Linkerd 和 Argo CD 结合使用
    Linkerd 2.10(Step by Step)—多集群通信
    Linkerd 2.10(Step by Step)—使用 Kustomize 自定义 Linkerd 的配置
    Linkerd 2.10(Step by Step)—控制平面调试端点
    Linkerd 2.10(Step by Step)—配置超时
    Linkerd 2.10(Step by Step)—配置重试
    Linkerd 2.10(Step by Step)—配置代理并发
    本地正常运行,线上环境诡异异常原因集合
    Need to invoke method 'xxx' declared on target class 'yyy', but not found in any interface(s) of the exposed proxy type
    alpine 安装常用命令
  • 原文地址:https://www.cnblogs.com/leijiangtao/p/4453901.html
Copyright © 2011-2022 走看看