测量Python中经过的时间?

问题描述 投票:897回答:25

我想要的是在我的代码中的某个地方开始计算时间,然后获得通过的时间,以测量执行少量功能所花费的时间。我认为我使用的是timeit模块错误,但文档对我来说只是让人困惑。

import timeit

start = timeit.timeit()
print "hello"
end = timeit.timeit()
print end - start
python performance measure timeit
25个回答
1168
投票

如果您只想测量两点之间经过的挂钟时间,可以使用time.time()

import time

start = time.time()
print("hello")
end = time.time()
print(end - start)

这给出了以秒为单位的执行时间。

3.3以后的另一个选择可能是使用perf_counterprocess_time,具体取决于您的要求。在3.3之前,建议使用time.clock(感谢Amber)。但是,它目前已被弃用:

在Unix上,将当前处理器时间返回为以秒为单位的浮点数。精确度,实际上是“处理器时间”含义的定义,取决于同名C函数的精度。

在Windows上,此函数返回自第一次调用此函数以来经过的挂钟秒,作为浮点数,基于Win32函数QueryPerformanceCounter()。分辨率通常优于1微秒。

从版本3.3开始不推荐使用:此函数的行为取决于平台:根据您的要求,使用perf_counter()process_time()来定义明确的行为。


17
投票

python cProfile和pstats模块为测量某些函数所用的时间提供了极大的支持,而无需在现有函数周围添加任何代码。

例如,如果你有一个python脚本timeFunctions.py:

import time

def hello():
    print "Hello :)"
    time.sleep(0.1)

def thankyou():
    print "Thank you!"
    time.sleep(0.05)

for idx in range(10):
    hello()

for idx in range(100):
    thankyou()

要运行探查器并为文件生成统计信息,您只需运行:

python -m cProfile -o timeStats.profile timeFunctions.py

这样做是使用cProfile模块分析timeFunctions.py中的所有函数并收集timeStats.profile文件中的统计信息。请注意,我们不必向现有模块添加任何代码(timeFunctions.py),这可以使用任何模块完成。

获得stats文件后,可以按如下方式运行pstats模块:

python -m pstats timeStats.profile

这将运行交互式统计浏览器,为您提供许多不错的功能。对于您的特定用例,您只需检查您的功能的统计数据。在我们的示例中,检查两个函数的统计信息显示以下内容:

Welcome to the profile statistics browser.
timeStats.profile% stats hello
<timestamp>    timeStats.profile

         224 function calls in 6.014 seconds

   Random listing order was used
   List reduced from 6 to 1 due to restriction <'hello'>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
       10    0.000    0.000    1.001    0.100 timeFunctions.py:3(hello)

timeStats.profile% stats thankyou
<timestamp>    timeStats.profile

         224 function calls in 6.014 seconds

   Random listing order was used
   List reduced from 6 to 1 due to restriction <'thankyou'>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
      100    0.002    0.000    5.012    0.050 timeFunctions.py:7(thankyou)

虚拟示例没有做太多,但让您了解可以做什么。关于这种方法最好的部分是我不必编辑任何现有代码来获取这些数字,显然有助于分析。


17
投票

这是定时代码的另一个上下文管理器 -

用法:

from benchmark import benchmark

with benchmark("Test 1+1"):
    1+1
=>
Test 1+1 : 1.41e-06 seconds

或者,如果您需要时间价值

with benchmark("Test 1+1") as b:
    1+1
print(b.time)
=>
Test 1+1 : 7.05e-07 seconds
7.05233786763e-07

benchmark.朋友:

from timeit import default_timer as timer

class benchmark(object):

    def __init__(self, msg, fmt="%0.3g"):
        self.msg = msg
        self.fmt = fmt

    def __enter__(self):
        self.start = timer()
        return self

    def __exit__(self, *args):
        t = timer() - self.start
        print(("%s : " + self.fmt + " seconds") % (self.msg, t))
        self.time = t

改编自http://dabeaz.blogspot.fr/2010/02/context-manager-for-timing-benchmarks.html


15
投票

使用分析器模块。它给出了非常详细的概况。

import profile
profile.run('main()')

它输出如下:

          5 function calls in 0.047 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.000    0.000 :0(exec)
        1    0.047    0.047    0.047    0.047 :0(setprofile)
        1    0.000    0.000    0.000    0.000 <string>:1(<module>)
        0    0.000             0.000          profile:0(profiler)
        1    0.000    0.000    0.047    0.047 profile:0(main())
        1    0.000    0.000    0.000    0.000 two_sum.py:2(twoSum)

我发现它非常有用。


13
投票

这是我在这里经过许多好的答案以及其他一些文章后的发现。

首先,你总是想使用timeit而不是time.time(在许多情况下还使用perf counter API),因为

  1. timeit选择您的操作系统和Python版本上可用的最佳计时器。
  2. timeit禁用垃圾收集,但这不是你可能想要或不想要的东西。

现在的问题是timeit不是那么简单,因为它需要设置,当你有大量的导入时,事情变得很难看。理想情况下,您只需要一个装饰者或使用with块并测量时间。不幸的是,没有内置的可用内容,所以我创建了下面的小实用程序模块。

定时实用程序模块

# utils.py
from functools import wraps
import gc
import timeit

def MeasureTime(f):
    @wraps(f)
    def _wrapper(*args, **kwargs):
        gcold = gc.isenabled()
        gc.disable()
        start_time = timeit.default_timer()
        try:
            result = f(*args, **kwargs)
        finally:
            elapsed = timeit.default_timer() - start_time
            if gcold:
                gc.enable()
            print('Function "{}": {}s'.format(f.__name__, elapsed))
        return result
    return _wrapper

class MeasureBlockTime:
    def __init__(self,name="(block)", no_print = False, disable_gc = True):
        self.name = name
        self.no_print = no_print
        self.disable_gc = disable_gc
    def __enter__(self):
        if self.disable_gc:
            self.gcold = gc.isenabled()
            gc.disable()
        self.start_time = timeit.default_timer()
    def __exit__(self,ty,val,tb):
        self.elapsed = timeit.default_timer() - self.start_time
        if self.disable_gc and self.gcold:
            gc.enable()
        if not self.no_print:
            print('Function "{}": {}s'.format(self.name, self.elapsed))
        return False #re-raise any exceptions

如何计时功能

现在你可以通过在它前面放一个装饰器来计时任何功能:

import utils

@utils.MeasureTime
def MyBigFunc():
    #do something time consuming
    for i in range(10000):
        print(i)

如何计时代码块

如果你想要时间部分代码,那么只需将它放在with块中:

import utils

#somewhere in my code

with utils.MeasureBlockTime("MyBlock"):
    #do something time consuming
    for i in range(10000):
        print(i)

# rest of my code

好处

有几个半支持版本浮动,所以我想指出一些亮点:

  1. 出于前面所述的原因,使用timeit from timeit而不是time.time。
  2. 在计时期间禁用GC。
  3. Decorator接受具有命名或未命名参数的函数。
  4. 能够在块时间中禁用打印(使用with utils.MeasureBlockTime() as t然后使用t.elapsed)。
  5. 能够保持gc启用块时序。

12
投票

(仅限Ipython)您可以使用%timeit来测量平均处理时间:

def foo():
    print "hello"

然后:

%timeit foo()

结果是这样的:

10000 loops, best of 3: 27 µs per loop

11
投票

在python3上:

from time import sleep, perf_counter as pc
t0 = pc()
sleep(1)
print(pc()-t0)

优雅而短暂。


9
投票

这是一种超级后来的反应,但也许它可以为某人服务。这是一种我认为非常干净的方法。

import time

def timed(fun, *args):
    s = time.time()
    r = fun(*args)
    print('{} execution took {} seconds.'.format(fun.__name__, time.time()-s))
    return(r)

timed(print, "Hello")

请记住,“print”是Python 3中的一个函数,而不是Python 2.7。但是,它适用于任何其他功能。干杯!


8
投票

使用timeit的另一种方法:

from timeit import timeit

def func():
    return 1 + 1

time = timeit(func, number=1)
print(time)

8
投票

现在是2019年。让我们用一种简洁的方式来做:

from ttictoc import TicToc
t = TicToc() ## TicToc("name")
t.tic();
# your code ...
t.toc();
print(t.elapsed)

使用这种方法而不是其他方法的优点:

  1. 简洁明了。它不需要程序员编写额外的变量,如: t1 =时间() t2 =时间() elapsed = t2 - t1
  2. 有嵌套
t = TicToc(nested=True)
t.tic()
some code1...
t.tic()
some code2...
t.tic()
some code3...
print(t.toc()) # Prints time for code 3 
print(t.toc()) # Prints time for code 2 with code 3
print(t.toc()) # Prints time for code 1 with code 2 and 3
  1. 保留你的tictoc的名字。
t = TicToc("save user")
print(t.name)

有关更详细的说明,请参阅此link


7
投票

我们还可以将时间转换为人类可读的时间。

import time, datetime

start = time.clock()

def num_multi1(max):
    result = 0
    for num in range(0, 1000):
        if (num % 3 == 0 or num % 5 == 0):
            result += num

    print "Sum is %d " % result

num_multi1(1000)

end = time.clock()
value = end - start
timestamp = datetime.datetime.fromtimestamp(value)
print timestamp.strftime('%Y-%m-%d %H:%M:%S')

512
投票

使用timeit.default_timer而不是timeit.timeit。前者提供了您平台上可用的最佳时钟和自动版本的Python:

from timeit import default_timer as timer

start = timer()
# ...
end = timer()
print(end - start) # Time in seconds, e.g. 5.38091952400282

根据操作系统,timeit.default_timer被分配到time.time()或time.clock()。在Python 3.3+上,default_timer在所有平台上都是time.perf_counter()。见Python - time.clock() vs. time.time() - accuracy?

也可以看看:


6
投票

我为此创建了一个库,如果你想测量一个函数你就可以这样做


from pythonbenchmark import compare, measure
import time

a,b,c,d,e = 10,10,10,10,10
something = [a,b,c,d,e]

@measure
def myFunction(something):
    time.sleep(0.4)

@measure
def myOptimizedFunction(something):
    time.sleep(0.2)

myFunction(input)
myOptimizedFunction(input)

https://github.com/Karlheinzniebuhr/pythonbenchmark


5
投票

To get insight on every function calls recursively, do:

%load_ext snakeviz
%%snakeviz

它只需要在Jupyter笔记本中使用这两行代码,它就会生成一个很好的交互式图表。例如:

enter image description here

这是代码。同样,以%开头的2行是使用snakeviz所需的唯一额外代码行:

# !pip install snakeviz
%load_ext snakeviz
import glob
import hashlib

%%snakeviz

files = glob.glob('*.txt')
def print_files_hashed(files):
    for file in files:
        with open(file) as f:
            print(hashlib.md5(f.read().encode('utf-8')).hexdigest())
print_files_hashed(files)

似乎也可以在笔记本外面运行snakeviz。有关snakeviz website的更多信息。


5
投票

我喜欢它简单(python 3):

from timeit import timeit

timeit(lambda: print("hello"))

单次执行的输出为微秒:

2.430883963010274

说明:timeit默认执行100万次匿名函数,结果以秒为单位。因此,单次执行的结果是相同的量,但平均为微秒。


对于慢速操作,添加较少的迭代次数,或者您可以永远等待:

import time

timeit(lambda: time.sleep(1.5), number=1)

迭代总数的输出总是以秒为单位:

1.5015795179999714

4
投票

你可以使用timeit。

这是一个关于如何使用Python REPL测试带参数的naive_func的示例:

>>> import timeit                                                                                         

>>> def naive_func(x):                                                                                    
...     a = 0                                                                                             
...     for i in range(a):                                                                                
...         a += i                                                                                        
...     return a                                                                                          

>>> def wrapper(func, *args, **kwargs):                                                                   
...     def wrapper():                                                                                    
...         return func(*args, **kwargs)                                                                  
...     return wrapper                                                                                    

>>> wrapped = wrapper(naive_func, 1_000)                                                                  

>>> timeit.timeit(wrapped, number=1_000_000)                                                              
0.4458435332577161  

如果函数没有任何参数,则不需要包装函数。


0
投票

我能想到的唯一方法是使用time.time()

import time
start = time.time()
sleep(5) #just to give it some delay to show it working
finish = time.time()
elapsed = finish - start
print(elapsed)

希望有所帮助。


-3
投票

除了ipython中的%timeit,你还可以使用%%timeit作为多行代码片段:

In [1]: %%timeit
   ...: complex_func()
   ...: 2 + 2 == 5
   ...:
   ...:

1 s ± 1.93 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

它也可以在jupyter笔记本中以相同的方式使用,只需将magic %%timeit放在单元格的开头。


-4
投票

最好简单地使用timeit :(它为同一个命令运行多次运行并为您提供结果)。

示例如下:

%timeit import pandas as pd

112
投票

Python 3 only:

从time.clock()is deprecated as of Python 3.3开始,你将需要使用time.perf_counter()进行系统范围的计时,或者使用time.process_time()进行进程范围的计时,就像你以前使用time.clock()一样:

import time

t = time.process_time()
#do some stuff
elapsed_time = time.process_time() - t

新功能process_time将不包括睡眠期间经过的时间。


77
投票

鉴于你想要的时间,

test.朋友:

def foo(): 
    # print "hello"   
    return "hello"

使用timeit的最简单方法是从命令行调用它:

% python -mtimeit -s'import test' 'test.foo()'
1000000 loops, best of 3: 0.254 usec per loop

不要试图使用time.timetime.clock(天真)来比较函数的速度。 They can give misleading results

PS。不要将打印语句放在您想要的时间函数中;否则测量的时间将取决于speed of the terminal


57
投票

使用上下文管理器执行此操作很有趣,该上下文管理器会在进入with块时自动记住开始时间,然后在块退出时冻结结束时间。通过一些小技巧,您甚至可以从相同的上下文管理器功能获得块内运行的经过时间计数。

核心库没有这个(但可能应该)。一旦到位,您可以执行以下操作:

with elapsed_timer() as elapsed:
    # some lengthy code
    print( "midpoint at %.2f seconds" % elapsed() )  # time so far
    # other lengthy code

print( "all done at %.2f seconds" % elapsed() )

这里的contextmanager代码足以完成这个诀窍:

from contextlib import contextmanager
from timeit import default_timer

@contextmanager
def elapsed_timer():
    start = default_timer()
    elapser = lambda: default_timer() - start
    yield lambda: elapser()
    end = default_timer()
    elapser = lambda: end-start

还有一些可运行的演示代码:

import time

with elapsed_timer() as elapsed:
    time.sleep(1)
    print(elapsed())
    time.sleep(2)
    print(elapsed())
    time.sleep(3)

请注意,通过设计此函数,elapsed()的返回值在块退出时被冻结,并且其他调用返回相同的持续时间(在此玩具示例中约为6秒)。


48
投票

我更喜欢这个。 timeit doc太混乱了。

from datetime import datetime 

start_time = datetime.now() 

# INSERT YOUR CODE 

time_elapsed = datetime.now() - start_time 

print('Time elapsed (hh:mm:ss.ms) {}'.format(time_elapsed))

注意,这里没有任何格式化,我只是在打印输出中写了hh:mm:ss所以可以解释time_elapsed


25
投票

使用time.time来度量执行可以为您提供命令的总执行时间,包括计算机上其他进程所花费的运行时间。这是用户注意到的时间,但如果您想要比较不同的代码片段/算法/函数/ ...则不好

有关timeit的更多信息:

如果您想更深入地了解分析:

更新:我在去年使用了http://pythonhosted.org/line_profiler/并发现它非常有用,并建议使用它而不是Pythons配置文件模块。


18
投票

这是一个微小的计时器类,返回“hh:mm:ss”字符串:

class Timer:
  def __init__(self):
    self.start = time.time()

  def restart(self):
    self.start = time.time()

  def get_time_hhmmss(self):
    end = time.time()
    m, s = divmod(end - self.start, 60)
    h, m = divmod(m, 60)
    time_str = "%02d:%02d:%02d" % (h, m, s)
    return time_str

用法:

# Start timer
my_timer = Timer()

# ... do something

# Get time string:
time_hhmmss = my_timer.get_time_hhmmss()
print("Time elapsed: %s" % time_hhmmss )

# ... use the timer again
my_timer.restart()

# ... do something

# Get time:
time_hhmmss = my_timer.get_time_hhmmss()

# ... etc

18
投票

测量时间(秒):

from timeit import default_timer as timer
from datetime import timedelta

start = timer()
end = timer()
print(timedelta(seconds=end-start))

输出:

0:00:01.946339
© www.soinside.com 2019 - 2024. All rights reserved.