zoukankan      html  css  js  c++  java
  • celery 定时任务时间篇

    1、Celery加入定时任务

    Celery除了可以异步执行任务之外,还可以定时执行任务。在实例代码的基础上写个测试方法:

    复制代码
     1 #coding:utf-8
     2 from celery.task.schedules import crontab 
     3 from celery.decorators import periodic_task
     4 
     5 @periodic_task(run_every=crontab())
     6 def some_task():
     7 print('periodic task test!!!!!')
     8 time.sleep(5)
     9 print('success')
    10 return True
    复制代码

    该代码是每分钟执行一次some_task方法。

    启动celery是使用worker。但worker不能启动定时任务。启动方式如下:

    1)先确保中间人是否打开,我使用redis作为中间人。可参考Redis在CentOS和Windows安装过程

    2)进入django项目的根目录执行如下代码启动celery的worker:

    1 celery -A myproject worker -l info

    其中,myproject是我的django项目名称。

    当出现celery@xxx ready说明redis启动成功。

    有两个任务,其中一个myapp.tasks.sendmail添加的异步处理任务。myapp.tasks.some_task是本次的定时任务。

    3)同样在django项目的根目录下再打开一个命令行界面,执行如下代码:

    1 celery -A myproject beat -l info

    这个beat是检查定时任务,并启动定时任务丢给worker执行。

    可以稍微等待几分钟,多执行几次任务。如下图:

    上面的窗口是beat,下面的窗口是worker。可看到print的信息在worker中输出。

    我们甚至不用打开Django项目的服务器,就可以执行定时任务。 

    2、Celery定时任务时间设置

    若你觉得1分钟等待时间太长。可以设置为每10秒执行一次定时任务。将上面的periodic_task修改如下:

    1 @periodic_task(run_every=10)

    修改代码,需要重启Celery的worker和beat。

    这个run_every参数是设置定时任务的时间间隔或执行的时间。该参数设置有3种方式。

    1)直接设置秒数

    例如刚刚所说的10秒间隔,run_every=10,每10秒执行一次任务。1分钟即是60秒;1小时即是3600秒。

    2)通过datetime设置时间间隔

    有时直接设置秒数不方便,需要通过计算得到具体秒数。

    例如,1小时15分钟40秒 = 1*60*60 + 15*60 + 40。这种情况可读性也不高。

    可以采用datetime设置,代码如下:

    1 from celery.decorators import periodic_task
    2 import datetime
    3 
    4 @periodic_task(run_every=datetime.timedelta(hours=1, minutes=15, seconds=40))
    5 def some_task():
    6 print('periodic task test!!!!!')

    代码可读性明显提升,而且设置方便。

    但这种不能满足定时定点的时间设置。假如我想固定每天12点15分的时候,执行一次任务。datetime和直接设置秒数的方式都无法实现。这时得使用第3种方式。

    3)celery的crontab表达式

    crontab是比较完善,且稍微有点复杂(相对前面两种方式而言)的方式。可以实现我们各种设置时间的需求。

    例如,前面给出的代码:

    复制代码
    1 #coding:utf-8
    2 from celery.task.schedules import crontab 
    3 from celery.decorators import periodic_task
    4 
    5 @periodic_task(run_every=crontab())
    6 def some_task():
    7 print('periodic task test!!!!!'
    复制代码

    表示每分钟0秒时刻执行一次(后面不提这个0秒,大家都知道就行了,省点口水)。

    其中,crontab()实例化的时候没设置任何参数,都是使用默认值。crontab一共有7个参数,常用有5个参数分别为:

    minute:分钟,范围0-59;

    hour:小时,范围0-23;

    day_of_week:星期几,范围0-6。以星期天为开始,即0为星期天。这个星期几还可以使用英文缩写表示,例如“sun”表示星期天;

    day_of_month:每月第几号,范围1-31;

    month_of_year:月份,范围1-12。

    a、默认参数

    这些参数可以设置表达式,表达稍微复杂的设置。默认值都是"*"星号,代表任意时刻。即crontab()相当与:

    1 crontab(minute='*', hour='*', day_of_week='*', day_of_month='*', month_of_year='*')

    含义是每天、每小时、每分钟执行一次任务。这说法太反人类语言习惯,简单说就是每1分钟执行一次任务。

    b、具体某个值

    上面提到这些参数的取值范围。我们可以直接设置某个值。例如:

    1 crontab(minute=15)

    即每小时的15分时刻执行一次任务。直接指定某个时刻。以此类推可以设置每天0点0分时刻执行任务的设置如下:

    1 crontab(minute=0, hour=0)

    当然,也可以设置多个值。例如0分和30分执行一次任务:

    crontab(minute='0,30')

    这里使用字符串,用逗号隔开数值。这里的逗号是表示多个表达式or逻辑关系。

    c、设置范围

    设置范围也是设置多个值,例如指定9点到12点每个小时的每分钟执行任务。

    1 crontab(minute='*', hour='9-12')

    这里*号是默认值,可以省略如下:

    1 crontab(hour='9-12')

    上面提到逗号是or逻辑关系。拓展一下,指定9点到12点和20点中每分钟执行任务:

    1 crontab(hour='9-12,20')

    crontab的表达式越来越复杂了。celery还提供了一个类得到表达式解析结果,代码如下:

    1 from celery.task.schedules import crontab_parser
    2 r = crontab_parser(23, 0).parse('9-12,20')
    3 print(r)

    其中,crontab_parse是一个解析类。第1个参数是范围的最大值;第2个参数是范围的最小值。通过parse输入表达式,可得到表达式的解析结果:

    1 set([9, 10, 11, 12, 20])

    下面很多地方我们都可以通过该方法验证解析结果。

      

    d、设置间隔步长

    假如我要设置1、3、5、7、9、11月份每天每分钟执行任务,按照上面的做法可以设置如下:

    1 crontab(day_of_month='1,3,5,7,9,11')

    观察数据可以发现,都是间隔2的步长。需要设置的数字比较少,若数字比较多显得很麻烦。例如我想每间隔2分钟就执行一次任务,要写30个数字想想就觉得很麻烦。crontab表达式还提供了间隔的处理,例如:

    1 crontab(minute='*/2')
    2 crontab(minute='0-59/2') #效果等同上面

    这个/号不是除以的意思。相当与range的第3个参数,例如:

    1 range(0, 59+1, 2)

    差不多crontab表达式就这些,多举几个例子:

    复制代码
     1 #每2个小时中每分钟执行1次任务
     2 crontab(hour='*/2')
     3 
     4 #每3个小时的0分时刻执行1次任务
     5 #即[0,3,6,9,12,15,18,21]点0分
     6 crontab(minute=0, hour='*/3')
     7 
     8 #每3个小时或8点到12点的0分时刻执行1次任务
     9 #即[0,3,6,9,12,15,18,21]+[8,9,10,11,12]点0分
    10 crontab(minute=0, hour='*/3,8-12')
    11 
    12 #每个季度的第1个月中,每天每分钟执行1次任务
    13 #月份范围是1-12,每3个月为[1,4,7,10]
    14 crontab(month_of_year='*/3')
    15 
    16 #每月偶数天数的0点0分时刻执行1次任务
    17 crontab(minute=0, hour=0, day_of_month='2-31/2')
    18 
    19 #每年5月11号的0点0分时刻执行1次任务
    20 crontab(0, 0, day_of_month='11', month_of_year='5')
    复制代码
  • 相关阅读:
    PAT (Advanced Level) Practice 1055 The World's Richest (25 分) (结构体排序)
    PAT (Advanced Level) Practice 1036 Boys vs Girls (25 分)
    PAT (Advanced Level) Practice 1028 List Sorting (25 分) (自定义排序)
    PAT (Advanced Level) Practice 1035 Password (20 分)
    PAT (Advanced Level) Practice 1019 General Palindromic Number (20 分) (进制转换,回文数)
    PAT (Advanced Level) Practice 1120 Friend Numbers (20 分) (set)
    从零开始吧
    Python GUI编程(TKinter)(简易计算器)
    PAT 基础编程题目集 6-7 统计某类完全平方数 (20 分)
    PAT (Advanced Level) Practice 1152 Google Recruitment (20 分)
  • 原文地址:https://www.cnblogs.com/52forjie/p/9364135.html
Copyright © 2011-2022 走看看