python 定時任務


crontab expression

原文:https://www.cnblogs.com/pipi-changing/p/5697481.html

1. cron表達式格式:

{秒數} {分鍾} {小時} {日期} {月份} {星期} {年份(可為空)}
2. cron表達式各占位符解釋:

{秒數} ==> 允許值范圍: 0~59 ,不允許為空值,若值不合法,調度器將拋出SchedulerException異常

"*" 代表每隔1秒鍾觸發;

"," 代表在指定的秒數觸發,比如"0,15,45"代表0秒、15秒和45秒時觸發任務

"-" 代表在指定的范圍內觸發,比如"25-45"代表從25秒開始觸發到45秒結束觸發,每隔1秒觸發1次

"/" 代表觸發步進(step),"/"前面的值代表初始值("*"等同"0"),后面的值代表偏移量,比如"0/20"或者"*/20"代表從0秒鍾開始,每隔20秒鍾觸發1次,即0秒觸發1次,20秒觸發1次,40秒觸發1次;"5/20"代表5秒觸發1次,25秒觸發1次,45秒觸發1次;"10-45/20"代表在[10,45]內步進20秒命中的時間點觸發,即10秒觸發1次,30秒觸發1次

 

{分鍾} ==> 允許值范圍: 0~59 ,不允許為空值,若值不合法,調度器將拋出SchedulerException異常

"*" 代表每隔1分鍾觸發;

"," 代表在指定的分鍾觸發,比如"10,20,40"代表10分鍾、20分鍾和40分鍾時觸發任務

"-" 代表在指定的范圍內觸發,比如"5-30"代表從5分鍾開始觸發到30分鍾結束觸 發,每隔1分鍾觸發

"/" 代表觸發步進(step),"/"前面的值代表初始值("*"等同"0"),后面的值代表偏移量,比如"0/25"或者"*/25"代表從0分鍾開始,每隔25分鍾觸發1次,即0分鍾觸發1次,第25分鍾觸發1次,第50分鍾觸發1次;"5/25"代表5分鍾觸發1次,30分鍾觸發1次,55分鍾觸發1次;"10-45/20"代表在[10,45]內步進20分鍾命中的時間點觸發,即10分鍾觸發1次,30分鍾觸發1次

 

{小時} ==> 允許值范圍: 0~23 ,不允許為空值,若值不合法,調度器將拋出SchedulerException異常

"*" 代表每隔1小時觸發;

"," 代表在指定的時間點觸發,比如"10,20,23"代表10點鍾、20點鍾和23點觸發任務

"-" 代表在指定的時間段內觸發,比如"20-23"代表從20點開始觸發到23點結束觸發,每隔1小時觸發

"/" 代表觸發步進(step),"/"前面的值代表初始值("*"等同"0"),后面的值代表偏移量,比如"0/1"或者"*/1"代表從0點開始觸發,每隔1小時觸發1次;"1/2"代表從1點開始觸發,以后每隔2小時觸發一次;"19-20/2"表達式將只在19點觸發

 

{日期} ==> 允許值范圍: 1~31 ,不允許為空值,若值不合法,調度器將拋出SchedulerException異常

"*" 代表每天觸發;

"?" 與{星期}互斥,即意味着若明確指定{星期}觸發,則表示{日期}無意義,以免引起 沖突和混亂

"," 代表在指定的日期觸發,比如"1,10,20"代表1號、10號和20號這3天觸發

"-" 代表在指定的日期范圍內觸發,比如"10-15"代表從10號開始觸發到15號結束觸發,每隔1天觸發

"/" 代表觸發步進(step),"/"前面的值代表初始值("*"等同"1"),后面的值代表偏移量,比如"1/5"或者"*/5"代表從1號開始觸發,每隔5天觸發1次;"10/5"代表從10號開始觸發,以后每隔5天觸發一次;"1-10/2"表達式意味着在[1,10]范圍內,每隔2天觸發,即1號,3號,5號,7號,9號觸發

"L" 如果{日期}占位符如果是"L",即意味着當月的最后一天觸發

"W "意味着在本月內離當天最近的工作日觸發,所謂最近工作日,即當天到工作日的前后最短距離,如果當天即為工作日,則距離為0;所謂本月內的說法,就是不能跨月取到最近工作日,即使前/后月份的最后一天/第一天確實滿足最近工作日;因此,"LW"則意味着本月的最后一個工作日觸發,"W"強烈依賴{月份}

"C" 根據日歷觸發,由於使用較少,暫時不做解釋

 

{月份} ==> 允許值范圍: 1~12 (JAN-DEC),不允許為空值,若值不合法,調度器將拋出SchedulerException異常

"*" 代表每個月都觸發;

"," 代表在指定的月份觸發,比如"1,6,12"代表1月份、6月份和12月份觸發任務

"-" 代表在指定的月份范圍內觸發,比如"1-6"代表從1月份開始觸發到6月份結束觸發,每隔1個月觸發

"/" 代表觸發步進(step),"/"前面的值代表初始值("*"等同"1"),后面的值代表偏移量,比如"1/2"或者"*/2"代表從1月份開始觸發,每隔2個月觸發1次;"6/6"代表從6月份開始觸發,以后每隔6個月觸發一次;"1-6/12"表達式意味着每年1月份觸發

 

{星期} ==> 允許值范圍: 1~7 (SUN-SAT),1代表星期天(一星期的第一天),以此類推,7代表星期六(一星期的最后一天),不允許為空值,若值不合法,調度器將拋出SchedulerException異常

"*" 代表每星期都觸發;

"?" 與{日期}互斥,即意味着若明確指定{日期}觸發,則表示{星期}無意義,以免引起沖突和混亂

"," 代表在指定的星期約定觸發,比如"1,3,5"代表星期天、星期二和星期四觸發

"-" 代表在指定的星期范圍內觸發,比如"2-4"代表從星期一開始觸發到星期三結束觸發,每隔1天觸發

"/" 代表觸發步進(step),"/"前面的值代表初始值("*"等同"1"),后面的值代表偏移量,比如"1/3"或者"*/3"代表從星期天開始觸發,每隔3天觸發1次;"1-5/2"表達式意味着在[1,5]范圍內,每隔2天觸發,即星期天、星期二、星期四觸發

"L" 如果{星期}占位符如果是"L",即意味着星期的的最后一天觸發,即星期六觸發,L= 7或者 L = SAT,因此,"5L"意味着一個月的最后一個星期四觸發

"#" 用來指定具體的周數,"#"前面代表星期,"#"后面代表本月第幾周,比如"2#2"表示本月第二周的星期一,"5#3"表示本月第三周的星期四,因此,"5L"這種形式只不過是"#"的特殊形式而已

"C" 根據日歷觸發,由於使用較少,暫時不做解釋

 

{年份} ==> 允許值范圍: 1970~2099 ,允許為空,若值不合法,調度器將拋出SchedulerException異常

"*"代表每年都觸發;

","代表在指定的年份才觸發,比如"2011,2012,2013"代表2011年、2012年和2013年觸發任務

"-"代表在指定的年份范圍內觸發,比如"2011-2020"代表從2011年開始觸發到2020年結束觸發,每隔1年觸發

"/"代表觸發步進(step),"/"前面的值代表初始值("*"等同"1970"),后面的值代表偏移量,比如"2011/2"或者"*/2"代表從2011年開始觸發,每隔2年觸發1次

 

注意:除了{日期}和{星期}可以使用"?"來實現互斥,表達無意義的信息之外,其他占位符都要具有具體的時間含義,且依賴關系為:年->月->日期(星期)->小時->分鍾->秒數

 
 
3. cron表達式的強大魅力在於靈活的橫向和縱向組合以及簡單的語法,用cron表達式幾乎可以寫出任何你想要觸發的時間點

經典案例:

"30 * * * * ?" 每半分鍾觸發任務

"30 10 * * * ?" 每小時的10分30秒觸發任務

"30 10 1 * * ?" 每天1點10分30秒觸發任務

"30 10 1 20 * ?" 每月20號1點10分30秒觸發任務

"30 10 1 20 10 ? *" 每年10月20號1點10分30秒觸發任務

"30 10 1 20 10 ? 2011" 2011年10月20號1點10分30秒觸發任務

"30 10 1 ? 10 * 2011" 2011年10月每天1點10分30秒觸發任務

"30 10 1 ? 10 SUN 2011" 2011年10月每周日1點10分30秒觸發任務

"15,30,45 * * * * ?" 每15秒,30秒,45秒時觸發任務

"15-45 * * * * ?" 15到45秒內,每秒都觸發任務

"15/5 * * * * ?" 每分鍾的每15秒開始觸發,每隔5秒觸發一次

"15-30/5 * * * * ?" 每分鍾的15秒到30秒之間開始觸發,每隔5秒觸發一次

"0 0/3 * * * ?" 每小時的第0分0秒開始,每三分鍾觸發一次

"0 15 10 ? * MON-FRI" 星期一到星期五的10點15分0秒觸發任務

"0 15 10 L * ?" 每個月最后一天的10點15分0秒觸發任務

"0 15 10 LW * ?" 每個月最后一個工作日的10點15分0秒觸發任務

"0 15 10 ? * 5L" 每個月最后一個星期四的10點15分0秒觸發任務

"0 15 10 ? * 5#3" 每個月第三周的星期四的10點15分0秒觸發任務

 

 

 

定時任務框架APScheduler

推薦文檔:

官方文檔:https://apscheduler.readthedocs.io/en/v2.1.2/cronschedule.html   

APScheduler官方文檔翻譯: https://www.jianshu.com/p/4f5305e220f0

APScheduler簡介

APScheduler基於Quartz的一個Python定時任務框架,實現了Quartz的所有功能,使用起來十分方便。提供了基於日期、固定時間間隔以及crontab類型的任務,並且可以持久化任務。基於這些功能,我們可以很方便的實現一個python定時任務系統。

安裝

利用pip進行安裝

pip install apscheduler

源碼安裝(https://pypi.python.org/pypi/APScheduler/)

python setup.py install

APScheduler有四種組成部分:

觸發器(trigger)包含調度邏輯,每一個作業有它自己的觸發器,用於決定接下來哪一個作業會運行。除了他們自己初始配置意外,觸發器完全是無狀態的。

作業存儲(job store)存儲被調度的作業,默認的作業存儲是簡單地把作業保存在內存中,其他的作業存儲是將作業保存在數據庫中。一個作業的數據講在保存在持久化作業存儲時被序列化,並在加載時被反序列化。調度器不能分享同一個作業存儲。

執行器(executor)處理作業的運行,他們通常通過在作業中提交制定的可調用對象到一個線程或者進城池來進行。當作業完成時,執行器將會通知調度器。

調度器(scheduler)是其他的組成部分。你通常在應用只有一個調度器,應用的開發者通常不會直接處理作業存儲、調度器和觸發器,相反,調度器提供了處理這些的合適的接口。配置作業存儲和執行器可以在調度器中完成,例如添加、修改和移除作業。 

簡單應用:

import time
from apscheduler.schedulers.blocking import BlockingScheduler
 
def my_job():
    print time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
 
sched = BlockingScheduler()
sched.add_job(my_job, 'interval', seconds=5)
sched.start()

上面的例子表示每隔5s執行一次my_job函數,輸出當前時間信息

操作作業

1. 添加作業

上面是通過add_job()來添加作業,另外還有一種方式是通過scheduled_job()修飾器來修飾函數

import time
from apscheduler.schedulers.blocking import BlockingScheduler
 
sched = BlockingScheduler()
 
@sched.scheduled_job('interval', seconds=5)
def my_job():
    print time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
 
sched.start()

2. 移除作業

job = scheduler.add_job(myfunc, 'interval', minutes=2)
job.remove()
#如果有多個任務序列的話可以給每個任務設置ID號,可以根據ID號選擇清除對象,且remove放到start前才有效
sched.add_job(myfunc, 'interval', minutes=2, id='my_job_id')
sched.remove_job('my_job_id')

3. 暫停和恢復作業

 暫停作業:

apsched.job.Job.pause()
apsched.schedulers.base.BaseScheduler.pause_job()

 恢復作業:

apsched.job.Job.resume()
apsched.schedulers.base.BaseScheduler.resume_job()

4. 獲得job列表

 獲得調度作業的列表,可以使用get_jobs()來完成,它會返回所有的job實例。或者使用print_jobs()來輸出所有格式化的作業列表。也可以利用get_job(任務ID)獲取指定任務的作業列表

job = sched.add_job(my_job, 'interval', seconds=2 ,id='123')
print sched.get_job(job_id='123')
print sched.get_jobs()

 

5. 關閉調度器

 默認情況下調度器會等待所有正在運行的作業完成后,關閉所有的調度器和作業存儲。如果你不想等待,可以將wait選項設置為False。

sched.shutdown()
sched.shutdown(wait=False)

 作業運行的控制(trigger)

add_job的第二個參數是trigger,它管理着作業的調度方式。它可以為date, interval或者cron。對於不同的trigger,對應的參數也相同。

(1). cron定時調度(某一定時時刻執行)

復制代碼
(int|str) 表示參數既可以是int類型,也可以是str類型
(datetime | str) 表示參數既可以是datetime類型,也可以是str類型
 
year (int|str) – 4-digit year -(表示四位數的年份,如2008年)
month (int|str) – month (1-12) -(表示取值范圍為1-12月)
day (int|str) – day of the (1-31) -(表示取值范圍為1-31日)
week (int|str) – ISO week (1-53) -(格里歷2006年12月31日可以寫成2006年-W52-7(擴展形式)或2006W527(緊湊形式))
day_of_week (int|str) – number or name of weekday (0-6 or mon,tue,wed,thu,fri,sat,sun) - (表示一周中的第幾天,既可以用0-6表示也可以用其英語縮寫表示)
hour (int|str) – hour (0-23) - (表示取值范圍為0-23時)
minute (int|str) – minute (0-59) - (表示取值范圍為0-59分)
second (int|str) – second (0-59) - (表示取值范圍為0-59秒)
start_date (datetime|str) – earliest possible date/time to trigger on (inclusive) - (表示開始時間)
end_date (datetime|str) – latest possible date/time to trigger on (inclusive) - (表示結束時間)
timezone (datetime.tzinfo|str) – time zone to use for the date/time calculations (defaults to scheduler timezone) -(表示時區取值)
復制代碼

參數的取值格式:

例子:

#表示2017年3月22日17時19分07秒執行該程序
sched.add_job(my_job, 'cron', year=2017,month = 03,day = 22,hour = 17,minute = 19,second = 07)
 
#表示任務在6,7,8,11,12月份的第三個星期五的00:00,01:00,02:00,03:00 執行該程序
sched.add_job(my_job, 'cron', month='6-8,11-12', day='3rd fri', hour='0-3')
 
#表示從星期一到星期五5:30(AM)直到2014-05-30 00:00:00
sched.add_job(my_job(), 'cron', day_of_week='mon-fri', hour=5, minute=30,end_date='2014-05-30')
 
#表示每5秒執行該程序一次,相當於interval 間隔調度中seconds = 5
sched.add_job(my_job, 'cron',second = '*/5')

(2). interval 間隔調度(每隔多久執行)

weeks (int) – number of weeks to wait
days (int) – number of days to wait
hours (int) – number of hours to wait
minutes (int) – number of minutes to wait
seconds (int) – number of seconds to wait
start_date (datetime|str) – starting point for the interval calculation
end_date (datetime|str) – latest possible date/time to trigger on
timezone (datetime.tzinfo|str) – time zone to use for the date/time calculations

例子:

#表示每隔3天17時19分07秒執行一次任務
sched.add_job(my_job, 'interval',days  = 03,hours = 17,minutes = 19,seconds = 07)

(3). date 定時調度(作業只會執行一次)

run_date (datetime|str) – the date/time to run the job at  -(任務開始的時間)
timezone (datetime.tzinfo|str) – time zone for run_date if it doesn’t have one already

例子:

# The job will be executed on November 6th, 2009
sched.add_job(my_job, 'date', run_date=date(2009, 11, 6), args=['text'])
# The job will be executed on November 6th, 2009 at 16:30:05
sched.add_job(my_job, 'date', run_date=datetime(2009, 11, 6, 16, 30, 5), args=['text'])

Django中使用django-apscheduler執行定時任務

安裝

pip install apscheduler

配置

(1)修改settings.py文件,在INSTALLED_APPS中加入django-apscheduler應用:

INSTALLED_APPS = [
    ......
    'django_apscheduler',#定時執行任務
]
(2)執行遷移命令:
python manage.py migrate
# python manage.py migrate django_apscheduler

使用

在任意一個views.py文件中加入實現代碼,使得每次啟動Django框架時,定時任務都會同時啟動。代碼如下:

from apscheduler.schedulers.background import BackgroundScheduler
from django_apscheduler.jobstores import DjangoJobStore, register_events, register_job

#開啟定時工作
try:
    # 實例化調度器
    scheduler = BackgroundScheduler()
    # 調度器使用DjangoJobStore()
    scheduler.add_jobstore(DjangoJobStore(), "default")
    # 設置定時任務,選擇方式為interval,時間間隔為10s
    # 另一種方式為每天固定時間執行任務,對應代碼為:
    # @register_job(scheduler, 'cron', day_of_week='mon-fri', hour='9', minute='30', second='10',id='task_time')
    @register_job(scheduler,"interval", seconds=10)
    def my_job():
        # 這里寫你要執行的任務
        pass
    register_events(scheduler)
    scheduler.start()
except Exception as e:
    print(e)
    # 有錯誤就停止定時器
    scheduler.shutdown()

 示例

from apscheduler.scheduler import Scheduler
from time import sleep

def task_Fun():
    '''
    這里寫定時任務
    '''
    sleep(1)

sched = Scheduler()

@sched.interval_schedule(seconds=6)
def my_task1():
    print('定時任務1開始\n')
    task_Fun()
    print('定時任務1結束\n')

@sched.interval_schedule(hours=4)
def my_task2():
    print('定時任務2開始\n')
    sleep(1)
    print('定時任務2結束\n')


sched.start()

Crontab定時任務

crontab

官方鏈接:https://linuxtools-rst.readthedocs.io/zh_CN/latest/tool/crontab.html

在做一個django項目的時候,我遇到了一個定時任務的需求,我這里是需要定時掃描數據庫並發送郵件,在查閱相關資料后,總結出如下幾個方法

  1. 使用while創建一個死循環,判斷時間,從而執行一些函數
  2. 使用APScheduler庫實現定時任務 (詳情可以見http://blog.csdn.net/hui3909/article/details/46652623
  3. django-crontab實現定時任務
  4. django-celery實現定時任務

django-crontab實現定時任務

在我斟酌再三,最終還是選擇了django-crontab這個方法,這個方法最契合我的需求,同時也相對簡單,所以本文也就着重介紹一下

django-crontab安裝

安裝django-crontab庫

這里使用pip安裝即可,在終端輸入以下命令即可

pip install django-crontab

在工程里使用django-crontab

在django項目的settings.pyINSTALLED_APPS添加django-crontab

 
在app中加入django-crontab

django-crontab配置

django-crontab可以定時運行自定義命令和函數兩種方式

定時函數

在django項目的settings.py中添加以下命令

CRONJOBS = (
    ('*/1 * * * *', '你的app名.定時函數所在的py文件名.定時函數名'), ('0 0 1 * *', '你的app名.定時函數所在的py文件名.定時函數名', '>> 輸出文件路徑和名稱'), )
  • 第一種的意思就是每一分鍾執行一次你的定時函數
  • 第二種時定時函數輸出的內容到指定文件(如果該路徑或文件不存在將會自動創建)

定時命令

CRONJOBS = (
    ('10 12 * * *', 'django.core.management.call_command', ['要執行的命令']), )
  • 意思是在12點10分執行命令

定時任務的操作

  1. python manage.py crontab add  添加定時任務
  2. python manage.py crontab remove 清除定時任務
  3. python manage.py crontab show 顯示定時任務
  • 當你添加了或者修改的定時任務,只需執行命令1即可
  • 如果你想刪除定時任務,請執行命令2

注:

  • 當定時任務執行時,如果你只是一些輸出語句,那么你將看不到任何內容。請不要懷疑沒有執行
  • 上述環境在ubuntu16.04 lts django1.9中測試成功
  • 上述文字皆為個人看法,如有錯誤或建議請及時聯系我
作者:EarthChen
鏈接:https://www.jianshu.com/p/27f003149090
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並注明出處。

查看crontab日志

1. linux
看 /var/log/cron.log這個文件就可以,可以用tail -f /var/log/cron.log觀察

2. unix
在 /var/spool/cron/tmp文件中,有croutXXX001864的tmp文件,tail 這些文件就可以看到正在執行的任務了。

3. mail任務
在 /var/spool/mail/root 文件中,有crontab執行日志的記錄,用tail -f /var/spool/mail/root 即可查看最近的crontab執行情況。

注:Ubuntu 默認沒有開啟cron log.

vim /etc/rsyslog.d/50-default.conf 
#cron.* /var/log/cron.log #去掉注釋符號#, 
sudo service rsyslog restart #重啟rsyslog 
sudo service crontab restart #重啟crontab

示例

CRONJOBS = (
    ('*/1 * * * *', 'apps.index.test.do_something', '>>/tmp/cron.log'), )

 apps.index.test.py

def do_something():
    print(123)

錯誤匯總

/tmp/cron.log沒有日志打印,排查

1、apps.index.test.do_something,注意路徑是否正確,apps在項目根目錄

2、重啟系統cron

更新系統時間時區后需要重啟cron,在ubuntu中服務名為cron:

$service cron restart

ubuntu下啟動、停止與重啟cron:

$sudo /etc/init.d/cron start
$sudo /etc/init.d/cron stop
$sudo /etc/init.d/cron restart

3、Ubuntu 默認沒有開啟cron log.

vim /etc/rsyslog.d/50-default.conf 
#cron.* /var/log/cron.log #去掉注釋符號#, sudo service rsyslog restart #重啟rsyslog sudo service crontab restart #重啟crontab

參考資料

django使用 django-apscheduler 實現定時任務

Django中使用django-apscheduler執行定時任務
作者:JL_Cheng 鏈接:https://www.jianshu.com/p/dd22e8bd29c1
Django使用apscheduler完成定時任務:https://blog.csdn.net/stormdony/article/details/81144605


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM