过了年就开始面临毕业了,毕业季是幸福的,但也是紧迫的。2月已过就开始着手策划毕业论文了,一直到现在,论文基本完成了,感觉过去的一个半月的时间,对自己过去2年在实验室所学又温习了一遍。书到用时方恨少,在实验室研究论文的那段日子费了不少精力,等到现在写论文再回头去回忆自己所看文献的时候,突然发现当时没有做个详细的论文研究笔记是一个严重的失误。于是,写论文的过程变成了读一遍文献写一小段,到论文完成,我发现我温故知新,在很多以前没有理解的部分上有了新的认识!
好了,上面是对我最近生活的一点概况。2月下旬,有人看到我在博客园的一片随笔,关于SmartAPI的,然后通过QQ联系我,让我帮忙写个小程序,用于实时的去获取API接口所提供的所有城市的天气状况,于是我在那一周,挤出点时间出来,花了约3天的时间写了一个小demo,初步有了一个成果,并且程序比较稳健。
今天我就其中的一个部分和大家一起分享。客户的需求是,每隔2个小时收集一次实况天气预报,所以我需要写一个简单的调配程序来完成这个任务,即需要一个守护进程去计时,在指定的时间间隔自动调用相关的程序完成数据收集的过程。
开发环境: Windows8.1 + Python2.7
好了,废话不多说,先上代码:
import sched, time from threading import Thread, Timer import subprocess import sys s = sched.scheduler(time.time, time.sleep) class Job(Thread): def __init__(self, loc): Thread.__init__(self) self.loc = loc def run(self): print_time() print ‘--------------- begin to get weather info ---------------‘ subprocess.call("forecast3d.exe " + self.loc) print ‘--------------- end to get weather info ---------------‘ def each_day_time(hour, min, sec, next_day): struct = time.localtime() if next_day == 0: day = struct.tm_mday + 1 else: day = struct.tm_mday return time.mktime((struct.tm_year,struct.tm_mon,day, hour,min,sec,struct.tm_wday, struct.tm_yday, struct.tm_isdst)) def print_time(): print "From print_time", time.ctime() def do_somthing(loc): job = Job(loc) job.start() def echo_start_msg(): print ‘**************** auto task begin running ****************‘ def main(loc, istomorrow=1): print ‘-------------- scheduled task will run once every two hours --------------‘ s.enterabs(each_day_time(8, 0, 0, istomorrow), 1, echo_start_msg, ()) s.run() while(True): Timer(0, do_somthing, (loc,)).start() time.sleep(3 * 60 * 60) if __name__ == "__main__": if len(sys.argv) < 2: print ‘Usage: taskSched location <istomorrow>‘ sys.exit() elif len(sys.argv) == 2: main(sys.argv[1]) else: main(sys.argv[1], sys.argv[2])
在Python中,标准库中提供了用于定时的执行某个任务的模块,即sched和Timer类。先说sched模块,准确的说,它是一个调度(延时处理机制),每次想要定时执行某任务都必须写入一个调度。
使用步骤如下:
(1)生成调度器:
s = sched.scheduler(time.time,time.sleep)
第一个参数是一个可以返回时间戳的函数,第二个参数可以在定时未到达之前阻塞。可以说sched模块设计者是“在下很大的一盘棋”,比如第一个函数可以是自定义的一个函数,不一定是时间戳,第二个也可以是阻塞socket等。
(2)加入调度事件
其实有enter、enterabs等等,我们以enter为例子。
s.enter(x1,x2,x3,x4)
四个参数分别为:间隔事件、优先级(用于同时间到达的两个事件同时执行时定序)、被调用触发的函数,给他的参数(注意:一定要以tuple给如,如果只有一个参数就(xx,))。
(3)运行
s.run()
分析上面的程序,我们可以知道,我们得目的就是检测系统的时间,当系统时间到达早上8点这个临界点,程序触发。这样的目的就是为了方便程序在前一天晚上跑起来,在第二天的早上8点开始获取第一批数据。
那么,Timer模块的作用呢,说白了就是计时器,程序循环计时,每过一定的时间执行一次收集操作。
最近论文写作完成,下一步的工作是将调度程序写成Windows服务,开机自启动,更加方便!