侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

python自定义时钟类、定时任务类

Python  /  管理员 发布于 7年前   173

这是我使用python写的第一个类(也算是学习面向对象语言以来正式写的第一个解耦的类),记录下改进的过程。

分析需求

最初,因为使用time模块显示日期时,每次都要设置时间字符串的格式,挺麻烦,但还是忍了。
后来,在处理多线程任务时需要实现定时控制的功能,更麻烦,终于决定自己做一个解决这些问题的通用代码(虽然网上有现成的模块,但亲手编写这部分代码正好能锻炼一下我的面向对象编程)。

分析框架

刚开始,我计划做一个模仿时钟的抽象类,让它独立运行在一个线程中,让它提供显示日期、计时、设置定时任务的方法……然而由于缺乏规划,编程乱糟糟的,这些方法的代码和变量交杂在一起,难以入目,更难以扩展……气得重构代码,这次把显示日期、计时、设置定时任务三大功能分别抽象成三个类,相互解耦,各自独立运行,代码变得简洁多了。
ok,旧代码就藏在git的历史记录里吧,这里贴出重构后的代码。

显示时间的类

import timeimport threadingclass _Clock:  """  自定义的时钟类,用于获取几种不同格式的当前时间。   decimal : 设置time_float的精度,控制其保留几位小数。   time_diff : 设置该时钟与UTC+0时区的时差。如果不设置,会自动采用   本地时区。  """  def __init__(self, name=None, decimal=3, time_diff=None):    self.name = name    self.decimal = decimal    self.time_diff = time_diff    self.time_format = "%Y/%m/%d %H:%M:%S" # 时间字符串的格式  @property  def time_float(self):    """ UTC+0时区的时间戳,精度由self.decimal决定 """    return round(time.time(), self.decimal)  @property  def time_int(self):    """ UTC+0时区的时间戳,精度为秒 """    return int(time.time())  @property  def time_tuple(self):    """ 本地时区的时间元组 """    if self.time_diff == None:      return time.localtime(self.time_int)    else:      return time.gmtime(self.time_int+self.time_diff)  @property  def time_str(self):    """ 本地时间的格式化字符串 """    return time.strftime(self.time_format, self.time_tuple)

秒表计时的类

class Timer(_Clock):  """  自定义的计时器,像秒表一样,可以随时查看当前计时、暂停计时、继续计时。   ・ 创建一个计时器之后,它就会开始计时。   ・ 默认使用time.time()获取时间,精度为毫秒。   ・ 可以直接调用_Clock类的方法来获取当前时间。  """  def __init__(self, *args, **kwargs):    _Clock.__init__(self, *args, **kwargs)    self.record = [] # 记录每次使用的 (开始时刻,暂停时刻,计时时长)    self.status = "initial"    self.go()  @property  def count(self):    """ 当前计时值 """    count = 0    for line in self.record:      if line[2] == None:        count += self.time_float - line[0]      else:        count += line[2]    return round(count, self.decimal)  def go(self):    """ 开始计时 """    if self.status != "timing":      self.record.append((self.time_float, None, None))      self.status = "timing"  def pause(self):    """ 暂停计时 """    # 如果该计时器在计时中,就暂停它,并计算这一段的计时时长    if self.status == "timing":      last_line = self.record[-1]      self.record.remove(last_line)      current_time = self.time_float      self.record.append(        (last_line[0], current_time, round(current_time - last_line[0], self.decimal)))      self.status = "paused"

定时任务的类

class Schedule(threading.Thread):  """  自定义的定时任务表,添加第一个定时任务后就创建一个线程,开始循环检查  是否执行任务表中的任务。   ・ 调用stop()来终止该线程。  """  def __init__(self, *args, **kwargs):    threading.Thread.__init__(self, *args, **kwargs)    self._askToStop = False    self._schedule = [] # 保存定时任务表    self.status = "initial"  def _get_time(self):    """ 获取当前时间 """    return time.time()  def addTask(self, countDown, func, *args, **kwargs):    """     在任务表中增加一项定时任务:在倒计时countDown结束之后调用    函数func,并传入参数*args和**kwargs。     ・ 定时任务只会被执行一次,执行后就会被从任务表中删除。     ・ 定时任务只会在倒计时结束之后被执行,但无法保证无延迟。    """    if self.status == "initial": # 第一次添加定时任务时创建一个新线程      self.status = "running"      self.start()    task = []    if isinstance(countDown, (int, float)) and countDown > 0:      task.append(self._get_time()+countDown) # 准备在指定时刻执行该任务    else:      raise ValueError("'countDown' must be a positive int or float.")    if callable(func):      task.append(func)    else:      raise ValueError("'func' must be callable.")    task.append(args) # 保存元组参数    task.append(kwargs) # 保存字典参数    self._schedule.append(task)    self._schedule.sort(key=lambda task: task[0]) # 将任务表按时间戳的大小排序  def _doTask(self):    """ 检查任务表中各项任务的时间,判断是否要执行它。 """    current_time = self._get_time()    i = 0    while i < len(self._schedule): # 遍历任务表      task = self._schedule[i]      if task[0] <= current_time:        # 如果该任务的时间不晚于当前时间,就创建一个线程去执行该任务,避免阻塞定时器线程        t1 = CreatThread(task[1], *task[2], **task[3])        t1.start()        i += 1      else:        break # 如果该任务的时间戳大于当前时间,就提前结束遍历    del self._schedule[:i] # 删除过时的任务  def run(self):    """ 线程循环运行的内容 """    while not self._askToStop:      self._doTask()    # 结束时进行清理    self.status == "stopped"    return 0  def stop(self):    self._askToStop = Trueclass CreatThread(threading.Thread):  """ 一个简单的创建线程的类 """  def __init__(self, func, *args, **kwargs):    threading.Thread.__init__(self)    self.func = func    self.args = args    self.kwargs = kwargs  def run(self):    self.func(*self.args, **self.kwargs)

源代码:use_time.py

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


  • 上一条:
    Python Django 实现简单注册功能过程详解
    下一条:
    python Pandas如何对数据集随机抽样
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 智能合约Solidity学习CryptoZombie第四课:僵尸作战系统(0个评论)
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客