ChatGPT解决这个技术问题 Extra ChatGPT

如何在 Python 中测量经过的时间?

我想测量执行功能所花费的时间。我无法让 timeit 工作:

import timeit
start = timeit.timeit()
print("hello")
end = timeit.timeit()
print(end - start)
timeit.timeit() 打印执行其参数所需的时间,默认为“通过”。你必须改用 start= time.time() end = time.time()

M
Mateen Ulhaq

使用 time.time() 测量两点之间经过的挂钟时间:

import time

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

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

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

在 Unix 上,以浮点数形式返回当前处理器时间,以秒为单位。精度,实际上是“处理器时间”含义的定义,取决于同名 C 函数的精度。在 Windows 上,此函数根据 Win32 函数 QueryPerformanceCounter() 以浮点数形式返回自第一次调用此函数以来经过的挂钟秒数。分辨率通常优于一微秒。 3.3 版后已弃用:此函数的行为取决于平台:根据您的要求使用 perf_counter() 或 process_time() 来获得明确定义的行为。


对于微秒,使用 datetime.time()
(对于性能测量,time.clock() 实际上是首选,因为如果系统时钟被打乱,它不会受到干扰,但 .time() 确实主要完成相同的目的。)
有没有一种很好的方法可以将生成的执行时间(以秒为单位)转换为 HH:MM::SS 之类的东西?
@Danijel:print(timedelta(seconds=execution_time))。虽然这是一个单独的问题。
time.clock() 在 Python 3.3 docs.python.org/3.3/library/time.html#time.clock 已弃用
j
jfs

使用 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?

也可以看看:

优化代码

如何优化速度


很好的答案 - 使用 timeit 会产生更准确的结果,因为它会自动考虑垃圾收集和操作系统差异等问题
这以毫秒或秒为单位给出时间?
@KhushbooTiwari 以小数秒为单位。
我认为需要添加官方文档中的此注释default_timer() measurations can be affected by other programs running on the same machine, so the best thing to do when accurate timing is necessary is to repeat the timing a few times and use the best time. The -r option is good for this; the default of 3 repetitions is probably enough in most cases. On Unix, you can use time.clock() to measure CPU time.
我不喜欢导入的方式。 “从 timeit 导入 default_timer 作为计时器”。在阅读代码时迷路了。如果没有“作为计时器”部分,可能会更清楚。
p
phoenix

仅限 Python 3:

由于 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 将不包括睡眠期间经过的时间。


Use timeit.default_timer 而不是 time.perf_counter。前者会选择合适的计时器来衡量针对你的平台和 Python 版本调整的时间性能。 process_time()包括睡眠期间的时间,因此不适合测量经过的时间。
我正在使用 Pierre 建议的实现,这些值是以秒为单位给出的吗?
这个答案似乎离题了(嗯,这个问题不是很具体)。有两个“时间”测量:两点之间的挂钟时间,进程的cpu消耗。
@fjs timeit.default_timer 在 Python 中使用 time.perf_counter >=3.3 docs.python.org/3/library/timeit.html#timeit.default_timer
例如,elapsed_time 返回 0.07812。我该如何解释?一秒会是 1.000,所以我的脚本在 7,812 毫秒内运行吗?
G
Gal Bracha

以秒为单位测量时间:

from timeit import default_timer as timer
from datetime import timedelta

start = timer()

# ....
# (your code runs here)
# ...

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

输出:

0:00:01.946339

这是输出最简洁的最简洁的答案。
C
Community

给定一个你想要计时的函数,

测试.py:

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


N
Nicholas Riley

使用上下文管理器执行此操作很有趣,它会在进入 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 秒)。


其他上下文管理器示例:dabeaz.blogspot.fr/2010/02/…
@Jérôme 很好的例子-我将其改编为另一个答案-stackoverflow.com/a/41408510/243392
S
Saugat

我更喜欢这个。 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


有人告诉我 timeit 计算 CPU 时间,datetime 是否也考虑使用的 CPU 时间?这些是一样的吗?
以这种方式测量经过的时间是有风险的,因为 datetime.now() 可能由于网络时间同步、夏令时切换或用户旋转时钟等原因在两个调用之间发生变化。
来自 Shital Shah 的回答:“首先,如果您在 timeit 和 time.time 之间进行辩论,则 timeit 有两个优点:timeit 选择您的操作系统和 Python 版本上可用的最佳计时器。timeit 禁用垃圾收集,但是,这不是您可能想要也可能不想要。”
M
Mingwei He

这是另一种方法:

>> from pytictoc import TicToc
>> t = TicToc() # create TicToc instance
>> t.tic() # Start timer
>> # do something
>> t.toc() # Print elapsed time
Elapsed time is 2.612231 seconds.

与传统方式比较:

>> from time import time
>> t1 = time()
>> # do something
>> t2 = time()
>> elapsed = t2 - t1
>> print('Elapsed time is %f seconds.' % elapsed)
Elapsed time is 2.612231 seconds.

安装:

pip install pytictoc

有关详细信息,请参阅 PyPi page


最好解释一下使用这个库相对于其他方法的优势。
嵌套的功能实际上被破坏了。我打开了一个问题,描述了代码中的问题在哪里,但回购协议一年内没有维护,所以我不希望有任何变化。
我发现嵌套有点混乱。如果我遇到了隐藏在代码中的 t.tic(),那么开发人员应该在脑海中列出我应该期望它在系列中的哪个位置。您是否发现自己设置了巢穴或只是多个 tictocs?
@PetarMI:仅供参考,我刚刚解决了 ttictoc 的问题。我以前很乱,但现在应该很好了。
@hlg 如果我没记错的话,MATLAB 使用与时间类似名称的函数。所以我想优点是相似之处,对于那些在 MATLAB 中喜欢这个但改用 Python 的人来说。
u
user1318499

计算操作持续时间的最简单方法:

import time

start_time = time.monotonic()

<operations, programs>

print('seconds: ', time.monotonic() - start_time)

官方文档 here


user1318499 并不是它返回负值,它可以返回比先前调用更低的值。 docs.python.org/3/library/time.html#time.time
最好使用 time.monotonic_ns(),请参阅 docs.python.org/3/library/time.html#time.monotonic_ns
S
Shital Shah

这是我在这里阅读了许多好的答案以及其他几篇文章后的发现。

首先,如果您在 timeittime.time 之间进行辩论,timeit 有两个优点:

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

现在的问题是 timeit 使用起来并不简单,因为它需要设置,而且当你有一堆导入时事情会变得很糟糕。理想情况下,您只需要一个装饰器或使用 with 块并测量时间。不幸的是,没有可用的内置功能,因此您有两种选择:

选项 1:使用 timebudget 库

timebudget 是一个多功能且非常简单的库,您只需在 pip 安装后的一行代码中即可使用它。

@timebudget  # Record how long this function takes
def my_method():
    # my code

选项 2:使用我的小模块

我在名为 timing.py 的小计时实用程序模块下创建了。只需将此文件放入您的项目并开始使用它。唯一的外部依赖是 runstats,它又很小。

现在你可以通过在它前面放置一个装饰器来为任何函数计时:

import timing

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

timing.print_all_timings()

如果您想对部分代码进行计时,只需将其放在 with 块中:

import timing

#somewhere in my code

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

# rest of my code

timing.print_all_timings()

优点:

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

出于前面描述的原因,使用 timeit 中的计时器而不是 time.time。如果需要,您可以在计时期间禁用 GC。装饰器接受具有命名或未命名参数的函数。能够在块定时中禁用打印(与 timing.MeasureBlockTime() 一起使用作为 t 然后 t.elapsed)。能够保持 gc 为块计时启用。


关于“能够在块定时中禁用打印(使用 with utils.MeasureBlockTime() as t,然后使用 t.elapsed)。”:这不起作用,因为 tNone。我认为 __enter__ 需要返回 self,并且要禁用打印,我们必须将其构造为 utils.MeasureBlockTime(no_print=True)
@mic - 感谢您指出这一点。我已经用这个和其他几个增强功能更新了答案。
C
Community

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

关于 timeit 的更多信息:

使用 timeit 模块

timeit – 为一小段 Python 代码的执行计时

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

http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Profiling_Code

如何分析 python 脚本?

更新:我在去年使用了很多 http://pythonhosted.org/line_profiler/,发现它很有帮助,建议使用它来代替 Python 的配置文件模块。


B
Brian Burns

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

用法:

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

基准.py:

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


L
Leonid Ganeline

使用分析器模块。它提供了非常详细的配置文件。

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)

我发现它非常有用。


main() 是什么?如果您可以提供一个简单的代码示例,将会更有用。
s
sanchitarora

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) 添加任何代码,这可以通过任何模块完成。

获得统计文件后,您可以按如下方式运行 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)

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


这一切都很好,但是 AFAICT 这仍然测量 CPU 时间,而不是挂钟时间。
实际上有一些混乱;看来 cProfile 默认情况下确实会查看挂钟时间。我赞成你的回答。
仅供参考:如果您得到 python -m pstats timeStats.profile ValueError: bad marshal data (unknown type code),请检查您正在运行的 python 版本。我在运行 python3 -m cProfile...python -m pstats 时得到了这个。我的错误,但让我一秒钟,所以,我想分享 don't forget consistency。 =)
S
Shai

这是一个返回“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

现在包含 f 字符串和 format specificationstime_str = f"{h:02d}:{m:02d}:{s:02d}"
r
raacer

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

def foo():
    print "hello"

接着:

%timeit foo()

结果是这样的:

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

值得一提的是,可以将标志传递给 %timeit,例如 -n 指定代码应该重复多少次。
D
David

我喜欢它简单(python 3):

from timeit import timeit

timeit(lambda: print("hello"))

单次执行的输出为微秒:

2.430883963010274

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

对于缓慢的操作,请添加较少的迭代次数,否则您可能会永远等待:

import time

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

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

1.5015795179999714

你说的输出是什么意思? timeit 会写入标准输出吗?
没有。我的意思是返回值。
D
DmitrySemenov

在 python3 上:

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

优雅而简短。


这是什么?小姐?
@KIC 只需几秒钟。
r
raacer

使用 timeit 的另一种方法:

from timeit import timeit

def func():
    return 1 + 1

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

G
Guillaume Chevalier

要以递归方式深入了解每个函数调用,请执行以下操作:

%load_ext snakeviz
%%snakeviz

它只需要 Jupyter 笔记本中的这两行代码,就可以生成一个漂亮的交互式图表。例如:

https://i.stack.imgur.com/0ahaw.png

这是代码。同样,以 % 开头的 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 的更多信息。


W
Wojciech Moszczyński

如何测量两次操作之间的时间。比较两次操作的时间。

import time

b = (123*321)*123
t1 = time.time()

c = ((9999^123)*321)^123
t2 = time.time()

print(t2-t1)

7.987022399902344e-05


易于阅读,易于使用,足够准确,可以进行近似测试或比较。但是,由于我在撰写本文时似乎无法编辑,以“比较两次操作的时间”,这应该有 t0 = time.time() 我在导入行之后的感觉。那么print(t1 -t0)是第一次操作时间。比较 2 次操作需要 2 次。
r
ruohola

这是我用作通用实用程序的一个有据可查且完全类型提示的装饰器:

from functools import wraps
from time import perf_counter
from typing import Any, Callable, Optional, TypeVar, cast

F = TypeVar("F", bound=Callable[..., Any])


def timer(prefix: Optional[str] = None, precision: int = 6) -> Callable[[F], F]:
    """Use as a decorator to time the execution of any function.

    Args:
        prefix: String to print before the time taken.
            Default is the name of the function.
        precision: How many decimals to include in the seconds value.

    Examples:
        >>> @timer()
        ... def foo(x):
        ...     return x
        >>> foo(123)
        foo: 0.000...s
        123
        >>> @timer("Time taken: ", 2)
        ... def foo(x):
        ...     return x
        >>> foo(123)
        Time taken: 0.00s
        123

    """
    def decorator(func: F) -> F:
        @wraps(func)
        def wrapper(*args: Any, **kwargs: Any) -> Any:
            nonlocal prefix
            prefix = prefix if prefix is not None else f"{func.__name__}: "
            start = perf_counter()
            result = func(*args, **kwargs)
            end = perf_counter()
            print(f"{prefix}{end - start:.{precision}f}s")
            return result
        return cast(F, wrapper)
    return decorator

示例用法:

from timer import timer


@timer(precision=9)
def takes_long(x: int) -> bool:
    return x in (i for i in range(x + 1))


result = takes_long(10**8)
print(result)

输出:take_long:4.942629056s True

可以通过以下方式检查文档测试:

$ python3 -m doctest --verbose -o=ELLIPSIS timer.py

类型提示:

$ mypy timer.py

这个超级酷,谢谢分享。我没有遇到过打字库或 nonlocal 关键字——找到新东西来学习很有趣。我很难理解这个:Callable[[AnyF], AnyF]。这是什么意思?
@Danny 在顶部,我将类型别名 AnyF 定义为表示 Callable[..., Any],因此 AnyF 是一个可以接受任意数量的任何类型参数并返回任何内容的函数。因此 Callable[[AnyF], AnyF] 将扩展为 Callable[[Callable[..., Any]], Callable[..., Any]]。这是 timer 的返回值的类型,也就是 decorator 的完整类型。它是一个将任何类型的函数作为其唯一参数并返回任何类型的函数的函数。
感谢您的解释!我仍在尝试完全了解装饰器的内部结构。这有很大帮助!
A
Andreas Herman

一种超级后来的回应,但也许它对某人有用。这是一种我认为非常干净的方法。

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 中的函数。但是,它适用于任何其他功能。干杯!


如何打印非常小的时间?我总是得到 0.0 秒
你可以把它变成一个装饰器;这对我来说看起来更好。
V
Vlad Bezden

你可以使用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  

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


lambda 会更简洁:print(timeit.timeit(lambda: naive_func(1_000), number=1_000_000))
M
Myeongsik Joo

print_elapsed_time 函数如下

def print_elapsed_time(prefix=''):
    e_time = time.time()
    if not hasattr(print_elapsed_time, 's_time'):
        print_elapsed_time.s_time = e_time
    else:
        print(f'{prefix} elapsed time: {e_time - print_elapsed_time.s_time:.2f} sec')
        print_elapsed_time.s_time = e_time

以这种方式使用它

print_elapsed_time()
.... heavy jobs ...
print_elapsed_time('after heavy jobs')
.... tons of jobs ...
print_elapsed_time('after tons of jobs')

结果是

after heavy jobs elapsed time: 0.39 sec
after tons of jobs elapsed time: 0.60 sec  

这个功能的优点和缺点是你不需要通过开始时间


N
Ninjakannon

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

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

L
Lee Netherton

尽管问题中没有严格要求,但通常情况下,您需要一种简单、统一的方法来增量测量几行代码之间的经过时间。

如果您使用的是 Python 3.8 或更高版本,则可以使用 assignment expressions(又名海象运算符)以相当优雅的方式实现此目的:

import time

start, times = time.perf_counter(), {}

print("hello")
times["print"] = -start + (start := time.perf_counter())

time.sleep(1.42)
times["sleep"] = -start + (start := time.perf_counter())

a = [n**2 for n in range(10000)]
times["pow"] = -start + (start := time.perf_counter())

print(times)

=>

{'print': 2.193450927734375e-05, 'sleep': 1.4210970401763916, 'power': 0.005671024322509766}

K
Karl

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


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


D
Daniel Giger

如果您希望能够方便地对函数进行计时,可以使用一个简单的装饰器:

def timing_decorator(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        original_return_val = func(*args, **kwargs)
        end = time.time()
        print("time elapsed in ", func.__name__, ": ", end - start, sep='')
        return original_return_val

    return wrapper

您可以在要计时的函数上使用它,如下所示:

@timing_decorator
def function_to_time():
    time.sleep(1)

然后,无论何时调用 function_to_time,它都会打印花费了多长时间以及正在计时的函数的名称。


是否有 Python2.x 方法可以做到这一点而无需从 __future__ 导入 print_function?我尝试使用 join,但我对它的理解不够好,无法使其正常工作。
更新。我想通了并使用了这个:print(''.join(["time elapsed in ",(func.__name__),": ",str(end - start)]))
A
Asclepius

这种独特的基于类的方法提供了可打印的字符串表示、可自定义的舍入以及以字符串或浮点数形式方便地访问经过的时间。它是用 Python 3.7 开发的。

import datetime
import timeit


class Timer:
    """Measure time used."""
    # Ref: https://stackoverflow.com/a/57931660/

    def __init__(self, round_ndigits: int = 0):
        self._round_ndigits = round_ndigits
        self._start_time = timeit.default_timer()

    def __call__(self) -> float:
        return timeit.default_timer() - self._start_time

    def __str__(self) -> str:
        return str(datetime.timedelta(seconds=round(self(), self._round_ndigits)))

用法:

# Setup timer
>>> timer = Timer()

# Access as a string
>>> print(f'Time elapsed is {timer}.')
Time elapsed is 0:00:03.
>>> print(f'Time elapsed is {timer}.')
Time elapsed is 0:00:04.

# Access as a float
>>> timer()
6.841332235
>>> timer()
7.970274425

这既简单又出色——易于编码;我很惊讶 (a) 这种功能在任何现有的 Python 分析器中都不存在;并且(b)这个答案,包括一个可以复制和粘贴的简单类,在几年前并没有被提供给这个问题,并且得到了更多的支持。