python实现高性能定时器--时间轮和最小堆

python实现高性能定时器–时间轮和最小堆
定时器的使用场景:
1,批量任务处理,任务都带有超时控制;
2,监控场景,批量添加的监控指标,不可能每个任务都开个定时器处理。

常用高性能方式有三种, 时间轮(参见沈剑文章),最小堆方式和timefd的方式,前两者基于数据结构实现,最后一种通过 epoll 提供的封装实现。本文仅实现时间轮和最小堆的 python 封装。

时间轮原理,一个环形队列,每个元素一个槽位,每个槽位关联一个任务列表,整个系统只需要一个定时器,每隔一定时间跳一格。

实现细节,第一,一个时间槽初始化后大小固定,槽的实现可以通过数组或者说链表。python中可以用list 简单实现。第二,插入元素要通过 任务key 找到槽,所以得维护个dict 来增删改任务。第三,能通过槽找到每个槽对应的任务,这通过dict实现。整体发现,这里因为会维护两个映射,会比较占用内存。

具体封装如下:



最小堆原理:维护一个最小堆,堆的元素是时间和任务,定时器隔一定时间间隔从堆中取任务,对比时间戳不超时为止,每取出任务会有个调整堆的过程,所以时间复杂度是lgn 。
https://my.oschina.net/u/2950272/blog/1547216

监控场景

批量任务

参考书籍

真实世界的Python仪器监控:数据采集与控制系统自动化(硬件DIY 不可多得的实战指南)
理解如何定义应用的范围、确定必要的算法,以及二者的重要性
学习如何使用工业标准接口,如RS-232、RS-485和GPIB
用C语言创建底层扩展模块,以利用Python接入各种硬件和测试仪器
探索终端、curses、Tkinter,以及wxPython的图形和基于文本的用户界面
使用开源软件工具和库来降低成本,避免从头开始实现功能

相关推荐: 《Python基础教程:第2版》 《Python核心编程(中文 第二版)》

      《Python科学计算》 《Head First Python(中文版)》 

      《Python学习手册:第4版》

《真实世界的Python仪器监控:数据采集与控制系统自动化》主要探讨如何运用Python 快速构建自动化仪器控制系统,帮助读者了解如何通过自行开发应用程序来监视或者控制仪器硬件。本书内容涵盖了从接线到建立接口,直到完成可用软件的整个过程。
《真实世界的Python仪器监控:数据采集与控制系统自动化》适合需要进行仪表控制、机器人、数据采集、过程控制等相关工作的读者阅读参考。

J.M.Hughes是一位拥有超过30年工作经验的嵌入式系统工程师,工作领域涉及电气、嵌入式系统和软件、航空航天系统,以及科学应用编程。他曾经负责设计凤凰号火星着陆器的表面成像软件,商用和军用飞机的数字引擎控制,自动测试系统,射电望远镜的数据采集和实时控制等工作。Huzhes已在各种应用中使用Python很多年了,包括詹姆斯·韦伯太空望远镜中的多波长激光干涉仪系统的对准检验软件。目前,他正在亚利桑那大学,在成像系统的仿真和分析方面继续使用Python。

《真实世界的Python仪器监控:数据采集与控制系统自动化》
第1 章 仪器学概论 1
数据采集 2
控制输出 4
开环控制 5
闭环控制 6
顺序控制 8
应用概观 9
电子测试仪器 9
实验室仪器 11
过程控制 12
小结 14
第2 章 基本电子学 15
电荷 15
电流 17
基础电路理论.18
电路原理图 20
直流电路特性.23
欧姆定律 24
电流吸入与电流输出 26
再谈电阻 27
交流电路 28
正弦波 29
电容器 30
电感器 34
其他波形:方波、斜波、三角波和脉冲 37
接口 38
离散数字I/O 38
模拟I/O 42
计数器与定时器 46
脉宽调制 48
串行I/O 49
并行I/O 51
小结 53
推荐阅读 54
第3 章 Python 编程语言 55
安装Python 56
Python 编程 57
Python 的命令行 57
命令行参数和环境 .58
Python 中的对象 59
Python 中的数据类型 60
表达式 73
操作符 73
语句 79
字串 86
程序组织 91
模块导入 101
加载并运行Python 程序 104
基础输入输出 106
提示和技巧 110
Python 开发工具 112
编辑器和IDE 112
调试器 115
小结 115
推荐阅读 115
第4 章 C 语言编程 117
安装C 语言编程环境 117
使用C 语言开发软件 118
一个简单的C 程序 119
预处理指令 122
标准数据类型 126
用户定义类型 127
操作符 127
表达式 136
语句 136
数组和指针 143
结构 146
函式 150
标准库 151
编译C 程序 152
C 语言综述 156
C 开发工具 156
小结 157
推荐阅读 157
第5 章 Python 扩展 159
用C 建立Python 扩展 160
Python 的C 扩展API 161
扩展代码的模块组织 161
Python API 类型和函数 163
方法表 163
方法标记 164
传递数据 165
使用Python 的C 扩展API 167
通用离散I/O API 167
通用包装器示例 169
调用扩展 173
Python 的ctypes 外部函数库 177
用ctypes 载入外部DLL 177
ctypes 中的基本数据类型 178
使用ctypes 179
小结 179
推荐阅读 180
第6 章 硬件:工具与耗材 181
必备工具 181
手工工具 182
数字万用表 184
焊接工具 187
最好能有的工具 189
高级工具 190
示波器 190
逻辑分析仪 192
测试设备注意事项 194
耗材 194
全新和二手 195
小结 196
推荐阅读 196
第7 章 物理接口 197
连接器 197
DB 型连接器 198
USB 连接器 201
圆形连接器 202
接线端子 203
接线 205
连接器失效 207
串行接口 208
RS-232/EIA-232 209
RS-485/EIA-485 215
USB 220
Windows 虚拟串口 224
GPIB/IEEE-488 226
GPIB/IEEE-488 信号 226
GPIB 连接 228
GPIB 转接USB 229
PC 总线接口设备 230
基于总线接口的优缺点 230
数据采集卡 232
GPIB 接口卡 232
旧并不代表差 233
小结 234
推荐阅读 234
第8 章 开始干吧 235
项目定义 236
需求驱动的设计 236
从需求开始 237
工程目标 238
需求 239
为什么需要需求 240
良好的需求 241
全景 242
需求类型 242
用例 244
可追溯性 246
需求捕获 248
设计软件 248
软件设计说明 249
SDD 的图景 249
伪代码 253
分而治之 253
处理错误和故障 255
功能测试 256
为需求而测 257
测试用例 257
测试错误处理 260
回归测试 261
进展追踪 261
实施 262
代码风格 262
组织你的代码 264
代码复查 265
单元测试 268
连接到硬件 277
软件文档化 278
版本控制 281
缺陷跟踪 281
用户文档 282
小结 283
推荐阅读 283
第9 章 控制系统概念 285
基础控制系统理论 286
线性控制系统 286
非线性控制系统 288
顺序控制系统 289
术语和符号 290
控制系统框图 292
传递函数 293
时间和频率 293
控制系统类型 298
开环控制 299
闭环控制 299
非线性控制:继电器控制器 306
顺序控制系统 308
比例、比例积分、比例积分微分控制 312
混合控制系统 317
用Python 实现控制系统 318
线性比例控制器 318
开关式控制器 319
简单PID 控制器 320
小结 324
推荐阅读 324
第10 章 构建并使用仿真器 327
什么是仿真 328
低保真和高保真 329
模拟错误和故障 330
使用Python 创建一个仿真器 333
程序包和模块的组织 334
数据输入/ 输出仿真器 334
交流电源控制器仿真 349
串行终端仿真器 358
使用终端仿真器脚本 359
显示仿真数据 361
gnuplot 361
使用gnuplot 363
使用gnuplot 将仿真器数据图表化 366
创建你自己的仿真器 369
确认仿真器的必要性 369
仿真的范围 370
时间和精力 371
小结 371
推荐阅读 371
第11 章 仪器数据I/O 373
数据I/O :接口软件 373
接口格式与协议 374
Python 接口支持的工具包 383
Windows 平台上的替代品 389
在Linux 下使用基于总线的硬件I/O 设备 389
数据I/O :数据采集与写入 391
基本数据I/O 391
阻塞和非阻塞调用 398
数据I/O 方法 399
数据I/O 错误处理 402
处理不一致的数据 407
小结 411
推荐阅读 412
第12 章 读写数据文件 413
ASCII 数据文件 414
原始的ASCII 字符集 414
Python 的ASCII 字符操作方法 416
读写ASCII 平面文件 418
配置数据 425
AutoConvert.py 模块——自动转换字符串 427
FileUtils.py 模块——ASCII 数据文件I/O 工具 430
二进制数据文件 440
平面二进制数据文件 440
用Python 处理二进制数据 442
图像数据 453
小结 462
推荐阅读 462
第13 章 用户界面 465
文本界面 465
控制台 465
ANSI 显示控制台技术 478
Python 和curses 494
用不用curse 是个问题吗 502
图形用户界面 502
图形用户界面的历史和概念 503
在Python 中使用GUI 504
TkInter 508
wxPython 514
小结 522
推荐阅读 523
第14 章 实例 525
串行接口 525
简易DMM 数据获取 526
串行接口的离散或模拟数据I/O 设备 531
串行接口及对速度的考虑 535
USB 实例:LabJack U3 536
LabJack 连接 537
安装LabJack 设备 538
LabJack 与Python 539
小结 546
推荐阅读 547
附录A 自由和开源软件资源 549
附录B 仪器资源 553
索引 557

↑折 叠
译者序
  本书是“侠少”(张春雨编辑)推荐给我翻译的。只是因为之前组织过几本Python 相关技术图书的翻译工程,就成为所谓资深人士,进而被编辑盯上了。可是拿到书一看,不是单纯讲Python 开发技巧,而是如同TBBT(《生活大爆炸》)片头曲背景MV 那般,内容包罗万象:从电子到仪表到线缆再到高端的软件工程都有所包含,内容的推进也是高速但清晰的,而且完全是根据学习的自然路径组织的,一步一步,从简入繁,自然而然,明明白白,很有Pythonic 的感觉!所以,俺就无耻地心动了。再说,华蠎用户组(CPyUG)订阅人数近一万,其中肯定有软硬兼修的高人,俺只要作好大妈的本职工作,就可以向中国Python 社区贡献第一本硬件相关的好书了!于是,革命的乐观主义精神主导了俺的情绪。终于,在2011 年春节前,俺接下了本书的翻译组织任务!
  最终图书署名为OBP Group(开放图书工作组),原因有三:
  本书的翻译出版过程沿用了OBP(Open Book Project,y 开放图书计划)的协同流程;
  大家的主要协同场景是在Google Group(邮件列表)中;
  工作组专门为本书成立,翻译完成后就地解散,转为通过Group 的形式存在,继续支持图书内容的讨论。
  其中OBP 的工作流程细节请参考:
  http://code.google.com/p/openbookproject/wiki/HowToBuildBookOnline
  目前,OBP 是作为一种开放的分布式协作流程而存在的。
  任何人都可以使用OBP 实践检验过的在线分布式团队的组织形式来完成任意作品。
  其实就是将软件工程管理的思想及工具,组合应用在图书创译方面而已。
  相比其他翻译团队,特殊在协同的工具链。
  1. 在Bitbucket.org 上使用Mercurial 分布式仓库,或是在Github/Gitcafe 中使用分布
  式仓库。
  2. 基于Sphinx 来组织新结构化文本(rST)。
  3. 通过readthedocs.org 随时编译为html 格式的图书式网站。
  果然,通过邮件列表,快速报名上来十多位有意向的译者。根据以往经验,三个和尚没水吃,人多时,大家都以为有人在翻译,自个儿就不动手了。于是,以C 语言/Python语言/ 硬件进行领域划分,俺单独负责所有Python 及软件工程相关的内容,另外邀请四位译者分别承担其他两部分内容,再加上责任编辑,实际上形成了一个有专项目标的迷你社区。
  那么什么是社区呢?
  简单的说就是相对固定的成员在相对固定的场所对固定的目标进行固定的行动。所以,技术图书的翻译团队,如果是分布式的,其实就形成了一个确切的社区。只是,一般OBP 专项社区随着图书的出版会快速转入静默,不是图书内容没有值得持续讨论的地方,而是大家不愿意回忆那些熬夜翻译赶进度的苦吧。
  本书的专门列表也已经建立:[email protected],欢迎大家订阅和加入讨论。
  虽然原书有600 多页,翻译为中文,也就500 页的样子,其中还包含大段的代码,平均到每个人也就100 多页,几万字而已。相比动辄几百万字的网络小说来,大家的工作量不算大。但是,技术文字的翻译,不是口水化的玄幻小说,至少要做到:
↓展开全部内容
前言
  本书介绍自动化仪器及其自动化控制。我们将探讨如何运用Python 语言快速轻巧地构建自动化仪器的控制系统。
  从研究实验室到工业厂房,自动化仪器无所不在。一旦人们意识到收集随时间变迁的数据很有用,自然就需要某种手段来捕捉并完成数据记录。当然,人们可以取叠纸拿个时钟,盯着温度计、刻度盘或是其他仪表,定期记录数值,但是很快就会受不了这种乏味的工作。如果这一记录过程可以自动化,无疑将更加可靠和易行。幸运的是,技术的进步早已超越了手写日志及发条驱动的带状图记录的时代!
  如今,人们可以购买各种便宜的物理仪器并使用计算机来获取数据。一旦计算机被连接到仪器,数据收集、分析和控制等等功能就可以自由扩展,唯一受限的只是实现者自身的创造力了。
  本书的主要目的是向读者展示如何创建一个有能力同用户友好交互的仪器或控制应用程序软件,并使用最低成本运行起来。为此,我们仅基于最必需的步骤来创建程序,包括怎么使用不同类型的输入/ 输出硬件接入现实世界的底层接口。我们也将研究一些行之有效的方法,用以指导创建强大且可靠的程序。特别提醒,应该为数据处理所必需的算法支付设计费用。最终,我们将体验如何为用户设计命令的输入以及结果展示。如果读者能从本书中发现一些想法,并创造性地运用在各种仪器设备上,满足自己的需要,那么我的愿望也就达成了,善哉。
  
  本书的目标读者
  本书专为需要或是自制仪器控制器(也称为数据采集和控制系统)的人准备的。你可能是名研究员、软件开发者、学生、项目主管、工程师,或一个业余爱好者。想实现的应用系统,可能只是在实验过程中需要的自动化电子测试系统,或是其他类型的自动化设备。
  本书要完成的目标软件将是跨平台的。我假定你至少在Windows 平台特别是XP 平台玩得很顺。而我会使用Ubuntu 发行版本的Linux 系统,不过书中讨论的程序将在各种兼容发行版中良好运行,同时我也假定你知道如何使用csh 或是bash 命令行脚本。
  由于本书是关于如何通过物理硬件同现实世界交互的,其中自然涉及了一系列相关电气产品。但是,并不要求读者是名有足够背景知识的电气工程师。在第2 章,包含了基本电子理论知识的介绍,虽然事实上不必理解深层次的电子学知识也可以令计算机与现实世界交互,不过,知道多点相关领域知识绝对没坏处,万一首次遇到意外,我们可以从中获得思路。
  不论读者的工作类型或场所怎样,最关键的,我假定你需要通过某些硬件接口捕获一些数据,或是产生控制信号。更加重要的是,需要轻便又精确且可靠地构建出这些仪器的控制软件来。
  
  本书所用编程语言
  我们将使用Python 作为主要的编程语言,仅仅嵌入一点点的C 程序。在本书中,我将假定你有一些编程经验,并对Python 或C(理想情况下,两者都)熟悉。如果不是这样,有Perl 或Tcl/Tk 或如Matlab 或IDL 分析工具的经验,也是一个合理的起点。
  本书坚定地回避Python 语言更深奥的知识,配合大量的实例代码、图表注释和截屏来引导理解。对C 涉及得很少,只用来说明如何创建和使用Python 应用的底层系统扩展。第3 章覆盖了Python 语言的基础介绍,第4 章介绍了C 语言的基础知识,对以上语言进一步的探究可通过阅读建议自行学习。
  
  为什么选用Python
  Python 是Guido van Rossum 在80 年代末开发的解释型语言。因其是种即时编译的脚本语言,故而用户可以在Python 命令行环境中直接创建并执行。语言本身很容易学习和理解,只要一开始别理会过多的高级功能(装饰器,自省,列表推导,等等)就行。因此,Python 提供了快速构建原型及易懂的双重好处,这反过来又有利于快速为不同的设备创建各种不同应用,没有开发者通常需要应对的学习曲线以及传统的编译语言依赖的特定供应商提供的编程环境。
  Python 是高度可移植的,几乎运行在所有现代计算平台中。在项目中坚持只使用常用的接口方法,应用程序就很可能在安装Windows 的PC 中编写, 但是不用修改一行代码也可以在Linux 操作系统中运行良好。甚至于可以在Sun 的Solaris 机器和Apple 的OS X系统中运行,即使书中没有特意提及这一点。一旦Python 必须配合特定平台的特定扩展或驱动程序,便失去了可移植性,所以在这些情况下,我将提供分别适用于Windows 和Linux 的替代品。
  本书包括了完整的可用示例代码,并配合框图和流程图来说明关键点,操作一些现成的、低成本的接口硬件。
 “O’Reilly Radar 博客有口皆碑。”
  ——Wired
  “O’Reilly 凭借一系列(真希望当初我也想到了)非凡想法建立了数百万美元的业
  务。”
  ——Business 2.0
  “O’Reilly Conference 是聚集关键思想领袖的绝对典范。”
  ——CRN
  “一本O’Reilly 的书就代表一个有用、有前途、需要学习的主题。”
  ——Irish Times
  “Tim 是位特立独行的商人,他不光放眼于最长远、最广阔的视野并且切实地按照Yogi Berra 的建议去做了:‘如果你在路上遇到岔路口,走小路(岔路)。’回顾过去Tim 似乎每一次都选择了小路,而且有几次都是一闪即逝的机会,尽管大路也不错。”
  ——Linux Journal

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的Timer:

threading模块中的Timer能够帮助实现定时任务,而且是非阻塞的。

比如3秒后打印helloworld:

def printHello():
  print "hello world" 

Timer(3, printHello).start() 
比如每3秒打印一次helloworld:

def printHello():
  print "Hello World"
  t = Timer(2, printHello)
  t.start() 

if __name__ == "__main__":
  printHello() 
使用sched模块:

sched是一种调度(延时处理机制)。

# -*- coding:utf-8 -*-
# use sched to timing
import time
import os
import sched 

# 初始化sched模块的scheduler类
# 第一个参数是一个可以返回时间戳的函数,第二个参数可以在定时未到达之前阻塞。
schedule = sched.scheduler(time.time, time.sleep) 

# 被周期性调度触发的函数
def execute_command(cmd, inc):
  '''''
  终端上显示当前计算机的连接情况
  '''
  os.system(cmd)
  schedule.enter(inc, 0, execute_command, (cmd, inc)) 

def main(cmd, inc=60):
  # enter四个参数分别为:间隔事件、优先级(用于同时间到达的两个事件同时执行时定序)、被调用触发的函数,
  # 给该触发函数的参数(tuple形式)
  schedule.enter(0, 0, execute_command, (cmd, inc))
  schedule.run() 

# 每60秒查看下网络连接情况
if __name__ == '__main__':
  main("netstat -an", 60) 
使用定时框架APScheduler:

APScheduler是基于Quartz的一个Python定时任务框架。提供了基于日期、固定时间间隔以及crontab类型的任务,并且可以持久化任务。

这个现在还没自己尝试过,等过段时间用了再来补充。

使用windows的定时任务:

这里可以将所需要的Python程序打包成exe文件,然后在windows下设置定时执行。

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

时间: 2017-02-07

你可能感兴趣的:(python)