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

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

(0)

相关推荐

  • Python实现定时任务

    Python下实现定时任务的方式有很多种方式.下面介绍几种 循环sleep: 这是一种最简单的方式,在循环里放入要执行的任务,然后sleep一段时间再执行.缺点是,不容易控制,而且sleep是个阻塞函数. def timer(n): ''''' 每n秒执行一次 ''' while True: print time.strftime('%Y-%m-%d %X',time.localtime()) yourTask() # 此处为要执行的任务 time.sleep(n) threading的Time

  • 对python周期性定时器的示例详解

    一.用thread实现定时器 py_timer.py文件 #!/usr/bin/python #coding:utf-8 import threading import os import sys class _Timer(threading.Thread): def __init__(self, interval, function, args=[], kwargs={}): threading.Thread.__init__(self) self.interval = interval se

  • Python3实现定时任务的四种方式

    最近做一个小程序开发任务,主要负责后台部分开发:根据项目需求,需要实现三个定时任务: 1>定时更新微信token,需要2小时更新一次: 2>商品定时上线: 3>定时检测后台服务是否存活: 使用Python去实现这三个任务,这里需要使用定时相关知识点: Python实现定点与定时任务方式比较多,找到下面四中实现方式,每个方式都有自己应用场景:下面来快速介绍Python中常用的定时任务实现方式: 1>循环+sleep: 2>线程模块中Timer类: 3>schedule模块

  • Django配置celery(非djcelery)执行异步任务和定时任务

    所有演示均基于Django2.0 celery是一个基于python开发的简单.灵活且可靠的分布式任务队列框架,支持使用任务队列的方式在分布式的机器/进程/线程上执行任务调度.采用典型的生产者-消费者模型,主要由三部分组成: 消息队列broker:broker实际上就是一个MQ队列服务,可以使用redis.rabbitmq等作为broker 处理任务的消费者workers:broker通知worker队列中有任务,worker去队列中取出任务执行,每一个worker就是一个进程 存储结果的bac

  • Python实现定时执行任务的三种方式简单示例

    本文实例讲述了Python实现定时执行任务的三种方式.分享给大家供大家参考,具体如下: 1.定时任务代码 #!/user/bin/env python # @Time :2018/6/7 16:31 # @Author :PGIDYSQ #@File :PerformTaskTimer.py #定时执行任务命令 import time,os,sched schedule = sched.scheduler(time.time,time.sleep) def perform_command(cmd

  • Python3中常用的处理时间和实现定时任务的方法的介绍

    无论哪种编程语言,时间肯定都是非常重要的部分,今天来看一下python如何来处理时间和python定时任务,注意咯:本篇所讲是python3版本的实现,在python2版本中的实现略有不同,有时间会再写一篇以便大家区分. 1.计算明天和昨天的日期 #! /usr/bin/env python #coding=utf-8 # 获取今天.昨天和明天的日期 # 引入datetime模块 import datetime #计算今天的时间 today = datetime.date.today() #计算

  • 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(f

  • python的schedule定时任务模块二次封装方法

    通过定时来执行任务,我们日常工作生活中会经常用到.python有schedule这个库,简单好用,比如,可以每秒,每分,每小时,每天,每天的某个时间点,间隔天数的某个时间点定时执行,另外自己又写了一个可以自定义时间点来定时执行任务,代码如下. import schedule import time class Timing(): #按秒循环定时执行任务 def doEverySecond(self,seconds,job_func): try: schedule.every(seconds).s

  • Python脚本实现定时任务的最佳方法

    目录 前言 问题描述 解决方案 总结 前言 在日常工作中,常常需要周期性地执行某些任务,常用的方式是采用 Linux 系统自带的 crond 结合命令行实现,但最近却遇到了一个让人头大的问题. 问题描述 一个包含cx_Oracle的python文件,直接在linux下使用python命令可以运行,但是设置crontab定时任务会报错如下: cx_Oracle.DatabaseError: DPI-1047: 64-bit Oracle Client library cannot be loade

  • Python命令行定时任务自动化工作流程

    目录 1.使用场景 2.库 3.运行脚本 4.脚本 5.python常用的定时任务 6.四种方法用python调用命令行 1.使用场景 定时执行jmeter脚本,通过python定时器隔一段时间执行命令行命令. 2.库 os.datetime.threading (1)利用threading.Timer()定时器实现定时任务 Timer方法 说明 Timer(interval, function, args=None, kwargs=None) 创建定时器 cancel() 取消定时器 star

  • 对Python定时任务的启动和停止方法详解

    在python中我们可以使用APScheduler进行定时任务. APScheduler的具体编码这里就不介绍了.主要说下在终端中启动和停止任务. 一.运行计划任务的python脚本 如果我们在终端中直接执行的话,关闭终端窗口,Python任务就会中断,Python进程会被杀死,程序将停止运行.可以使用如下命令运行python脚本, python apschedulerscript.py & 这样执行后及时关闭终端窗口,程序依旧运行. 二.停止计划任务的Python脚本 如何停止呢,可使用如下方

  • Python 异步协程函数原理及实例详解

    这篇文章主要介绍了Python 异步协程函数原理及实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一. asyncio 1.python3.4开始引入标准库之中,内置对异步io的支持 2.asyncio本身是一个消息循环 3.步骤: (1)创建消息循环 (2)把协程导入 (3)关闭 4.举例: import threading # 引入异步io包 import asyncio # 使用协程 @ asyncio.coroutine def

  • Python异步编程之协程任务的调度操作实例分析

    本文实例讲述了Python异步编程之协程任务的调度操作.分享给大家供大家参考,具体如下: 我们知道协程是异步进行的,碰到IO阻塞型操作时需要调度其他任务,那么这个调度规则或者是算法是怎样的呢?现在有以下几个疑问: 1.多个任务准备好,需要运行时,优先执行哪一个? 2.一个任务运行时,如果别的任务准备好了,是否需要中断当前任务呢? 在网上找了很多资料,也无法找到相关的资料,于是编写了几个简单的程序,查看任务的执行过程. 根据Python的asyncio我们可以编写一个简单的程序: import a

  • python异步Web框架sanic的实现

    我们继续学习Python异步编程,这里将介绍异步Web框架sanic,为什么不是tornado?从框架的易用性来说,Flask要远远比tornado简单,可惜flask不支持异步,而sanic就是类似Flask语法的异步框架. github:https://github.com/huge-success/sanic 不过sanic对环境有要求: macOS/linux python 3.6+ 不过,我在macOS上安装 sanic 还是踩了坑.依赖库ujson一直安装失败.最后不得不卸载官方py

  • python 异步async库的使用说明

    在学习asyncio之前,先理清楚同步/异步的概念: 同步是指完成事务的逻辑,先执行第一个事务,如果阻塞了,会一直等待,直到这个事务完成,再执行第二个事务,顺序执行 异步是和同步相对的,异步是指在处理调用这个事务的之后,不会等待这个事务的处理结果,直接处理第二个事务去了,通过状态.通知.回调来通知调用者处理结果 asyncio函数: 异步IO采用消息循环的模式,重复"读取消息-处理消息"的过程,也就是说异步IO模型"需要一个消息循环,在消息循环中,主线程不断地重复"

  • Python异步爬虫实现原理与知识总结

    一.背景 默认情况下,用get请求时,会出现阻塞,需要很多时间来等待,对于有很多请求url时,速度就很慢.因为需要一个url请求的完成,才能让下一个url继续访问.一种很自然的想法就是用异步机制来提高爬虫速度.通过构建线程池或者进程池完成异步爬虫,即使用多线程或者多进程来处理多个请求(在别的进程或者线程阻塞时). import time #串形 def getPage(url): print("开始爬取网站",url) time.sleep(2)#阻塞 print("爬取完成

随机推荐