Python:定时任务

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Abstract: 定时任务
 
import os
import re
import sys
import logging
import datetime
import threading,time
sys.path.append(os.path.dirname(os.path.split(os.path.realpath(__file__))[0]))
from lib.mail import Mail
from tornado.template import Template,Loader
from model.morule import MoRule
from model.mojob import MoJobTimer,MoJobLog
from conf.style_dic import DicMap
from service.alarmhandler import AlarmHandler
from lib.database2org import ModelMap
from lib.databaseBkorg import ModelMapBak
 
class Timer(threading.Thread):
    '''
    定时任务
    self.isPlay和self.fnPlay保证程序执行完毕才退出,而不是直接退出
    self.lastDo声明当定时器收到结束命令的时候是否最后执行一次,以保证数据的完整性
    '''
    #初始化定时任务相关参数
    def __init__(self,fn,args=(),interval=0,lastDo=True):
        threading.Thread.__init__(self)
        self.fn = fn
        self.args = args
        self.interval = interval
        self.lastDo = lastDo
        self.setDaemon(True) #设置该线程为守护线程
        self.isPlay = True
        self.fnPlay = False
 
    def __do(self):
        logging.info('start sched: %s',datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
        #self.fnPlay = True
        apply(self.fn,self.args)
        self.fnPlay = False
 
    def run(self):
        '''
        线程执行体
        '''
        while self.isPlay:
            time.sleep(self.interval)
            self.__do()
 
    def stop(self):
        self.isPlay = False
        print self.fnPlay
        while True:
            if not self.fnPlay : break
            time.sleep(0.01)
        if self.lastDo : self.__do()
        logging.info('close sched: %s',datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
 
class ExtTimerRun(object):
    '''
    定时任务执行体,加入了执行方式,执行间隔设置等业务内容
    '''
    def __init__(self):
        '''
        初始化执行间隔和报警标识
        '''
        self.__interval = 5.0
        self.isAlarm = False
                       
    def __timerFunc(self,rule_id,alarm_type,note_id,mail_id,timer_id):
        '''
        线程实际执行的方法体
        '''
        timer_job = MoJobTimer.mgr(ismaster=True).one(timer_id)
        #记录线程开始执行时间
        t = MoJobLog.new()
        t.timer_id,t.timer_name = timer_id,timer_job.name
        t.thr_name,t.is_alive = self.__timer.getName(),self.__timer.isAlive()
        t.job_status = DicMap.RUN_START
        t = t.save()
        log_id = t.id
 
        #扫描到停止线程请求,则调用线程暂停请求
        if timer_job.is_run<>DicMap.THREAD_RUN:
            logging.info('===>Stopping the timer.The timer is %s',timer_id)
            MoJobTimer.mgr(ismaster=True).raw("update mo_job_timer set is_run='%s' where id=%s"%(DicMap.THREAD_STOPING,timer_id))
            self.__timer.stop()
            MoJobTimer.mgr(ismaster=True).raw("update mo_job_timer set is_run='%s' where id=%s"%(DicMap.THREAD_STOP,timer_id))
            #记录线程日志差值
            log = MoJobLog.mgr(ismaster=True).one(log_id)
            log.end_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            log.job_status = DicMap.RUN_STOP
            t.use_time = '%s秒'%((datetime.datetime.now()-log.start_time).seconds)
            t = t.save()
            return
 
        #对定时任务执行类型进行过滤
        now_time = datetime.datetime.now()
        timeEq = datetime.timedelta(minutes=0)
        #按时间段执行
        if DicMap.JOB_TYPE_BETWEEN==timer_job.job_type:
            start_time = timer_job.start_time
            end_time = timer_job.end_time
            #如果不在时间段内,则结束定时任务运行
            if (start_time - now_time)>timeEq or (now_time - end_time)>timeEq:
                MoJobTimer.mgr(ismaster=True).raw("update mo_job_timer set is_run='%s' where id=%s"%(DicMap.THREAD_STOPING,timer_id)
)
                self.__timer.stop()
                return
 
        #按时间点执行
        elif DicMap.JOB_TYPE_POINT==timer_job.job_type:
            trigger_time = timer_job.trigger_time
            timeSpace = datetime.timedelta(minutes=40)
            start_time = trigger_time - timeSpace
            end_time = trigger_time + timeSpace
            if not ((now_time - start_time)>timeEq and (end_time - now_time)>timeEq):
                time.sleep(30*60)
            else:
                if timer_job.interval==DicMap.INTERVAL_DAY:
                    timer_job.trigger_time = timer_job.trigger_time + datetime.timedelta(days=1)
                elif timer_job.interval==DicMap.INTERVAL_WEEK:
                    timer_job.trigger_time = timer_job.trigger_time + datetime.timedelta(days=7)
                elif timer_job.interval==DicMap.INTERVAL_MONTH:
                    timer_job.trigger_time = timer_job.trigger_time + datetime.timedelta(days=30)
                timer_job = timer_job.save()
        #标志当前线程体正在执行,确保数据的完整,避免在停止线程时产生脏数据
        self.__timer.fnPlay = True
 
        #获取规则数据,驱动执行,获取执行结果,并发送模板报警
        rule = MoRule.mgr(ismaster=True).one(rule_id)
        rs = []
        thrName = self.__timer.getName()
        MoJobLog.mgr(ismaster=True).raw("update mo_job_log set job_status='%s' where id=%s"%(DicMap.RUN_EXECU,log_id))
        #规则类型:简单汇总、使用执行体
        if rule.rule_type==DicMap.CORE_DRIVER_TYPE_SIMPLE_SUMMARY and rule.is_use_task==DicMap.YES:
            logging.info("Run Simple SQL.")
            runTask = rule.run_task #执行体
            rs = ModelMap().raw(runTask)
            if len(rs)>0:
                self.isAlarm = True
            logging.info('The runTask is : %s',runTask)
        elif rule.rule_type==DicMap.CORE_DRIVER_TYPE_SIMPLE_PROCEDURE and rule.is_use_task==DicMap.YES:
            procName = rule.proc_name #存储过程名
            logging.info("Run Procedure %s .",procName)
            param = (thrName,)
            result = ModelMap().call(procName,param)
            if result.data:
                self.isAlarm = True
                runTask = rule.run_task
                out_exec_timestamp = result.data[0][0]
                query_sql = runTask%out_exec_timestamp
                rs = ModelMap().raw(query_sql)
                delete_sql = "DELETE FROM temp_op_monitor_proc WHERE exec_timestamp='%s'"%out_exec_timestamp
                ModelMap(ismaster=True).raw(delete_sql)
        elif rule.rule_type==DicMap.CORE_DRIVER_TYPE_JUMP_SUMMARY and rule.is_use_task==DicMap.YES:
            logging.info("Run Over Database SQL.")
            runTask = rule.run_task #执行体
            runTaskSlave = rule.run_task_slave #从库执行体
            rs_master = ModelMap().raw(runTask)
            if len(rs_master)>0:
                self.isAlarm = True
                fd_arr = re.findall( r'(?<=/\$).+?(?=\$/)' , runTaskSlave )
                for rec in rs_master:
                    master_rec_keys = rec.keys()
                    runTaskSlaveTmp = runTaskSlave
                    #完成动态参数替换
                    for slave_key in fd_arr:
                        slave_key = slave_key.strip()
                        if rec.has_key(slave_key):
                            rep_key = '/$'+slave_key+'$/'
                            runTaskSlaveTmp = runTaskSlaveTmp.replace(rep_key,str(rec.get(slave_key)))
                    rs_slave = ModelMapBak().raw(runTaskSlaveTmp)
                    if rs_slave and len(rs_slave)>0:
                        rs_slave_rec = rs_slave[0]
                        rs.append(dict(rec,**rs_slave_rec))
        else:
            pass
        #是否发警报
        if self.isAlarm:
            AlarmHandler.alarm(self,rule.data_head,rs,alarm_type,note_id,mail_id,timer_id)
       
        #记录线程日志差值
        log = MoJobLog.mgr(ismaster=True).one(log_id)
        log.end_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        log.use_time = '%s秒'%((datetime.datetime.now()-log.start_time).seconds)
        log.job_status = DicMap.RUN_STOP
        log = log.save()
 
 
    def createTimer(self, interval,rule_id,alarm_type,note_id,mail_id,timer_id):
        '''
        定时任务线程创建,并启动线程
        '''
        self.__interval = interval
        self.__timer = Timer(self.__timerFunc,(rule_id,alarm_type,note_id,mail_id,timer_id,),self.__interval,False)
        self.__timer.start()
        th_info = self.__timer.getName()
        th_isAlive = self.__timer.isAlive()
        #logging.info("The thread info .thread-Name:%s isAlive:%s ",(th_info,th_isAlive))
        return th_info,th_isAlive
 
 
if __name__ == "__main__":
    print "start timer"
    t = ExtTimerRun()
    #每隔一秒执行一次
    t.createTimer(1)
    while True:
        pass  
--------------------------------------------------------------------------------------------------------
定时任务的使用
        logging.info("---->start timer. ")
        #创建定时任务,并执行
        t = ExtTimerRun()
        MoJobTimer.mgr(ismaster=True).raw("update mo_job_timer set run_status='%s'where id=%s" %(DicMap.RUN_START,timer_id), ())
        thrID,thrStatus = t.createTimer(self.interval,rule_id,alarm_type,note_id,mail_id,timer_id)
 

posted on 2014-05-21 09:25  云梦山庄  阅读(2058)  评论(0)    收藏  举报

导航