8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

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

Joud 1月前

160 0

我想测量执行某个函数所花费的时间。我无法让 timeit 工作:import timeitstart = timeit.timeit()print(\'hello\')end = timeit.timeit()print(end - start)

我想测量执行某个函数所花费的时间。我无法开始 timeit 工作:

import timeit
start = timeit.timeit()
print("hello")
end = timeit.timeit()
print(end - start)
帖子版权声明 1、本帖标题:如何在 Python 中测量经过的时间?
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Joud在本站《matplotlib》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 我为此创建了一个库,如果你想测量一个函数,你可以这样做

    
    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

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

    如果您使用的是 Python 3.8 或更高版本,则可以使用 赋值表达式 (又名海象运算符)以相当优雅的方式实现这一点:

    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}
    
  • 我们还可以将时间转换为人类可读的时间。

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

    这个函数的优点和缺点是你不需要传递开始时间

  • lambda 更简洁:print(timeit.timeit(lambda: naive_func(1_000), number=1_000_000))

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

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

  • 有点太晚了,但也许对某些人来说有用。我认为这是一种非常干净的方法。

    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 中的函数。但是,它可以与任何其他函数一起使用。干杯!

  • @Danny 在顶部,我已将类型别名 AnyF 定义为 Callable[..., Any],因此 AnyF 是一个可以接受任意数量任意类型参数并返回任何值的函数。因此 Callable[[AnyF], AnyF] 将扩展为 Callable[[Callable[..., Any]], Callable[..., Any]]。这是计时器返回值的类型,也称为装饰器的完整类型。它是一个以任意类型的函数作为其唯一参数并返回任意类型的函数的函数。

  • 这太酷了,谢谢你的分享。我还没有遇到过类型库或 nonlocal 关键字——找到新东西来学习很有趣。我很难理解这个:Callable[[AnyF], AnyF]。这是什么意思?

  • 这是一个有详细文档和完整类型提示的装饰器,我将其用作通用实用程序:

    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)
    

    输出:

    takes_long: 4.942629056s
    True
    

    可以使用以下方法检查文档测试:

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

    类型提示如下:

    $ mypy timer.py
    
  • 易于阅读,易于使用,足够精确,可用于近似测试或比较。但是,由于我似乎无法在撰写本文时进行编辑,因此“比较两个操作的时间”,我觉得在 import 行之后应该有 t0 = time.time()。然后 print(t1 -t0) 是第一个操作的时间。需要 2 次来比较 2 个操作。

  • 引用 13

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

    import time
    
    b = (123*321)*123
    t1 = time.time()
    
    c = ((9999^123)*321)^123
    t2 = time.time()
    
    print(t2-t1)
    

    7.987022399902344e-05

  • 还有一种使用 timeit :

    from timeit import timeit
    
    def func():
        return 1 + 1
    
    time = timeit(func, number=1)
    print(time)
    
  • 要了解每个函数的递归调用,请执行以下操作:

    %load_ext snakeviz
    %%snakeviz
    

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

    enter image description here

    以下是代码。同样,以 开头的两行 % 是使用 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 网站 .

  • 我喜欢它 简单 (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
    
  • 感谢您的评论。我对 PEP 604 启用 Type | None 代替 Optional[Type] 感到困惑,但这不适用于此处。所以,您说得对,不需要 python 3.10。PEP 585 证实了您的建议,所以我更新了我的答案。

  • 您可能希望直接对 collections.abc.Iterator 进行下标;请参阅 docs.python.org/3/library/typing.html#typing.Iterator。顺便说一句,由于类型问题,运行此功能所需的最低版本不是 3.10。

  • 以下是使用以下方法得到的答案:

    • 简洁的上下文管理器来计时代码片段
    • time.perf_counter() 计算时间增量。它应该是首选,因为它不可调整(系统管理员和守护进程都不能更改其值),与 time.time() (参见 doc )
    import time
    from collections.abc import Iterator
    from contextlib import contextmanager
    
    @contextmanager
    def time_it() -> Iterator[None]:
        tic: float = time.perf_counter()
        try:
            yield
        finally:
            toc: float = time.perf_counter()
            print(f"Computation time = {1000*(toc - tic):.3f}ms")
    

    如何使用它的一个例子:

    # Example: vector dot product computation
    with time_it():
        A = B = range(1_000_000)
        dot = sum(a*b for a,b in zip(A,B))
    # Computation time = 95.353ms
    

    附录

    import time
    
    # to check adjustability
    assert time.get_clock_info('time').adjustable
    assert time.get_clock_info('perf_counter').adjustable is False
    
  • 你好,有没有办法有条件地测量函数运行的时间?例如,每当我在其中传递参数 True 时?

返回
作者最近主题: