通过一个python线程异步实现 [定时任务] + [周期任务]

一.如何调用

    def f1(arg1, arg2):
        print('f1', arg1, arg2)
     
     
    def f2(arg1):
        print('f2', arg1)
     
     
    def f3():
        print('f3')
     
     
    def f4():
        print('周期任务', int(time.time()))
     
     
    timer = TaskTimer()
    # 把任务加入任务队列
    timer.join_task(f1, [1, 2], timing=15.5)  # 每天15:30执行
    timer.join_task(f2, [3], timing=14)  # 每天14:00执行
    timer.join_task(f3, [], timing=15)  # 每天15:00执行
    timer.join_task(f4, [], interval=10)  # 每10秒执行1次
    # 开始执行(此时才会创建线程)
    timer.start()

f1~f4是我们需要定时执行的函数。

首先创建TaskTimer对象(TaskTimer的代码在下面)。调用join_task函数,把需要执行的函数加入到任务队列。最后调用start,任务就开始执行了。

join_task参数:

fun:需要执行的函数

arg:fun的参数,如果没有就传一个空列表

interval:如果有此参数,说明任务是周期任务,单位为秒(注意interval最少5秒)

timing:如果有此参数,说明任务是定时任务,单位为时

注意:interval和timing只能选填1个
 
二.源码

    import datetime
    import time
    from threading import Thread
    from time import sleep
     
     
    class TaskTimer:
        __instance = None
     
        def __new__(cls, *args, **kwargs):
            """
            单例模式
            """
            if not cls.__instance:
                cls.__instance = object.__new__(cls)
            return cls.__instance
     
        def __init__(self):
            if not hasattr(self, 'task_queue'):
                setattr(self, 'task_queue', [])
     
            if not hasattr(self, 'is_running'):
                setattr(self, 'is_running', False)
     
        def write_log(self, level, msg):
            cur_time = datetime.datetime.now()
            with open('./task.log', mode='a+', encoding='utf8') as file:
                s = "[" + str(cur_time) + "][" + level + "]   " + msg
                print(s)
                file.write(s + "\n")
     
        def work(self):
     
            """
            处理任务队列
            """
            while True:
                for task in self.task_queue:
                    if task['interval']:
                        self.cycle_task(task)
                    elif task['timing']:
                        self.timing_task(task)
     
                sleep(5)
     
        def cycle_task(self, task):
            """
            周期任务
            """
            if task['next_sec'] <= int(time.time()):
                try:
                    task['fun'](*task['arg'])
                    self.write_log("正常", "周期任务:" + task['fun'].__name__ + " 已执行")
                except Exception as e:
                    self.write_log("异常", "周期任务:" + task['fun'].__name__ + " 函数内部异常:" + str(e))
                finally:
                    task['next_sec'] = int(time.time()) + task['interval']
     
        def timing_task(self, task):
            """
            定时任务
            """
            # 今天已过秒数
            today_sec = self.get_today_until_now()
     
            # 到了第二天,就重置任务状态
            if task['today'] != self.get_today():
                task['today'] = self.get_today()
                task['today_done'] = False
     
            # 第一次执行
            if task['first_work']:
                if today_sec >= task['task_sec']:
                    task['today_done'] = True
                    task['first_work'] = False
                else:
                    task['first_work'] = False
     
            # 今天还没有执行
            if not task['today_done']:
                if today_sec >= task['task_sec']:  # 到点了,开始执行任务
                    try:
                        task['fun'](*task['arg'])
                        self.write_log("正常", "定时任务:" + task['fun'].__name__ + " 已执行")
                    except Exception as e:
                        self.write_log("异常", "定时任务:" + task['fun'].__name__ + " 函数内部异常:" + str(e))
                    finally:
                        task['today_done'] = True
                        if task['first_work']:
                            task['first_work'] = False
     
        def get_today_until_now(self):
            """
            获取今天凌晨到现在的秒数
            """
            i = datetime.datetime.now()
            return i.hour * 3600 + i.minute * 60 + i.second
     
        def get_today(self):
            """
            获取今天的日期
            """
            i = datetime.datetime.now()
            return i.day
     
        def join_task(self, fun, arg, interval=None, timing=None):
            """
            interval和timing只能存在1个
            :param fun: 你要调用的任务
            :param arg: fun的参数
            :param interval: 周期任务,单位秒
            :param timing: 定时任务,取值:[0,24)
            """
            # 参数校验
            if (interval != None and timing != None) or (interval == None and timing == None):
                raise Exception('interval和timing只能选填1个')
     
            if timing and not 0 <= timing < 24:
                raise Exception('timing的取值范围为[0,24)')
     
            if interval and interval < 5:
                raise Exception('interval最少为5')
     
            # 封装一个task
            task = {
                'fun': fun,
                'arg': arg,
                'interval': interval,
                'timing': timing,
            }
            # 封装周期或定时任务相应的参数
            if timing:
                task['task_sec'] = timing * 3600
                task['today_done'] = False
                task['first_work'] = True
                task['today'] = self.get_today()
            elif interval:
                task['next_sec'] = int(time.time()) + interval
     
            # 把task加入任务队列
            self.task_queue.append(task)
     
            self.write_log("正常", "新增任务:" + fun.__name__)
     
        def start(self):
            """
            开始执行任务
            返回线程标识符
            """
            if not self.is_running:
                thread = Thread(target=self.work)
     
                thread.start()
     
                self.is_running = True
     
                self.write_log("正常", "TaskTimer已开始运行!")
     
                return thread.ident
     
            self.write_log("警告", "TaskTimer已运行,请勿重复启动!")
---------------------
作者:狡猾的皮球
来源:CSDN
原文:https://blog.csdn.net/qq_39687901/article/details/81985767
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

正在修炼的IT大佬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值