背景
目前所在的项目组需要经常执行一些定时任务,于是选择使用 Python 的定时器。

Python 实现定时任务

循环 sleep

这种方式最简单,在循环里面放入要执行的任务,然后 sleep 一段时间再执行

from datetime import datetime
import time
# 每n秒执行一次
def timer(n):while True:print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))time.sleep(n)
# 5s
timer(5)

这个方法的缺点是,只能执行固定间隔时间的任务,如果有定时任务就无法完成,比如早上六点半喊我起床。并且 sleep 是一个阻塞函数,也就是说 sleep 这一段时间,啥都不能做。

threading模块中的Timer
threading 模块中的 Timer 是一个非阻塞函数,比 sleep 稍好一点,不过依然无法喊我起床。

from datetime import datetime
from threading import Timer
# 打印时间函数
def printTime(inc):print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))t = Timer(inc, printTime, (inc,))t.start()
# 5s
printTime(5)

Timer 函数第一个参数是时间间隔(单位是秒),第二个参数是要调用的函数名,第三个参数是调用函数的参数(tuple)

使用sched模块

sched 模块是 Python 内置的模块,它是一个调度(延时处理机制),每次想要定时执行某任务都必须写入一个调度。

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:857662006
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
import sched
import time
from datetime import datetime
# 初始化sched模块的 scheduler 类
# 第一个参数是一个可以返回时间戳的函数,第二个参数可以在定时未到达之前阻塞。
schedule = sched.scheduler(time.time, time.sleep)
# 被周期性调度触发的函数
def printTime(inc):print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))schedule.enter(inc, 0, printTime, (inc,))
# 默认参数60s
def main(inc=60):# enter四个参数分别为:间隔事件、优先级(用于同时间到达的两个事件同时执行时定序)、被调用触发的函数,# 给该触发函数的参数(tuple形式)schedule.enter(0, 0, printTime, (inc,))schedule.run()
# 10s 输出一次
main(10)

sched 使用步骤如下:

(1)生成调度器:

s = sched.scheduler(time.time,time.sleep)

第一个参数是一个可以返回时间戳的函数,第二个参数可以在定时未到达之前阻塞。

(2)加入调度事件
其实有 enter、enterabs 等等,我们以 enter 为例子。

s.enter(x1,x2,x3,x4)

四个参数分别为:间隔事件、优先级(用于同时间到达的两个事件同时执行时定序)、被调用触发的函数,给触发函数的参数(注意:一定要以 tuple 给,如果只有一个参数就(xx,))

(3)运行

s.run()

注意 sched 模块不是循环的,一次调度被执行后就 Over 了,如果想再执行,请再次 enter

APScheduler定时框架

终于找到了可以每天定时喊我起床的方式了

APScheduler是一个 Python 定时任务框架,使用起来十分方便。提供了基于日期、固定时间间隔以及 crontab 类型的任务,并且可以持久化任务、并以 daemon 方式运行应用。

使用 APScheduler 需要安装

$ pip install apscheduler

首先来看一个周一到周五每天早上6点半喊我起床的例子

from apscheduler.schedulers.blocking import BlockingScheduler
from datetime import datetime
# 输出时间
def job():print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
# BlockingScheduler
scheduler = BlockingScheduler()
scheduler.add_job(job, 'cron', day_of_week='1-5', hour=6, minute=30)
scheduler.start()

代码中的 BlockingScheduler 是什么呢?

BlockingScheduler是APScheduler中的调度器,APScheduler 中有两种常用的调度器,BlockingScheduler 和 BackgroundScheduler,当调度器是应用中唯一要运行的任务时,使用 BlockingSchedule,如果希望调度器在后台执行,使用 BackgroundScheduler。

BlockingScheduler: use when the scheduler is the only thing running in your process
BackgroundScheduler: use when you’re not using any of the frameworks below, and want the scheduler to run in the background inside your application
AsyncIOScheduler: use if your application uses the asyncio module
GeventScheduler: use if your application uses gevent
TornadoScheduler: use if you’re building a Tornado application
TwistedScheduler: use if you’re building a Twisted application
QtScheduler: use if you’re building a Qt application

APScheduler四个组件

APScheduler 四个组件分别为:触发器(trigger),作业存储(job store),执行器(executor),调度器(scheduler)。

触发器(trigger)

包含调度逻辑,每一个作业有它自己的触发器,用于决定接下来哪一个作业会运行。除了他们自己初始配置意外,触发器完全是无状态的
APScheduler 有三种内建的 trigger:

date: 特定的时间点触发
interval: 固定时间间隔触发
cron: 在特定时间周期性地触发

作业存储(job store)

存储被调度的作业,默认的作业存储是简单地把作业保存在内存中,其他的作业存储是将作业保存在数据库中。一个作业的数据讲在保存在持久化作业存储时被序列化,并在加载时被反序列化。调度器不能分享同一个作业存储。
APScheduler 默认使用 MemoryJobStore,可以修改使用 DB 存储方案

执行器(executor)

处理作业的运行,他们通常通过在作业中提交制定的可调用对象到一个线程或者进城池来进行。当作业完成时,执行器将会通知调度器。
最常用的 executor 有两种:

ProcessPoolExecutor
ThreadPoolExecutor

调度器(scheduler)

通常在应用中只有一个调度器,应用的开发者通常不会直接处理作业存储、调度器和触发器,相反,调度器提供了处理这些的合适的接口。配置作业存储和执行器可以在调度器中完成,例如添加、修改和移除作业。

配置调度器

APScheduler提供了许多不同的方式来配置调度器,你可以使用一个配置字典或者作为参数关键字的方式传入。你也可以先创建调度器,再配置和添加作业,这样你可以在不同的环境中得到更大的灵活性。

下面来看一个简单的 BlockingScheduler 例子

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:857662006
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
from apscheduler.schedulers.blocking import BlockingScheduler
from datetime import datetimedef job():print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
# 定义BlockingScheduler
sched = BlockingScheduler()
sched.add_job(job, 'interval', seconds=5)
sched.start()

上述代码创建了一个 BlockingScheduler,并使用默认内存存储和默认执行器。(默认选项分别是 MemoryJobStore 和 ThreadPoolExecutor,其中线程池的最大线程数为10)。配置完成后使用 start() 方法来启动。

如果想要显式设置 job store(使用mongo存储)和 executor 可以这样写:

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:857662006
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
from datetime import datetime
from pymongo import MongoClient
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.jobstores.memory import MemoryJobStore
from apscheduler.jobstores.mongodb import MongoDBJobStore
from apscheduler.executors.pool import ThreadPoolExecutor, ProcessPoolExecutor
# MongoDB 参数
host = '127.0.0.1'
port = 27017
client = MongoClient(host, port)
# 输出时间
def job():print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
# 存储方式
jobstores = {'mongo': MongoDBJobStore(collection='job', database='test', client=client),'default': MemoryJobStore()
}
executors = {'default': ThreadPoolExecutor(10),'processpool': ProcessPoolExecutor(3)
}
job_defaults = {'coalesce': False,'max_instances': 3
}
scheduler = BlockingScheduler(jobstores=jobstores, executors=executors, job_defaults=job_defaults)
scheduler.add_job(job, 'interval', seconds=5, jobstore='mongo')
scheduler.start()

在运行程序5秒后,第一次输出时间。
在 MongoDB 中可以看到 job 的状态

对 job 的操作

添加 job

添加job有两种方式:

add_job()
scheduled_job()

第二种方法只适用于应用运行期间不会改变的 job,而第一种方法返回一个apscheduler.job.Job 的实例,可以用来改变或者移除 job。

from apscheduler.schedulers.blocking import BlockingScheduler
sched = BlockingScheduler()
# 装饰器
@sched.scheduled_job('interval', id='my_job_id', seconds=5)
def job_function():print("Hello World")
# 开始
sched.start()

@sched.scheduled_job() 是 Python 的装饰器。

移除 job

移除 job 也有两种方法:

remove_job()
job.remove()

remove_job 使用 jobID 移除
job.remove() 使用 add_job() 返回的实例

job = scheduler.add_job(myfunc, 'interval', minutes=2)
job.remove()
# id
scheduler.add_job(myfunc, 'interval', minutes=2, id='my_job_id')
scheduler.remove_job('my_job_id')

暂停和恢复 job

暂停一个 job:

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

恢复一个 job:

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

希望你还记得 apscheduler.job.Job 是 add_job() 返回的实例

获取 job 列表

获得可调度 job 列表,可以使用get_jobs() 来完成,它会返回所有的 job 实例。

也可以使用print_jobs() 来输出所有格式化的 job 列表。

修改 job

除了 jobID 之外 job 的所有属性都可以修改,使用 apscheduler.job.Job.modify() 或者 modify_job() 修改一个 job 的属性

job.modify(max_instances=6, name='Alternate name')
modify_job('my_job_id', trigger='cron', minute='*/5')

关闭 job

默认情况下调度器会等待所有的 job 完成后,关闭所有的调度器和作业存储。将 wait 选项设置为 False 可以立即关闭。

scheduler.shutdown()
scheduler.shutdown(wait=False)
scheduler 事件

scheduler 可以添加事件监听器,并在特殊的时间触发。

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:857662006
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
def my_listener(event):if event.exception:print('The job crashed :(')else:print('The job worked :)')
# 添加监听器
scheduler.add_listener(my_listener, EVENT_JOB_EXECUTED | EVENT_JOB_ERROR)

trigger 规则

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
from datetime import date
from apscheduler.schedulers.blocking import BlockingScheduler
sched = BlockingScheduler()
def my_job(text):print(text)
# The job will be executed on November 6th, 2009
sched.add_job(my_job, 'date', run_date=date(2009, 11, 6), args=['text'])
sched.add_job(my_job, 'date', run_date=datetime(2009, 11, 6, 16, 30, 5), args=['text'])
sched.add_job(my_job, 'date', run_date='2009-11-06 16:30:05', args=['text'])
# The 'date' trigger and datetime.now() as run_date are implicit
sched.add_job(my_job, args=['text'])
sched.start()

cron

year (int|str) – 4-digit year
month (int|str) – month (1-12)
day (int|str) – day of the (1-31)
week (int|str) – ISO week (1-53)
day_of_week (int|str) – number or name of weekday (0-6 or mon,tue,wed,thu,fri,sat,sun)
hour (int|str) – hour (0-23)
minute (int|str) – minute (0-59)
second (int|str) – second (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)

表达式:

from apscheduler.schedulers.blocking import BlockingSchedulerdef job_function():print("Hello World")
# BlockingScheduler
sched = BlockingScheduler()
# Schedules job_function to be run on the third Friday
# of June, July, August, November and December at 00:00, 01:00, 02:00 and 03:00
sched.add_job(job_function, 'cron', month='6-8,11-12', day='3rd fri', hour='0-3')
# Runs from Monday to Friday at 5:30 (am) until 2014-05-30 00:00:00
sched.add_job(job_function, 'cron', day_of_week='mon-fri', hour=5, minute=30, end_date='2014-05-30')
sched.start()

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
from datetime import datetime
from apscheduler.schedulers.blocking import BlockingSchedulerdef job_function():print("Hello World")
# BlockingScheduler
sched = BlockingScheduler()
# Schedule job_function to be called every two hours
sched.add_job(job_function, 'interval', hours=2)
# The same as before, but starts on 2010-10-10 at 9:30 and stops on 2014-06-15 at 11:00
sched.add_job(job_function, 'interval', hours=2, start_date='2010-10-10 09:30:00', end_date='2014-06-15 11:00:00')
sched.start()

Python 定时任务的实现方式相关推荐

  1. 在Linux服务器上执行python定时任务(APScheduler定时框架)

    目标:在Linux服务器上,定时运行python脚本. 这个小玩意儿适用于让服务器做一些自动的东西,比如定时查库发送报表.定时让爬虫爬数据.定时提醒等等. 那有同学要问了:为啥不用自己电脑直接运行?- ...

  2. python做定时任务的方式及优缺点_python BlockingScheduler定时任务及其他方式的实现...

    本文介绍了python BlockingScheduler定时任务及其他方式的实现,具体如下: #BlockingScheduler定时任务 from apscheduler.schedulers.b ...

  3. python 定时任务实现方式

    python 实现定时任务 循环 sleep 方式 这种方式实现最简单,在循环里放入要执行的任务,然后 sleep 一段时间在执行.这个方法的缺点是只能在固定的时间间隔下执行,如果有定时任务也无法完成 ...

  4. python定时任务:apscheduler的使用(还有一个celery~)

    APScheduler简介 在平常的工作中几乎有一半的功能模块都需要定时任务来推动,例如项目中有一个定时统计程序,定时爬出网站的URL程序,定时检测钓鱼网站的程序等等,都涉及到了关于定时任务的问题,第 ...

  5. python定时任务_Python定时任务(上)

    在项目中,我们可能遇到有定时任务的需求.其一:定时执行任务.例如每天早上 8 点定时推送早报.其二:每隔一个时间段就执行任务.比如:每隔一个小时提醒自己起来走动走动,避免长时间坐着.今天,我跟大家分享 ...

  6. python定时任务_Python 定时任务最佳实践

    背景 最近有个需求,需要实现一个定时或定期任务的功能,需要实现每月.每日.每时.一次性等需求,必须是轻量级不依赖其它额外组件,并能支持动态添加任务.由于当前任务信息保存在集群 ETCD 数据库中,因此 ...

  7. python定时任务之cron_Python定时任务框架APScheduler 3.0.3 Cron示例

    APScheduler是基于Quartz的一个Python定时任务框架,实现了Quartz的所有功能,使用起来十分方便.提供了基于日期.固定时间间隔以及crontab类型的任务,并且可以持久化任务.基 ...

  8. Python定时任务

    Python下实现定时任务的方式有很多种方式 方法一:循环sleep,这是一种最简单的方式,在循环里放入要执行的任务,然后sleep一段时间再执行.缺点是,不容易控制,而且sleep是个阻塞函数 im ...

  9. python定时任务 每天运行一次_Python 定时任务最佳实践

    背景 最近有个需求,需要实现一个定时或定期任务的功能,需要实现每月.每日.每时.一次性等需求,必须是轻量级不依赖其它额外组件,并能支持动态添加任务.由于当前任务信息保存在集群 ETCD 数据库中,因此 ...

最新文章

  1. 控制C++的内存分配
  2. Weblogic 10.3.6 for linux 集群安装
  3. python语言的翻译方式是什么-python自动翻译实现方法
  4. 多元函数的极限与连续(一)
  5. 树莓派 rtl8188eu 芯片wifi驱动
  6. String Stringbuilder StringBuffer的区别和应用
  7. Debug a Server–Side Rendered SAP Spartacus Storefront Using Chrome Dev Tools
  8. ttl接地是高电平还是低电平_功放技术参数1——高电平
  9. MATLAB判断文件是否存在、删除文件
  10. 组合数学 —— 组合数
  11. 数据分析需要权衡哪些要素?
  12. 在micropython固件中加入st7789驱动
  13. setoolkit制作简单钓鱼网站
  14. Python制作绘图板,基础功能实现
  15. 计算机更新好不,Win10自动更新好不好有必要吗?如何关闭屏蔽Windows更新?
  16. 20172303 2017-2018-2 《程序设计与数据结构》第10周学习总结
  17. Python流程控制下:循环语句
  18. R 语言:简短的示例
  19. ESP32设备驱动-TM1637-驱动4位7段数码管
  20. 全权:从多旋翼角度看新时代下的航空人才需求

热门文章

  1. javascript基础语法——词法结构
  2. 9款jQuery插件为你的网站增加亮点
  3. 终于要考网络架构师了
  4. 软件黑盒测试的意思,请问黑盒测试是什么意思?
  5. 【ABAP】报表进度提示
  6. 如何根据事物代码查找相应BAPI
  7. abap 取数排序之后怎么取第一行
  8. smartforms不输出0
  9. 修改参数failed_login_attempts=unlimited
  10. 查看移动平均价的历史记录