美文网首页
[python] 统计函数运行时间

[python] 统计函数运行时间

作者: Silver_42ac | 来源:发表于2020-07-06 11:01 被阅读0次

第一种:

import time
def time_me(fn):  #fn 是要修饰/修改 的函数
    def _wrapper(*args, **kwargs): #这个   _wrapper(*args, **kwargs) 则代指fn, *args 代表一般变量参数, **kwargs代表 字典,哈希等参数
        start = time.perf_counter()
        fn(*args, **kwargs)
        print ("%s cost %s second"%(fn.__name__, time.perf_counter() - start))
    return _wrapper
#这个装饰器可以在方便地统计函数运行的耗时。
#用来分析脚本的性能是最好不过了。
#这样用:
@time_me()       这里 没有指定
def test(x, y):
    time.sleep(0.1)
@time_me()
def test2(x):
    time.sleep(0.2)
test(1, 2)
test2(2)

第二种:

import time
import functools
def time_me(info="used"):
    def _time_me(fn):
        @functools.wraps(fn)    #转化为输入函数
        def _wrapper(*args, **kwargs):  #*args, **kwargs 代指所有 输入函数的参数
            start = time.perf_counter()
            fn(*args, **kwargs)        
            print("%s %s %s"%(fn.__name__, info, time.perf_counter() - start), "second")
        return _wrapper
    return _time_me

#应用
@time_me()  #添加修饰器,就是函数嵌套了函数,中间加了一些功能和执行内容,而不需要 修改 test() 函数的内容
def test(x, y):
    time.sleep(0.1)

@time_me("cost") #添加修饰器
def test2(x):
    time.sleep(0.2)
test(1, 2)
test2(2)

结果参考这里:
https://glot.io/snippets/fp0zevptef

image.png

第三种改进版:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import division
from __future__ import unicode_literals
import sys,time,datetime,functools

#info
__author__ = ''
__email__ = 'xxx@xxx.com'
__version__ = '0.0.1'
__status__ = 'Dev'

def time_me(info="used"):
    def _time_me(fn):
        @functools.wraps(fn)    #转化为输入函数
        def _wrapper(*args, **kwargs):  #*args, **kwargs 代指所有 输入函数的参数
            if sys.version[0]=="3":
                start = time.perf_counter()
            else:
                start = time.clock()
            fn(*args, **kwargs)      
            if sys.version[0]=="3":
                end = time.perf_counter()
            else:
                end = time.clock()
            print("%s %s %s"%(fn.__name__, info, str(datetime.timedelta(seconds = end - start))))
        return _wrapper
    return _time_me

#应用
@time_me()  #添加修饰器,就是函数嵌套了函数,中间加了一些功能和执行内容,而不需要 修改 test() 函数的内容
def test(x, y):
    time.sleep(0.3)

@time_me("cost") #添加修饰器,给个参数cost
def test2(x):
    time.sleep(0.4)
test(1, 2)
test2(2)

输出为:


image.png

第四种 在实际应用时 发现会报错

TypeError: cannot unpack non-iterable NoneType object

自己用在某个函数上,这个函数输入和返回都不止 一个参数

@time_me()
def bam2fa(bam,lst,fz=1000,rz=100,pb=0.66,if="ins",if2="hr",sf=False):
     pass
     return list, dict, list

查询后发现 原因是:

TypeError: cannot unpack non-iterable NoneType object
报错的原因是函数返回值得数量不一致,查看函数返回值数量和调用函数时接收返回值的数量是不是一致,修改一致即可

发觉是是自己对装饰器理解不到位,逐
参考了这里,发现 之前的例子里少了 return func(*args, **kwargs) 返回这个原始函数func
Python 函数装饰器

image.png

看完了这篇才明白
如何理解Python装饰器?
如下图中
fn(*args, **kwargs) 放在了 获取时间的中间,但是我的函数是有返回值的

image.png

完善版本(支持具有返回值的函数)


8881910.png
'''
import sys,time,datetime,functools,logging
#logging 用于输出日志
def main():
    #logging 设置
    LOG_FORMAT = "%(asctime)s %(name)s %(levelname)s %(pathname)s %(message)s "#配置输出日志格式
    DATE_FORMAT = '%Y-%m-%d  %H:%M:%S' #配置输出时间的格式,注意月份和天数不要搞乱了
    logging.basicConfig(level=logging.DEBUG,format=LOG_FORMAT,datefmt = DATE_FORMAT,filename=r"logging.log" )
'''
def time_me(info="used"):
    def _time_me(func):
        if sys.version[0]=="3":  #获得python版本号,截取第一个字符,2.7就是2 ,3.8就是3
            start = time.perf_counter() #python3 中使用perf_counter() 
        else:
            start = time.clock()              #python2 中使用clock()  
        @functools.wraps(func)    #效果是保持当前装饰器去装饰的函数的 __name__ 的值不变;
#函数的函数名即 __name__默认被装饰器改变为_wrapper,但是当存在多个修饰器时,重名会发生错误,
        def _wrapper(*args, **kwargs):  #*args, **kwargs 代指所有 输入函数的参数    
            return func(*args, **kwargs)  #这里等于执行了一次这个函数
        if sys.version[0]=="3":    #获得python版本号,截取第一个字符,2.7就是2 ,3.8就是3
            end = time.perf_counter()
        else:
            end = time.clock()  
       #logging.info("%s %s %s\n"%(func.__name__, info, str(datetime.timedelta(seconds = end - start))))  #这里可以替换 logging 日志,func.__name__ 是该函数的名字,也可以自己在函数中设置 __name__="xxx"
        print("%s %s %s"%(fn.__name__, info, str(datetime.timedelta(seconds = end - start))))
        return _wrapper
    return _time_me

*args, **kwargs

args表示任何多个无名参数,它是一个tuple;kwargs表示关键字参数,它是一个dict。并且同时使用args和kwargs时,必须args参数列要在*kwargs前,像foo(a=1, b='2', c=3, a', 1, None, )这样调用的话,会提示语法错误“SyntaxError: non-keyword arg after keyword arg”。
获得的启示:编写函数时,参数中字典类型的放在后面 func() 的后面 ,如 func( arg,tuple,list,dict)

参考:
Python 函数装饰器
python装饰器中functools.wraps的作用详解
Python中统计函数运行耗时的方法
Python time.clock在Python3.3废弃,在Python3.8中将被移除
python functools模块
关于python中time模块的time.process 和 time.perf_count的关系
python装饰器中functools.wraps的作用详解
Python-如何将秒转换为小时,分钟和秒?
How do I convert seconds to hours, minutes and seconds?
*args, **kwargs

相关文章

网友评论

      本文标题:[python] 统计函数运行时间

      本文链接:https://www.haomeiwen.com/subject/hnhwqktx.html