使用装饰器和调用次数查找任意函数的平均运行时间

时间:2017-11-18 21:08:51

标签: python decorator

创建一个以下列方式装饰另一个函数的函数:

@profile
def foo ( ... ) :
    ...

什么配置文件用于记录有关运行时的信息,以及使用时间模块的时钟功能对其装饰的函数的调用次数。例如:

from time import clock
start = clock()
    #do something for a while
duration = clock() - start

如果全局变量PROFILE_FUNCTIONS的值为True,则您的配置文件实现应仅记录函数的运行时。无论PROFILE_FUNCTIONS的值如何,您的装饰器都不应该更改它所装饰的函数的行为。也就是说,修饰函数应该接受相同数量和种类的参数,并输出相同的值,就好像它没有被装饰一样。你的装饰者也必须是通用的,即我应该能够用个人资料装饰任意函数。

将分析结果记录在全局字典PROFILE_RESULTS中。字典应该将配置文件的函数名称映射到元组:(a,b),其中a是对函数的所有调用的平均运行时间,b是调用函数的次数。

到目前为止,我有:

import time  
import operator                                        
PROFILE_RESULTS={}
funcs_ran=[]
func_runtimes=[]
func_occurences=[]

def profile(method):
    def wrapper(*args, **kw):
        startTime = clock()
        result = method(*args, **kw)
        endTime = clock()-start
        funcs_ran.append(method.__name__)
        func_runtimes.append(endTime - startTime)

@profile
def func1(sleep):
    time.sleep(sleep)

我称之为:

func1(0.5)
func1(1)
func1(2)

到目前为止,我有功能和运行时间,但我不确定如何继续

1 个答案:

答案 0 :(得分:1)

这是怎么做的。我摆脱了大多数全局变量并将左边的一个变成了字典。这使得更新它并快速且相当容易地检查成员资格。这包括取消PROFILE_RESULTS,因为我不确定您要将其放入其中。

请注意,您的装饰器功能编码错误 - 它从未返回装饰的函数/方法(它本身需要返回调用原始函数的结果)。

import time

func_runtimes = {}

def profile(method):
    """ Profiling decorator. """
    def wrapper(*args, **kw):
        start_time = time.clock()

        result = method(*args, **kw)

        elapsed_time = time.clock() - start_time
        func_runtimes.setdefault(method.__name__, []).append(elapsed_time)
        return result
    return wrapper  # Decorated method (need to return this).

def print_stats(method_name):
    if method_name not in func_runtimes:
        print("{!r} wasn't profiled, nothing to display.".format(method_name))
    else:
        runtimes = func_runtimes[method_name]
        total_runtime = sum(runtimes)
        average = total_runtime / len(runtimes)
        print('Stats for method: {!r}'.format(method_name))
        print('  run times: {}'.format(runtimes))
        print('  total run time: {}'.format(total_runtime))
        print('  average run time: {}'.format(average))

@profile
def func1(sleep):
    time.sleep(sleep)

func1(0.5)
func1(1)
func1(2)

print('func_runtimes:', func_runtimes)
print()
print_stats('func1')

输出:

func_runtimes: {'func1': [0.4996212506738944, 1.0000399133651898, 2.0000319306921517]}

Stats for method: 'func1'
  run times: [0.4996212506738944, 1.0000399133651898, 2.0000319306921517]
  total run time: 3.499693094731236
  average run time: 1.166564364910412