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

Posted

技术标签:

【中文标题】在 Python 2.7 中获取代码块的执行时间【英文标题】:Get time of execution of a block of code in Python 2.7 【发布时间】:2013-03-20 09:06:33 【问题描述】:

我想测量在 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 时间并不重要(尽管我想测量它们), 但是在过去的时间里,我希望能够做这样的事情, 而不是使用复杂的命令或模块。

【问题讨论】:

【参考方案1】:

要获得以秒为单位的经过时间,您可以使用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(),因为它会为任何平台选择具有更高分辨率的计时函数。

【讨论】:

我已经读到,对于只需要几分之一秒运行的代码块,这不是最佳方法。另外我认为使用时间模块 .clock() 方法是首选? ***.com/questions/85451/… 将我的答案更改为使用timeit.default_timer(),它将在time.time()time.clock() 之间进行选择,具体取决于您使用的平台上哪个分辨率更高。【参考方案2】:

我总是使用装饰器为现有函数做一些额外的工作,包括获取执行时间。它是 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()

【讨论】:

对不起,我还是不知道怎么使用装饰器:( @LucaCerone 关于装饰***.com/questions/739654/… 有一个很好的解释。试着耐心读下去,你就会明白decorator了。 也许在包装器中添加 retval=...return retval。如果按原样使用装饰器,它将丢弃 func 的返回值。【参考方案3】:

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

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 【参考方案4】:

我发现自己一次又一次地解决了这个问题,所以我终于为它创建了一个library。使用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%)

【讨论】:

我提出的一个看似相关的问题:***.com/questions/48260833/… 效果很好,除了一个错字('import timer' ---> 'import Timer')和一个丢失的包(import time 太棒了。我在你的 repo 上创建了一个 github 问题,如果他们想让它成为可选的,人们可以在导入时使用一个存根。【参考方案5】:

为了简单起见,我现在非常喜欢另一种选择 - ipython。在 ipython 你有很多有用的东西加上:

%time <expression> - 在表达式上获得直接的 cpu 和 wall time

%timeit <expression> - 在表达式循环中获取 cpu 和 wall time

【讨论】:

【参考方案6】:

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')

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

【讨论】:

以上是关于在 Python 2.7 中获取代码块的执行时间的主要内容,如果未能解决你的问题,请参考以下文章

Python 2.7:仅从文件句柄(而不是路径)获取文件的大小

如何在python 2.7中获取随机整数[重复]

块的执行总是延迟

获取时间戳而不是日期时间对象,sqlalchemy python 2.7

Python 2.7获取网站源代码的几种方式

Python 2.7获取网站源代码的几种方式_20160924