python异步实现定时任务和周期任务的方法


Posted in Python onJune 29, 2019

一. 如何调用

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已运行,请勿重复启动!")

以上这篇python异步实现定时任务和周期任务的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python isinstance判断对象类型
Sep 06 Python
python中使用pyhook实现键盘监控的例子
Jul 18 Python
用Python的SimPy库简化复杂的编程模型的介绍
Apr 13 Python
总结python爬虫抓站的实用技巧
Aug 09 Python
python实现mysql的读写分离及负载均衡
Feb 04 Python
python实现词法分析器
Jan 31 Python
python绘制漏斗图步骤详解
Mar 04 Python
Python使用LDAP做用户认证的方法
Jun 20 Python
python2.7实现复制大量文件及文件夹资料
Aug 31 Python
pytorch 指定gpu训练与多gpu并行训练示例
Dec 31 Python
Python urlopen()和urlretrieve()用法解析
Jan 07 Python
打印tensorflow恢复模型中所有变量与操作节点方式
May 26 Python
python循环定时中断执行某一段程序的实例
Jun 29 #Python
python顺序执行多个py文件的方法
Jun 29 #Python
如何使用python把ppt转换成pdf
Jun 29 #Python
对Python的交互模式和直接运行.py文件的区别详解
Jun 29 #Python
使用python搭建服务器并实现Android端与之通信的方法
Jun 28 #Python
python全栈要学什么 python全栈学习路线
Jun 28 #Python
使用python 写一个静态服务(实战)
Jun 28 #Python
You might like
php下通过伪造http头破解防盗链的代码
2010/07/03 PHP
php setcookie函数的参数说明及其用法
2014/04/20 PHP
PHP经典面试题集锦
2015/03/19 PHP
ThinkPHP使用Smarty第三方插件方法小结
2016/03/19 PHP
PHP实现JS中escape与unescape的方法
2016/07/11 PHP
详解PHP中的外观模式facade pattern
2018/02/05 PHP
静态页面的值传递(三部曲)
2006/09/25 Javascript
基于JQuery的6个Tab选项卡插件
2010/09/03 Javascript
javascript正则表达式中参数g(全局)的作用
2010/11/11 Javascript
使用jQuery避免鼠标双击的解决方案
2013/08/21 Javascript
node.js中的fs.statSync方法使用说明
2014/12/16 Javascript
javascript实现详细时间提醒信息效果的方法
2015/03/11 Javascript
JQuery PHP图片在线裁剪实例
2020/07/27 Javascript
JavaScript 输出显示内容(document.write、alert、innerHTML、console.log)
2016/12/14 Javascript
Bootstrap CSS组件之按钮下拉菜单
2016/12/17 Javascript
获取今天,昨天,本周,上周,本月,上月时间(实例分享)
2017/01/04 Javascript
教你快速搭建Node.Js服务器的方法教程
2017/03/30 Javascript
ReactNative短信验证码倒计时控件的实现代码
2017/07/20 Javascript
小程序绑定用户方案优化小结
2019/05/15 Javascript
vue iview的菜单组件Mune 点击不高亮的解决方案
2019/11/01 Javascript
详解Python3的TFTP文件传输
2018/06/26 Python
树莓派使用python-librtmp实现rtmp推流h264的方法
2019/07/22 Python
Python argparse模块使用方法解析
2020/02/20 Python
python利用线程实现多任务
2020/09/18 Python
html Table 表头固定的实现
2019/01/22 HTML / CSS
HTML5本地存储之IndexedDB
2017/06/16 HTML / CSS
大学生关于奋斗的演讲稿
2014/01/09 职场文书
合作投资意向书
2014/04/01 职场文书
国贸专业求职信
2014/06/28 职场文书
乡镇领导干部个人对照检查材料思想汇报
2014/09/23 职场文书
2014年辅导员工作总结
2014/11/18 职场文书
店铺转让协议书
2015/01/29 职场文书
订货会主持词
2015/07/01 职场文书
幼儿园毕业致辞
2015/07/29 职场文书
2016医师资格考试考生诚信考试承诺书
2016/03/25 职场文书
总结Java对象被序列化的两种方法
2021/06/30 Java/Android