Python定时任务
Python下实现定时任务的方式有很多种方式。
循环sleep:
这是一种最简单的方式,在循环里放入要执行的任务,然后sleep一段时间再执行。缺点是,不容易控制,而且sleep是个阻塞函数。
def timer(n): ''''' 每n秒执行一次 ''' while True: print time.strftime('%Y-%m-%d %X',time.localtime()) yourTask() # 此处为要执行的任务 time.sleep(n)
threading的Timer:
threading模块中的Timer能够帮助实现定时任务,而且是非阻塞的。
比如3秒后打印helloworld:
def printHello(): print "hello world" Timer(3, printHello).start()
比如每3秒打印一次helloworld:
def printHello(): print "Hello World" t = Timer(2, printHello) t.start() if __name__ == "__main__": printHello()
使用sched模块:
sched是一种调度(延时处理机制)。
# -*- coding:utf-8 -*- # use sched to timing import time import os import sched # 初始化sched模块的scheduler类 # 第一个参数是一个可以返回时间戳的函数,第二个参数可以在定时未到达之前阻塞。 schedule = sched.scheduler(time.time, time.sleep) # 被周期性调度触发的函数 def execute_command(cmd, inc): ''''' 终端上显示当前计算机的连接情况 ''' os.system(cmd) schedule.enter(inc, 0, execute_command, (cmd, inc)) def main(cmd, inc=60): # enter四个参数分别为:间隔事件、优先级(用于同时间到达的两个事件同时执行时定序)、被调用触发的函数, # 给该触发函数的参数(tuple形式) schedule.enter(0, 0, execute_command, (cmd, inc)) schedule.run() # 每60秒查看下网络连接情况 if __name__ == '__main__': main("netstat -an", 60)
使用定时框架APScheduler:
APScheduler是基于Quartz的一个Python定时任务框架。提供了基于日期、固定时间间隔以及crontab类型的任务,并且可以持久化任务。
这个现在还没自己尝试过,等过段时间用了再来补充。
使用windows的定时任务:
这里可以将所需要的Python程序打包成exe文件,然后在windows下设置定时执行。
使用Linux的定时任务(Crontab):
在Linux下可以很方便的借助Crontab来设置和运行定时任务。进入Crontab文件编辑页面,设置时间间隔,使用一些shell命令来运行bash脚本或者是Python脚本,保存后Linux会自动按照设定的时间来定时运行程序。
http://blog.csdn.net/whiterbear/article/details/50232637
有这方面需求,但是在网上找了半天没有每天特定时间执行任务的相关的包
就参考这位大神的代码写了一个
# -*- coding:utf-8 -*- """ -------------------------------- @Author: Dyson @Contact: Weaver1990@163.com @file: timer.py @time: 2017/7/20 11:01 -------------------------------- """ import time import os import sched import sys import datetime # 初始化sched模块的scheduler类 # 第一个参数是一个可以返回时间戳的函数,第二个参数可以在定时未到达之前阻塞。 schedule = sched.scheduler(time.time, time.sleep) sys.path.append(sys.prefix + "\\Lib\\MyWheels") reload(sys) sys.setdefaultencoding('utf8') start_time = 0 end_time = 0 class mytimer(object): # 被周期性调度触发的函数 def execute_command(self, cmd, inc): start_time = datetime.datetime.now() os.system(cmd) time.sleep(3) end_time = datetime.datetime.now() delay = round((end_time-start_time).total_seconds()) print print u'mytimer => 开始时间:%s' % start_time print u'mytimer => 耗时:%smin' %(delay/60) schedule.enter(int(inc-delay), 0, self.execute_command, (cmd, inc)) print u'mytimer => 结束时间:%s' % end_time def cmd_timer(self, cmd, time_str, inc=60): # cmd:windows中命令行代码 # time_str:哪一个时间点开始第一次执行 # inc:两次执行的间隔时间 # enter四个参数分别为:间隔时间、优先级(用于同时间到达的两个事件同时执行时定序)、被调用触发的函数, # 给该触发函数的参数(tuple形式) now = datetime.datetime.now() schedule_time = datetime.datetime.strptime(time_str,'%H:%M').replace(year=now.year,month=now.month,day=now.day) if schedule_time < now: schedule_time = schedule_time + datetime.timedelta(days=1) time_before_start = int(round((schedule_time-datetime.datetime.now()).total_seconds())) print u'mytimer => 还有%s秒开始任务' %time_before_start schedule.enter(time_before_start, 0, self.execute_command, (cmd, inc)) schedule.run() if __name__ == '__main__': mytimer = mytimer() mytimer.cmd_timer("netstat -an", '15:07', 60)
Python 定时任务
最近学习到了 python 中两种开启定时任务的方法,和大家分享一下心得。
- sched.scheduler()
- threading.Timer()
sched 定时任务
使用sched的套路如下:
s = sched.scheduler(time.time, time.sleep)
s.enter(delay, priority, func1, (arg1, arg2, ...))
s.enter(delay, priority, func2, (arg1, arg2, arg3, ...))
s.run()
第一步新建一个调度器;
第二步添加任务,可以添加多个任务;
第三步让调度器开始运行。
第二步各参数含义:
- delay 相对于调度器添加这个任务时刻的延时,以秒为单位;
- priority 优先级,数字越小优先级越高;
- func1 任务函数
- (arg1, arg2, ...) 任务函数的参数
import time import sched # 第一个工作函数 # 第二个参数 @starttime 表示任务开始的时间 # 很明显参数在建立这个任务的时候就已经传递过去了,至于任务何时开始执行就由调度器决定了 def worker(msg, starttime): print u"任务执行的时刻", time.time(), "传达的消息是", msg, '任务建立时刻', starttime # 创建一个调度器示例 # 第一参数是获取时间的函数,第二个参数是延时函数 print u'---------- 两个简单的例子 -------------' print u'程序启动时刻:', time.time() s = sched.scheduler(time.time, time.sleep) s.enter(1, 1, worker, ('hello', time.time())) s.enter(3, 1, worker, ('world', time.time())) s.run() # 这一个 s.run() 启动上面的两个任务 print u'睡眠2秒前时刻:', time.time() time.sleep(2) print u'睡眠2秒结束时刻:', time.time() # 重点关注下面2个任务,建立时间,启动时间 # 2个任务的建立时间都很好计算,但有没有发现 "hello world [3]" 的启动时间比建立时间晚 13 秒, # 这不就是2个 sleep 的总延时吗?所以说启动时间并不一定就是 delay 能指定的,还需要看具体的程序环境, # 如果程序堵塞的很厉害,已经浪费了一大段的时间还没有到 scheduler 能调度这个任务,当 scheduler 能调度这个 # 任务的时候,发现 delay 已经过去了, scheduler 为了弥补“罪过”,会马上启动这个任务。 # 任务 "hello world [15]" 就是一个很好的例子,正常情况下,程序没有阻塞的那么厉害,在scheduler 能调度这个任务的时候 # 发现 delay 还没到就等待,如果 delay 时间到了就可以在恰好指定的延时调用这个任务。 print u'\n\n---------- 两个复杂的例子 -------------' s.enter(3, 1, worker, ('hello world [3]', time.time())) print u'睡眠7秒前时刻:', time.time() time.sleep(7) print u'睡眠7秒结束时刻:', time.time() s.enter(15, 1, worker, ('hello world [15]', time.time())) print u'睡眠6秒前时刻:', time.time() time.sleep(6) print u'睡眠6秒结束时刻:', time.time() s.run() # 过了2秒之后,启动另外一个任务 print u'程序结束时刻', time.time() ---------- 两个简单的例子 ------------- 程序启动时刻: 1481731389.4 任务执行的时刻 1481731390.4 传达的消息是 hello 任务建立时刻 1481731389.4 任务执行的时刻 1481731392.41 传达的消息是 world 任务建立时刻 1481731389.4 睡眠2秒前时刻: 1481731392.41 睡眠2秒结束时刻: 1481731394.41 ---------- 两个复杂的例子 ------------- 睡眠7秒前时刻: 1481731394.41 睡眠7秒结束时刻: 1481731401.42 睡眠6秒前时刻: 1481731401.42 睡眠6秒结束时刻: 1481731407.42 任务执行的时刻 1481731407.42 传达的消息是 hello world [3] 任务建立时刻 1481731394.41 任务执行的时刻 1481731416.43 传达的消息是 hello world [15] 任务建立时刻 1481731401.42 程序结束时刻 1481731416.43
自调任务1
任务快结束时利用 scheduler 又重新调用自己让自己“活过来”。
# 计数器,一个循环任务,总共让自己执行3次 total = 0 # 第二个工作函数,自调任务,自己开启定时并启动。 def worker2(msg, starttime): global total total += 1 print u'当前时刻:', time.time(), '消息是:', msg, ' 启动时间是:', starttime # 只要没有让自己调用到第3次,那么继续重头开始执行本任务 if total < 3: # 这里的delay 可以重新指定 s.enter(5, 2, worker2, ('perfect world %d' % (total), time.time())) s.run() print u'程序开始时刻:', time.time() # 开启自调任务 s.enter(5, 2, worker2, ('perfect world %d' % (total), time.time())) s.run() print u'程序结束时刻:', time.time()
程序开始时刻: 1481731439.42 当前时刻: 1481731444.43 消息是: perfect world 0 启动时间是: 1481731439.42 当前时刻: 1481731449.44 消息是: perfect world 1 启动时间是: 1481731444.43 当前时刻: 1481731454.44 消息是: perfect world 2 启动时间是: 1481731449.44 程序结束时刻: 1481731454.44
Threading.Timer() 定时任务
from threading import Timer import time def func(msg, starttime): print u'程序启动时刻:', starttime, '当前时刻:', time.time(), '消息内容 --> %s' % (msg) # 下面的两个语句和上面的 scheduler 效果一样的 Timer(5, func, ('hello', time.time())).start() Timer(3, func, ('world', time.time())).start()
程序启动时刻: 1481731467.28 当前时刻: 1481731470.28 消息内容 --> world
程序启动时刻: 1481731467.28 当前时刻: 1481731472.28 消息内容 --> hello
循环任务2
利用 threading.Timer() 建立的自调任务
count = 0 def loopfunc(msg,starttime): global count print u'启动时刻:', starttime, ' 当前时刻:', time.time(), '消息 --> %s' % (msg) count += 1 if count < 3: Timer(3, loopfunc, ('world %d' % (count), time.time())).start() Timer(3, loopfunc, ('world %d' % (count), time.time())).start()
启动时刻: 1481731476.35 当前时刻: 1481731479.35 消息 --> world 0 启动时刻: 1481731479.35 当前时刻: 1481731482.35 消息 --> world 1 启动时刻: 1481731482.35 当前时刻: 1481731485.35 消息 --> world 2

浙公网安备 33010602011771号