Python功能点实现:函数级/代码块级计时器

工程中我们常常需要对某一个函数或者一块代码计时,从而监测系统关键位置的性能。计时方法是在代码块前后分别记录当前系统时间,然后两者相减得到代码块的耗时。最简单原始的实现类似:

from datetime import datetime
start = datetime.now()
# some code you want to measure
end = datetime.now()
print("Processing time for {} is: {} seconds".format('You Name It', elapse))

这种方式缺点明显:假如系统内有很多地方都需要计时,那么每个地方都需要插入这样的计时代码,首先是重复性工作很麻烦,其次这样会降低代码的可读性,干扰对业务逻辑的理解。本文将给出一些更好的实现,主要涉及的技术是装饰器(Decorator)和运行时上下文(runtime context)。

基于装饰器的函数级计时器

第一种计时器是比较常见的函数级计时器,通过装饰器完成,将原函数改装成拥有计时功能的新函数,使其可以完成运行原来函数和计时两件事。在使用时,只用在需要计时功能的函数代码前加上类似@timer的语法糖,这样每次调用原函数时,运行的将会是新函数。这样就大大减少了重复性劳动。

具体实现如下:

from datetime import datetime
def timer(func):
  '''Function Level Timer via Decorator'''
  def timed(*args, **kwargs):
    start = datetime.now()
    result = func(*args, **kwargs)
    end = datetime.now()
    elapse = (end - start).total_seconds()
    print("Processing time for {} is: {} seconds".format(func.__name__, elapse))
    return result
  return timed
@timer
def test_1(a):
  '''Function Level'''
  a *= 2
  return a
if __name__ == '__main__':
  print(test_1(1))

基于上下文的代码块级计时器

装饰器实现的计时器可以为函数添加计时功能,可以满足大部分情况的需要,但是假如我们想要更灵活一些,对任意一段连续的代码块做计时,怎样做?使用原始的插计时代码的方法显然不是我们想要的;也可以将代码块重构成一个函数,再在上面加装饰器,然而这就显得不够优雅。因此我做出了下面的实现。

首先了解上下文管理的概念。大致是说Python中允许创建一种叫上下文管理器(Context Manager)的对象,它可以管理一个代码块执行时的上下文信息。具体的方法是创建一个类,并为其实现object.__enter__和object.__exit__方法,前者在进入代码块时自动执行,后者在完成代码块执行时自动执行。

在使用时,通过with和as关键字,将__enter__的返回值绑定到某一个变量名,这个返回值里可以储存代码块运行过程中得到的一些信息,在这里就是运行时间啦。具体的实现是创建一个计时器类Timer,在enter时记录代码块运行的开始时间,exit时记录完成时间、计算并储存耗时到Timer实例中。在使用时,将with Timer() as t加到要计时的代码块前面,t.elapse中将会储存代码块耗时,可以任意使用。

在这个基础上,我们还可以做出一个装饰器timer_来实现基于上下文的函数级计时器。

具体实现如下:

class Timer(object):
  '''Code Block Level Timer via Context'''
  def __enter__(self):
    self.start = datetime.now()
    return self
  def __exit__(self, *args):
    self.end = datetime.now()
    self.elapse = (self.end - self.start).total_seconds()
def timer_(func):
  '''Function Level Timer via Context & with Statement'''
  def timed(*args, **kw):
    with Timer() as t:
      result = func(*args, **kw)
    print("Processing time for {} is: {} seconds".format(func.__name__, t.elapse))
    return result
  return timed
def test_2(a):
  '''Code Block Level'''
  with Timer() as t:
    a *= 2
  print("Processing time for {} is: {} seconds".format('You Name It', t.elapse))
  return a
@timer_
def test_3(a):
  '''Function Level'''
  a *= 2
  return a
if __name__ == '__main__':
  print(test_2(2))
  print(test_3(3))

更灵活的实现

更优雅地,我们还可以使用contextlib自带的ContextDecorator,参考官方示例,做出既可以with又可以作为装饰器的计时器timer_elegant:

from datetime import datetime
from contextlib import ContextDecorator
class timer_elegant(ContextDecorator):
  '''Elegant Timer via ContextDecorator'''
  def __init__(self, name):
    self.name = name
  def __enter__(self):
    self.start = datetime.now()
  def __exit__(self, *args):
    self.end = datetime.now()
    self.elapse = (self.end - self.start).total_seconds()
    print("Processing time for {} is: {} seconds".format(self.name, self.elapse))
@timer_elegant('test_4')
def test_4(a):
  a *= 2
  return a
def test_5(a):
  a *= 2
  return a
if __name__ == '__main__':
  print(test_4(4))

  with timer_elegant('test 5'):
    result_5 = test_5(5)
  print(result_5)

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对我们的支持。如果你想了解更多相关内容请查看下面相关链接

时间: 2019-01-01

使用python 打开文件并做匹配处理的实例

如下所示: import os import re import string file = open("data2.txt") p1 = re.compile(r"^(\d{16})\s+(\d{3})") re.compile(p1) for line in file: print(line) match1 = re.search(p1,line) #print(match1.group(0)) sCard = match1.group(1) sValue=ma

Python lxml解析HTML并用xpath获取元素的方法

代码 使用方法见注释 #-*- coding: UTF-8 -*- from lxml import etree source = u''' <div><p class="p1" data-a="1">测试数据1</p> <p class="p1" data-a="2">测试数据2</p> <p class="p1" data-a="

Python装饰器语法糖

Python装饰器语法糖代码示例 ####装饰器的固定格式 ##普通版本 def timer(func): def inner(*args,**kwargs): '''执行函数之前要做的''' ret = func(*args,**kwargs) '''执行函数之后要做的''' return ret return inner ##wraps版本 from functools import wraps def deco(func): @wraps(func) #加在最内层函数正上方 def wra

使用python3实现操作串口详解

通过引用serial模块包,来操作串口. 1.查看串口名称 在Linux和Windows中,串口的名字规则不太一样. 需要事先查看. Linux下的查看串口命令 root@D2:~# ls -l /dev/ttyS* crw-rw---- 1 root dialout 4, 64 Dec 26 06:53 /dev/ttyS0 crw-rw---- 1 root dialout 4, 65 Dec 26 06:41 /dev/ttyS1 crw--w---- 1 root tty     4,

python之验证码生成(gvcode与captcha)

今天向大家总结一下python在做项目时用到的验证码生成工具:gvcode与captcha gvcode 全称:graphic-verification-code 安装: pip install gvcode 使用: import gvcode s, v = gvcode.generate() #序列解包 s.show() #显示生成的验证码图片 print(v) #打印验证码字符串 效果: captcha 安装: pip install captcha 使用: from captcha.ima

python生成器与迭代器详解

列表生成式: 例一: a = [i+1 for i in range(10)] print(a) 输出: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 例二: L = [1, 2, 3, 4, 5] print([i*i for i in L if i>3]) 输出: [16, 25] 例三: L = [1, 2, 3, 4, 5] I = [6, 7, 8, 9, 10] print([i*a for i in L for a in I if i > 2 if a <

详解如何在Apache中运行Python WSGI应用

在生产环境上,一般会使用比较健壮的Web服务器,如Apache来运行我们的应用.如果我们的Web应用是采用Python开发,而且符合WSGI规范,比如基于Django,Flask等框架,那如何将其部署在Apache中呢?本文中,我们就会介绍如何使用Apache模块mod_wsgi来运行Python WSGI应用. 安装mod_wsgi 我们假设你已经有了Apache和Python环境,在Linux或者Mac上,那第一步自然是安装.在Ubuntu或Debian环境中,你可以使用apt-get命令来

python 内置模块详解

一.random模块  随机     random()    随机小数            uninform(a,b) 随机小数 randint(a,b)  随机整数 choice() 随机选择一个 sample() 随机选择多个 shuffle() 打乱 import random from random import randint print(randint(10, 20)) # print(random.randint(10, 20))/ print(random.random())

对Python发送带header的http请求方法详解

简单的header import urllib2 request = urllib2.Request('http://example.com/') request.add_header('User-Agent', 'fake-client') response = urllib2.urlopen(request) print request.read() 包含较多元素的header import urllib,urllib2 url = 'http://example.com/' headers

python的xpath获取div标签内html内容,实现innerhtml功能的方法

python的xpath没有获取div标签内html内容的功能,也就是获取div或a标签中的innerhtml,写了个小程序实现一下: 源代码 [webadmin@centos7 csdnd4q] #162> vim /mywork/python/csdnd4q/z040.py #去掉最外层标签,保留其内的所有html标记和文本 def getinnerhtml(data): return data[data.find(">")+1:data.rfind("<

Python爬虫之用Xpath获取关键标签实现自动评论盖楼抽奖(二)

一.分析链接 上一篇文章指路 一般来说,我们参加某个网站的盖楼抽奖活动,并不是仅仅只参加一个,而是多个盖楼活动一起参加. 这个时候,我们就需要分析评论的链接是怎么区分不同帖子进行评论的,如上篇的刷帖链接,具体格式如下: https://club.hihonor.com/cn/forum.php?mod=post&action=reply&fid=154&tid=21089001&extra=page%3D1&replysubmit=yes&infloat=y

Python 获取div标签中的文字实例

预备知识点 compile 函数 compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用. 语法格式为: re.compile(pattern[, flags]) .compile(pattern[, flags]) 参数: pattern : 一个字符串形式的正则表达式 flags 可选,表示匹配模式,比如忽略大小写,多行模式等,具体参数为: re.I 忽略大小写 re.L 表示特殊字符集 \w, \W,

python使用xpath获取页面元素的使用

关于python 使用xpath获取网页信息的方法? 1.xpath的使用方法? ​ XPath 使用路径表达式来选取 XML 文档中的节点或节点集.节点是通过沿着路径 (path) 或者步 (steps) 来选取的. 常用路径表达式含义 表达式 描述 / 从根节点选取(取子节点) // 选择的当前节点选择文档中的节点 . 选取当前节点. - 选取当前节点的父节点. @ 选取属性 * 表示任意内容(通配符) | 运算符可以选取多个路径 常用功能函数 函数 用法 解释 startswith() x

JS 获取HTML标签内的子节点的方法

子节点的个数: document.getElementById("id").childNodes.length 注意: 标签开/闭合算2个节点 第几个子几点: document.getElementById("id").childNodes[n] 示例: 这里是 length-4 处,margin-left:20px 输出:length=8 实例: <div id="page_kx" style="text-align: cent

Selenium+BeautifulSoup+json获取Script标签内的json数据

Selenium爬虫遇到 数据是以 JSON 字符串的形式包裹在 Script 标签中, 假设Script标签下代码如下: <script id="DATA_INFO" type="application/json" > { "user": { "isLogin": true, "userInfo": { "id": 123456, "nickname":

用xpath获取指定标签下的所有text的实例

今天用xpath获取的元素下面text 是被几个b标签分割开的,我想要一次性全部获取,参考了其他人的博客是如下的做法: value_ls = html.xpath("//tr/td[7]") value = value_ls[0].xpath('string(.)').extract()[0] 但是因为我用的是 lxml, 系统报错,lxml元素没有extract() 这个方法,去掉这个方法后,可以正常使用.所以要根据自己的情况选择要不要用.extract() value_ls = h

对Xpath 获取子标签下所有文本的方法详解

在爬虫中遇见这种怎么办 想提取名称, 但是 名称不在一个标签里 使用xpath string()方法 例如 data.xpath("string(path)") path -- 你xpath提取的路径 这里提取到父标签 string() 方法会提取子标签多有的文本内容. 以上这篇对Xpath 获取子标签下所有文本的方法详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

javascript中获取元素标签中间的内容的实现方法

使用ajax,通过会把服务器端响应获取到reponseText或者reponseXML中的信息,以某种方法动态的写到div和span标记中,这样,可以在无刷新的情况下,改变页面内容的显示. 通过javascript进行动态的修改,修改的方法有两种: 1. 一种是使用html的每个标记的innerHTML属性,使用此属性,只要为它提供一个有意义的html代码片段,那么html解释器就可以将其中的内容进行解释,并显示在页面上,使用这种方式比较简单,每次修改前不需要先把原来的内容清除掉,而可以直接进行

python通过urllib2获取带有中文参数url内容的方法

本文实例讲述了python通过urllib2获取带有中文参数url内容的方法.分享给大家供大家参考.具体如下: 对于中文的参数如果不进行编码的话,python的urllib2直接处理会报错,我们可以先将中文转换成utf-8编码,然后使用urllib2.quote方法对参数进行url编码后传递. content = u'你好 jb51.net' content = content.encode('utf-8') content = urllib2.quote(content) api_url =