获取在python 2.7中执行代码块的时间


78

我想测量在Python程序中评估一块代码所花费的时间,可能在用户cpu时间,系统cpu时间和经过时间之间进行区分。

我知道该timeit模块,但是我有许多自写函数,在设置过程中传递它们并不是很容易。

我宁愿有一些可以使用的东西:

#up to here I have done something....
start_counting() #or whatever command used to mark that I want to measure
                   #the time elapsed in the next rows
# code I want to evaluate
user,system,elapsed = stop_counting() #or whatever command says:
                                      #stop the timer and return the times

用户和系统的CPU时间不是必需的(尽管我想测量它们),但是对于过去的时间,我希望能够执行类似的操作,而不是使用复杂的命令或模块。

Answers:


164

要获取以秒为单位的经过时间,可以使用timeit.default_timer()

import timeit
start_time = timeit.default_timer()
# code you want to evaluate
elapsed = timeit.default_timer() - start_time

timeit.default_timer()使用代替time.time()time.clock()因为它将为所有平台选择具有更高分辨率的计时功能。


4
我已经读到,对于只需要几分之一秒运行时间的代码块,这并不是最佳方法。我也认为使用time模块的.clock()方法是首选?stackoverflow.com/questions/85451/…–
lucacerone

4
改变了我的答案使用timeit.default_timer(),这将选择之间time.time()time.clock()取决于其中有您所使用的平台上更高的分辨率。
Andrew Clark

24

我总是使用装饰器为现有功能做一些额外的工作,包括获取执行时间。这是pythonic且简单。

import time

def time_usage(func):
    def wrapper(*args, **kwargs):
        beg_ts = time.time()
        retval = func(*args, **kwargs)
        end_ts = time.time()
        print("elapsed time: %f" % (end_ts - beg_ts))
        return retval
    return wrapper

@time_usage
def test():
    for i in xrange(0, 10000):
        pass

if __name__ == "__main__":
    test()

3
抱歉,我仍然不知道如何使用装饰器:(
lucacerone 2013年

4
@LucaCerone关于装饰stackoverflow.com/questions/739654/…有一个很好的解释。尝试耐心阅读,您将了解装饰器。
Yarkee

也许将retval=...和添加return retval到包装器中。如果按原样使用装饰器,它将丢弃func的返回值。
戴夫X

10

我发现自己一次又一次地解决了这个问题,因此终于为它创建了一个。使用安装pip install timer_cm。然后:

from time import sleep
from timer_cm import Timer

with Timer('Long task') as timer:
    with timer.child('First step'):
        sleep(1)
    for _ in range(5):
        with timer.child('Baby steps'):
            sleep(.5)

输出:

Long task: 3.520s
  Baby steps: 2.518s (71%)
  First step: 1.001s (28%)

一个看似相关的问题,我提出:stackoverflow.com/questions/48260833/...
lurix66

除错字(“导入计时器” --->“导入计时器”)和缺少的包(import time)之外
都很好用

这太妙了。我用一个存根创建了仓库中的github问题,人们可以在导入时使用,如果他们想使其可选的话。
克雷格·林格

9

您可以通过上下文管理器来实现,例如:

from contextlib import contextmanager
import time
import logging
@contextmanager
def _log_time_usage(prefix=""):
    '''log the time usage in a code block
    prefix: the prefix text to show
    '''
    start = time.time()
    try:
        yield
    finally:
        end = time.time()
        elapsed_seconds = float("%.2f" % (end - start))
        logging.debug('%s: elapsed seconds: %s', prefix, elapsed_seconds)

使用示例:

with _log_time_usage("sleep 1: "):
    time.sleep(1)

在最后一行应该是prefix,而不是item_name
George Petrov

1

为简单起见,我现在爱上了另一个选择- ipython。在ipython中,您有很多有用的东西,另外:

%time <expression> -在表达上获得直接的cpu和墙时间

%timeit <expression> -在表达式循环中获得cpu和墙时间


0

Python 3-使用标准库的简单解决方案

选项1:三引号代码

import inspect
import timeit


code_block = inspect.cleandoc("""
    base = 123456789
    exponent = 100
    return base ** exponent
    """)
print(f'\Code block: {timeit.timeit(code_block, number=1, globals=globals())} elapsed seconds')

inspect.cleandoc 处理多余的制表符和空格的删除,以便可以复制和粘贴代码块而不会出现缩进错误。

 

选项2:将代码块放置在函数中

import timeit


def my_function():
    base = 123456789
    exponent = 100
    return base ** exponent


if __name__ == '__main__':
    print(f'With lambda wrapper: {timeit.timeit(lambda: my_function(), number=1)} elapsed seconds')

请注意,与直接计时功能主体相比,函数调用会增加额外的执行时间。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.