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处理文本文件中控制字符的方法
Feb 07 Python
Python实现好友全头像的拼接实例(推荐)
Jun 24 Python
python dataframe常见操作方法:实现取行、列、切片、统计特征值
Jun 09 Python
NLTK 3.2.4 环境搭建教程
Sep 19 Python
opencv 获取rtsp流媒体视频的实现方法
Aug 23 Python
python实现树的深度优先遍历与广度优先遍历详解
Oct 26 Python
Python 元组拆包示例(Tuple Unpacking)
Dec 24 Python
Python GUI编程学习笔记之tkinter中messagebox、filedialog控件用法详解
Mar 30 Python
python爬虫实现爬取同一个网站的多页数据的实例讲解
Jan 18 Python
如何用python识别滑块验证码中的缺口
Apr 01 Python
教你如何用Python实现人脸识别(含源代码)
Jun 23 Python
尝试使用Python爬取城市租房信息
Apr 12 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 的 __FILE__ 常量
2007/01/15 PHP
phpmyadmin配置文件现在需要绝密的短密码(blowfish_secret)的2种解决方法
2014/05/07 PHP
PHP实现视频文件上传完整实例
2014/08/28 PHP
分享3个php获取日历的函数
2015/09/25 PHP
深入理解PHP中mt_rand()随机数的安全
2017/10/12 PHP
PHP实现的二分查找算法实例分析
2017/12/19 PHP
js中关于new Object时传参的一些细节分析
2011/03/13 Javascript
IE关闭时判断及AJAX注销案例学习
2013/02/18 Javascript
JavaScript访问字符串中单个字符的两种方法
2015/07/03 Javascript
JavaScript编程中布尔对象的基本使用
2015/10/25 Javascript
javascript仿京东导航左侧分类导航下拉菜单效果
2020/11/25 Javascript
jQuery grep()方法详解及实例代码
2016/10/30 Javascript
JS实现页面打印(整体、局部)
2017/08/18 Javascript
使用cookie绕过验证码登录的实现代码
2017/10/12 Javascript
Nuxt 项目性能优化调研分析
2020/11/07 Javascript
举例介绍Python中的25个隐藏特性
2015/03/30 Python
解决Python出现_warn_unsafe_extraction问题的方法
2016/03/24 Python
详解python实现线程安全的单例模式
2018/03/05 Python
Python实现获取前100组勾股数的方法示例
2018/05/04 Python
Python3实现爬虫爬取赶集网列表功能【基于request和BeautifulSoup模块】
2018/12/05 Python
PyCharm中代码字体大小调整方法
2019/07/29 Python
Python同时处理多个异常的方法
2020/07/28 Python
如何使用Python自动生成报表并以邮件发送
2020/10/15 Python
css3的transform中scale缩放详解
2014/12/08 HTML / CSS
使用css3实现的tab选项卡代码分享
2014/12/09 HTML / CSS
亚马逊中国官方网站:amazon.cn
2017/05/25 全球购物
西班牙最好的在线购买葡萄酒的商店:Vinoseleccion
2019/10/30 全球购物
奢华时尚的创新平台:Baltini
2020/10/03 全球购物
销售业务实习自我鉴定
2013/09/23 职场文书
成功经营餐厅的创业计划书范文
2013/12/26 职场文书
企业厂务公开实施方案
2014/03/26 职场文书
八项规定个人对照检查材料思想汇报
2014/09/25 职场文书
检察院对照“四风”认真查找问题落实整改措施
2014/09/26 职场文书
学校开学标语
2014/10/06 职场文书
结婚保证书(三从四德)
2015/02/26 职场文书
2016年社区中秋节活动总结
2016/04/05 职场文书