博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
tornado实现异步计划任务及python常见计划任务方法
阅读量:5825 次
发布时间:2019-06-18

本文共 4961 字,大约阅读时间需要 16 分钟。

主要是要实现tornado实现计划任务类crontab间隔 ~

大家看了标题,可能知道我要写啥了 ~ 对头,我用tornado实现一个类似crontab时间间隔调度的程序。

我为啥要写这个?

一方面是 更加深入的了解tornado异步方面的能力 。 另一方面是 在特殊的环境下编写更适合更方便自己的工具。

啥特殊的环境?

比如,我们有好几个后端脚本,这些脚本都要间隔的运行调度。然而这些程序都是秒级别的,这样的话,你用crontab就不太适合了。当然你可以后台仍个脚本,然后sleep 也是可以的。 要是很多的话? 你运行多个脚本?

我上个监控校验项目——就有很多的后台有间隔的脚本跑着。每次系统有改变我都要kill掉进程,调试好了,再start,挺蛋疼的~

后来我把很多的监控校验都放到一个脚本里面,然后开多线程,让他自己去sleep。以后我只需要kill掉一个进程就行了。

Python本身自带了一个调度模块sched,timer,官方给出的例子,都是那样,调用一次的用法。

任务是并发执行的,但是s.run()会把线程堵塞掉,所以咱们有必要把s.run()放到一个独立的线程去运行。当然你要是有需要的话。

>>> import sched, time>>> s = sched.scheduler(time.time, time.sleep)>>> def print_time(): print "From print_time", time.time()...>>> def print_some_times():...     print time.time()...     s.enter(5, 1, print_time, ())...     s.enter(10, 1, print_time, ())...     s.run()...     print time.time()...>>> print_some_times()930343690.257From print_time 930343695.274From print_time 930343700.273930343700.276

scheduler实例含有以下方法和属性:

scheduler.enterabs(time, priority, action, argument)    调度一个新事件,time参数应该是数值类型的。scheduler.enter(delay, priority, action, argument)    延迟调度一个事件,不同于相对时间scheduler.cancel(event)    在事件队列中移除一个事件,如果事件不在事件队列中,则触发ValueErrorscheduler.empty()  如果事件队列为空则返回Truescheduler.run()    运行所有的调度事件,该函数会等待下一个事件,然后执行他直到没有可调度的事件为止。scheduler.queue  只读属性,返回一个list,里面包含了即将运行的事件列表。

需要关注的是 sched模块不是循环的,一次调度被执行后就完事了,如果想再执行,请再次enter事件了。

我们再来感受下sched里面的timer !

>>> import time>>> from threading import Timer>>> def print_time():...     print "From print_time", time.time()...>>> def print_some_times():...     print time.time()...     Timer(5, print_time, ()).start()...     Timer(10, print_time, ()).start()...     time.sleep(11)  # sleep while time-delay events execute...     print time.time()...>>> print_some_times()930343690.257From print_time 930343695.274From print_time 930343700.273930343701.301

说完了后,我们这里跑个实际中能用到的例子:

我们跑看看,我们中间加了sleep 2s ,然而他所用的时间是7s,说明他是并发执行的。

关于线程的timer我简单写了个例子,跑了下,感觉怪怪的。

import threadingimport timedef timer_start():    t = threading.Timer(2,func,("xiaorui.cc","2s"))    t.start()    t2 = threading.Timer(4,rui,("4s","nima"))    t2.start()def func(msg1,msg2):    print "come on,",msg1,msg2    print time.strftime('%Y%m%d%H%M %S')    timer_start()def rui(msg3,nima):    print 'this is rui %s %s'%(msg3,nima)    timer_start()if __name__ == "__main__":    timer_start()    while True:        time.sleep(1)

运行的结果,时不时的会乱,这东西不太适合做crontab的效果。

我这里微微的总结下:

按照我的测试,sched和timer不适合做循环的计划任务,当然你可以在sched调用函数的时候,用while sleep的方法实现也是靠谱的。。。。

这是脚本的逻辑,大家可以试试

感觉python应该有靠谱点的计划任务模块,问了下朋友,他们现在用的是 APScheduler

一个很牛逼的库~ 已经测试过了

特定时间的运行:

from apscheduler.scheduler import Schedulersched = Scheduler()sched.daemonic = Falsedef job_function(text):    print textfrom datetime import datetimejob = sched.add_date_job(job_function, datetime(2013, 10, 11, 02, 36, 00), ['Hello World'])sched.start()

间隔的运行:

from apscheduler.scheduler import Schedulerimport timesched = Scheduler()sched.daemonic = Falsedef job_function():    print "wan si ni"    print time.strftime('%Y%m%d%H%M %S')sched.add_interval_job(job_function,  seconds=3)sched.start()

循环3s,ok !!!

哈,我简单说了下 python下实现计划任务的几种方式,本来要聊tornado,结果搞到标准库了。

晕,赶紧说正题:

python的web框架中tornado是强大的,他的IOLoop类是Tornado的边缘触发事件驱动模型,在Linux平台下面封装的是epoll模型。这就是他的异步模式的基础。

要是合成到tornado的ioloop的话,我启动一个主程序,不仅把相应的脚本按照间隔调度跑起来,主web也可以访问啦。

用python实现计划任务,除了python自带的shed,timer之外,我能想到的就是开多线程,自己去处理每个任务以及时间间隔。还有就是tornado的ioloop。

精力有限,现在还没有做出像linux系统下的crontab那样的工具。

我想到的思路是 配置文件可以就是crontab的时间语法,或者是咱们用yaml,configparser。程序启动的时候,开一个线程,专门关注这些个数据,对于任务和时间都要采用全局的变量,这些个函数进入主体的时候,先把global变量加载进来,然后大家就懂啦。。。。

下面是我用tornado ioloop实现的方法:

from tornado import web, ioloopimport datetimeperiod = 5 * 1000   # every 5 sclass MainHandler(web.RequestHandler):    def get(self):        self.write('Hello Tornado')def like_cron():    print datetime.datetime.now()def xiaorui():    print 'xiaorui 2s'def lee():    print 'lee 3s'                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 if __name__ == '__main__':    application = web.Application([        (r'/', MainHandler),        ])    application.listen(8081)    ioloop.PeriodicCallback(like_cron, period).start()  # start scheduler    ioloop.PeriodicCallback(lee, 3000).start()  # start scheduler    ioloop.IOLoop.instance().start()

结果:

再跑计划任务的时候,不影响web的访问

一眨眼,发现自己原本要写tornado,结果成大杂烩了~

微微总结下这几种计划任务的方法:

sched 就原版的例子来说,不适合做循环执行的,就单个计划任务是挺不错的。要是想做循环,不要让那个线程死掉,一直while True: 就行了

timer 同sched,不知道为啥多任务的时候,出现奇怪的问题。。。

apscheduler 这个是利器,好用,也是必须推荐使用的。

tornado 我自己觉得是很不错的,他和别的方法不一样,别人是线程,他是异步回调的方式,他背靠着epoll异步,所以很爽。

自己写 这个实现的思路,其实和sched timer,差不多的,我也有提过,就是个多线程,然后while True。

转载地址:http://gjidx.baihongyu.com/

你可能感兴趣的文章
Ubuntu上的pycrypto给出了编译器错误
查看>>
聊聊flink的RestClientConfiguration
查看>>
在CentOS上搭建git仓库服务器以及mac端进行克隆和提交到远程git仓库
查看>>
測試文章
查看>>
Flex很难?一文就足够了
查看>>
【BATJ面试必会】JAVA面试到底需要掌握什么?【上】
查看>>
CollabNet_Subversion小结
查看>>
mysql定时备份自动上传
查看>>
Linux 高可用集群解决方案
查看>>
17岁时少年决定把海洋洗干净,现在21岁的他做到了
查看>>
linux 启动oracle
查看>>
《写给大忙人看的java se 8》笔记
查看>>
我的友情链接
查看>>
倒计时:计算时间差
查看>>
Linux/windows P2V VMWare ESXi
查看>>
Windows XP倒计时到底意味着什么?
查看>>
tomcat一步步实现反向代理、负载均衡、内存复制
查看>>
运维工程师在干什么学些什么?【致菜鸟】
查看>>
Linux中iptables详解
查看>>
java中回调函数以及关于包装类的Demo
查看>>