celery 学习笔记定时任务和异步任务
1、Celery加入異步和定時(shí)任務(wù)
Celery除了可以異步執(zhí)行任務(wù)之外,還可以定時(shí)執(zhí)行任務(wù)。在實(shí)例代碼的基礎(chǔ)上寫(xiě)個(gè)測(cè)試方法:
import datetime import timefrom celery import shared_task from celery.schedules import crontab from celery.task import periodic_taskfrom FruitGP2.utils import send_active_email@shared_task def send_activate_email_async(username,to_email):send_active_email(username,to_email)@periodic_task(run_every=datetime.timedelta(hours=1, minutes=15, seconds=40)) @periodic_task(run_every=10) def some_task():print('periodic task test!!!!!')# celery -A FruitShopGP2 beat -l info # celery -A FruitShopGP2 worker -l info# @periodic_task(run_every=crontab()) # def some_task(): # print('periodic task test!!!!!') # print('success')settings.py
# Celery settingsCELERY_BROKER_URL = 'redis://:@localhost:6379/0'#: Only add pickle to this list if your broker is secured #: from unwanted access (see userguide/security.html) CELERY_ACCEPT_CONTENT = ['json'] # CELERY_RESULT_BACKEND = 'db+sqlite:///results.sqlite' CELERY_RESULT_BACKEND = 'django-db' CELERY_TASK_SERIALIZER = 'json'celery.py
from __future__ import absolute_import, unicode_literalsimport osfrom celery import Celery# set the default Django settings module for the 'celery' program. os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'FruitShopGP2.settings')app = Celery('FruitShopGP2')# Using a string here means the worker doesn't have to serialize # the configuration object to child processes. # - namespace='CELERY' means all celery-related configuration keys # should have a `CELERY_` prefix. app.config_from_object('django.conf:settings', namespace='CELERY')# Load task modules from all registered Django app configs. app.autodiscover_tasks()@app.task(bind=True) def debug_task(self):print('Request: {0!r}'.format(self.request))?
該代碼是每分鐘執(zhí)行一次some_task方法。
啟動(dòng)celery是使用worker。但worker不能啟動(dòng)定時(shí)任務(wù)。啟動(dòng)方式如下:
1)先確保中間人是否打開(kāi),我使用redis作為中間人??蓞⒖?/p>
http://docs.celeryproject.org/en/master/getting-started/first-steps-with-celery.html#redis
https://github.com/celery/celery/blob/master/examples/django/proj/settings.py
2)進(jìn)入django項(xiàng)目的根目錄執(zhí)行如下代碼啟動(dòng)celery的worker:
celery -A FruitShopGP2 worker -l info其中,myproject是我的django項(xiàng)目名稱。
當(dāng)出現(xiàn)celery@xxx ready說(shuō)明redis啟動(dòng)成功。
有兩個(gè)任務(wù),其中一個(gè)myapp.tasks.sendmail添加的異步處理任務(wù)。myapp.tasks.some_task是本次的定時(shí)任務(wù)。
3)同樣在django項(xiàng)目的根目錄下再打開(kāi)一個(gè)命令行界面,執(zhí)行如下代碼:
? ?celery -A FruitShopGP2? beat -l info
可以稍微等待幾分鐘,多執(zhí)行幾次任務(wù)。如下圖 上面的窗口是beat,下面的窗口是worker??煽吹絧rint的信息在worker中輸出。
?
?
我們甚至不用打開(kāi)Django項(xiàng)目的服務(wù)器,就可以執(zhí)行定時(shí)任務(wù)。?
下方內(nèi)容僅供參考:
?
2、Celery定時(shí)任務(wù)時(shí)間設(shè)置
若你覺(jué)得1分鐘等待時(shí)間太長(zhǎng)??梢栽O(shè)置為每10秒執(zhí)行一次定時(shí)任務(wù)。將上面的periodic_task修改如下:
@periodic_task(run_every=10)修改代碼,需要重啟Celery的worker和beat。
這個(gè)run_every參數(shù)是設(shè)置定時(shí)任務(wù)的時(shí)間間隔或執(zhí)行的時(shí)間。該參數(shù)設(shè)置有3種方式。
1)直接設(shè)置秒數(shù)
例如剛剛所說(shuō)的10秒間隔,run_every=10,每10秒執(zhí)行一次任務(wù)。1分鐘即是60秒;1小時(shí)即是3600秒。
2)通過(guò)datetime設(shè)置時(shí)間間隔
有時(shí)直接設(shè)置秒數(shù)不方便,需要通過(guò)計(jì)算得到具體秒數(shù)。
例如,1小時(shí)15分鐘40秒 = 1*60*60 + 15*60 + 40。這種情況可讀性也不高。
可以采用datetime設(shè)置,代碼如下:
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!!!!!')代碼可讀性明顯提升,而且設(shè)置方便。
但這種不能滿足定時(shí)定點(diǎn)的時(shí)間設(shè)置。假如我想固定每天12點(diǎn)15分的時(shí)候,執(zhí)行一次任務(wù)。datetime和直接設(shè)置秒數(shù)的方式都無(wú)法實(shí)現(xiàn)。這時(shí)得使用第3種方式。
?
3)celery的crontab表達(dá)式
crontab是比較完善,且稍微有點(diǎn)復(fù)雜(相對(duì)前面兩種方式而言)的方式??梢詫?shí)現(xiàn)我們各種設(shè)置時(shí)間的需求。
例如,前面給出的代碼:
?
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秒時(shí)刻執(zhí)行一次(后面不提這個(gè)0秒,大家都知道就行了,省點(diǎn)口水)。
其中,crontab()實(shí)例化的時(shí)候沒(méi)設(shè)置任何參數(shù),都是使用默認(rèn)值。crontab一共有7個(gè)參數(shù),常用有5個(gè)參數(shù)分別為:
minute:分鐘,范圍0-59;
hour:小時(shí),范圍0-23;
day_of_week:星期幾,范圍0-6。以星期天為開(kāi)始,即0為星期天。這個(gè)星期幾還可以使用英文縮寫(xiě)表示,例如“sun”表示星期天;
day_of_month:每月第幾號(hào),范圍1-31;
month_of_year:月份,范圍1-12。
?
a、默認(rèn)參數(shù)
這些參數(shù)可以設(shè)置表達(dá)式,表達(dá)稍微復(fù)雜的設(shè)置。默認(rèn)值都是"*"星號(hào),代表任意時(shí)刻。即crontab()相當(dāng)與:
1 crontab(minute='*', hour='*', day_of_week='*', day_of_month='*', month_of_year='*')含義是每天、每小時(shí)、每分鐘執(zhí)行一次任務(wù)。這說(shuō)法太反人類語(yǔ)言習(xí)慣,簡(jiǎn)單說(shuō)就是每1分鐘執(zhí)行一次任務(wù)。
?
b、具體某個(gè)值
上面提到這些參數(shù)的取值范圍。我們可以直接設(shè)置某個(gè)值。例如:
1 crontab(minute=15)即每小時(shí)的15分時(shí)刻執(zhí)行一次任務(wù)。直接指定某個(gè)時(shí)刻。以此類推可以設(shè)置每天0點(diǎn)0分時(shí)刻執(zhí)行任務(wù)的設(shè)置如下:
1 crontab(minute=0, hour=0)當(dāng)然,也可以設(shè)置多個(gè)值。例如0分和30分執(zhí)行一次任務(wù):
crontab(minute='0,30')這里使用字符串,用逗號(hào)隔開(kāi)數(shù)值。這里的逗號(hào)是表示多個(gè)表達(dá)式or邏輯關(guān)系。
?
c、設(shè)置范圍
設(shè)置范圍也是設(shè)置多個(gè)值,例如指定9點(diǎn)到12點(diǎn)每個(gè)小時(shí)的每分鐘執(zhí)行任務(wù)。
1 crontab(minute='*', hour='9-12')這里*號(hào)是默認(rèn)值,可以省略如下:
1 crontab(hour='9-12')上面提到逗號(hào)是or邏輯關(guān)系。拓展一下,指定9點(diǎn)到12點(diǎn)和20點(diǎn)中每分鐘執(zhí)行任務(wù):
1 crontab(hour='9-12,20')crontab的表達(dá)式越來(lái)越復(fù)雜了。celery還提供了一個(gè)類得到表達(dá)式解析結(jié)果,代碼如下:
1 from celery.task.schedules import crontab_parser 2 r = crontab_parser(23, 0).parse('9-12,20') 3 print(r)其中,crontab_parse是一個(gè)解析類。第1個(gè)參數(shù)是范圍的最大值;第2個(gè)參數(shù)是范圍的最小值。通過(guò)parse輸入表達(dá)式,可得到表達(dá)式的解析結(jié)果:
1 set([9, 10, 11, 12, 20])下面很多地方我們都可以通過(guò)該方法驗(yàn)證解析結(jié)果。
??
d、設(shè)置間隔步長(zhǎng)
假如我要設(shè)置1、3、5、7、9、11月份每天每分鐘執(zhí)行任務(wù),按照上面的做法可以設(shè)置如下:
1 crontab(day_of_month='1,3,5,7,9,11')觀察數(shù)據(jù)可以發(fā)現(xiàn),都是間隔2的步長(zhǎng)。需要設(shè)置的數(shù)字比較少,若數(shù)字比較多顯得很麻煩。例如我想每間隔2分鐘就執(zhí)行一次任務(wù),要寫(xiě)30個(gè)數(shù)字想想就覺(jué)得很麻煩。crontab表達(dá)式還提供了間隔的處理,例如:
1 crontab(minute='*/2') 2 crontab(minute='0-59/2') #效果等同上面這個(gè)/號(hào)不是除以的意思。相當(dāng)與range的第3個(gè)參數(shù),例如:
1 range(0, 59+1, 2)差不多crontab表達(dá)式就這些,多舉幾個(gè)例子:
?
1 #每2個(gè)小時(shí)中每分鐘執(zhí)行1次任務(wù)2 crontab(hour='*/2')3 4 #每3個(gè)小時(shí)的0分時(shí)刻執(zhí)行1次任務(wù)5 #即[0,3,6,9,12,15,18,21]點(diǎn)0分6 crontab(minute=0, hour='*/3')7 8 #每3個(gè)小時(shí)或8點(diǎn)到12點(diǎn)的0分時(shí)刻執(zhí)行1次任務(wù)9 #即[0,3,6,9,12,15,18,21]+[8,9,10,11,12]點(diǎn)0分 10 crontab(minute=0, hour='*/3,8-12') 11 12 #每個(gè)季度的第1個(gè)月中,每天每分鐘執(zhí)行1次任務(wù) 13 #月份范圍是1-12,每3個(gè)月為[1,4,7,10] 14 crontab(month_of_year='*/3') 15 16 #每月偶數(shù)天數(shù)的0點(diǎn)0分時(shí)刻執(zhí)行1次任務(wù) 17 crontab(minute=0, hour=0, day_of_month='2-31/2') 18 19 #每年5月11號(hào)的0點(diǎn)0分時(shí)刻執(zhí)行1次任務(wù) 20 crontab(0, 0, day_of_month='11', month_of_year='5')總結(jié)
以上是生活随笔為你收集整理的celery 学习笔记定时任务和异步任务的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 当电脑接双屏扩展显示器时,系统崩溃,QQ
- 下一篇: 乌班图系统扩容