【问题标题】:How to measure time taken between lines of code in python?如何测量python中代码行之间的时间?
【发布时间】:2013-01-05 07:19:07
【问题描述】:

所以在Java中,我们可以做到How to measure time taken by a function to execute

但是它是如何在 python 中完成的呢?要测量代码行之间的时间开始和结束时间? 这样做的东西:

import some_time_library

starttime = some_time_library.some_module()
code_tobe_measured() 
endtime = some_time_library.some_module()

time_taken = endtime - starttime

【问题讨论】:

标签: python time profiling measure


【解决方案1】:

如果你想测量CPU时间,可以使用time.process_time() for Python 3.3及以上:

import time
start = time.process_time()
# your code here    
print(time.process_time() - start)

第一次调用会打开计时器,第二次调用会告诉您已经过了多少秒。

还有一个函数time.clock(),不过是deprecated since Python 3.3,在Python 3.8中会被移除。

有更好的分析工具,例如 timeitprofile,但是 time.process_time() 将测量 CPU 时间,这就是您要问的问题。

如果您想测量挂钟时间,请使用time.time()

【讨论】:

  • 这不是您使用time.clock() 的方式,time.clock() 在 Unix 上测量 CPU 时间,但在 Windows 上测量壁挂时间。最好使用time.time(),其中行为不会随操作系统而变化。 stackoverflow.com/questions/85451/…
  • 很好的观察,@Tim。然而,关于同一问题的另一篇文章在 time.clock() 上引用了 python 文档,“这是用于对 Python 或计时算法进行基准测试的函数”。我想这涉及到你真正想要测量的问题。
  • time.time() 的一个非常糟糕的地方是它会受到时间同步 ntpdate 等的影响。因此我会说 time.clock() 将是唯一可靠的选择
  • DeprecationWarning: time.clock has been deprecated in Python 3.3 and will be removed from Python 3.8: use time.perf_counter or time.process_time instead
  • 嗯...不知道我做错了什么。我用time.sleep(10) 替换了# your code here,得到了0.0 秒。添加for i in range(10000):/pass 产生了相同的结果。在我尝试过的任何情况下,time.process_time() 总是返回相同的数字。我使用time.perf_counter() 得到了预期的结果
【解决方案2】:

你也可以使用time库:

import time

start = time.time()

# your code

# end

print(f'Time: {time.time() - start}')

【讨论】:

  • @Hayat - 此方法以浮点数形式返回时间,以自纪元以​​来的秒数表示,以 UTC 为单位。 [docs.python.org/3/library/time.html]
  • @AnumoySutradhar 不是真的,因为它是从一个纪元中减去一个纪元,所以你会得到两个时间之间的时间差。
【解决方案3】:

借助一个小型便利类,您可以测量缩进行所花费的时间,如下所示:

with CodeTimer():
   line_to_measure()
   another_line()
   # etc...

缩进的行执行完毕后会显示以下内容:

Code block took: x.xxx ms

更新:您现在可以使用pip install linetimerfrom linetimer import CodeTimer 获取课程。见this GitHub project

以上类的代码:

import timeit

class CodeTimer:
    def __init__(self, name=None):
        self.name = " '"  + name + "'" if name else ''

    def __enter__(self):
        self.start = timeit.default_timer()

    def __exit__(self, exc_type, exc_value, traceback):
        self.took = (timeit.default_timer() - self.start) * 1000.0
        print('Code block' + self.name + ' took: ' + str(self.took) + ' ms')

然后您可以命名代码块要测量:

with CodeTimer('loop 1'):
   for i in range(100000):
      pass

with CodeTimer('loop 2'):
   for i in range(100000):
      pass

Code block 'loop 1' took: 4.991 ms
Code block 'loop 2' took: 3.666 ms

然后嵌套它们:

with CodeTimer('Outer'):
   for i in range(100000):
      pass

   with CodeTimer('Inner'):
      for i in range(100000):
         pass

   for i in range(100000):
      pass

Code block 'Inner' took: 2.382 ms
Code block 'Outer' took: 10.466 ms

关于timeit.default_timer(),它使用基于OS和Python版本的最佳计时器,见this answer

【讨论】:

    【解决方案4】:

    我总是喜欢以小时、分钟和秒 (%H:%M:%S) 格式检查时间:

    from datetime import datetime
    start = datetime.now()
    # your code
    end = datetime.now()
    time_taken = end - start
    print('Time: ',time_taken) 
    

    输出:

    Time:  0:00:00.000019
    

    【讨论】:

      【解决方案5】:

      将代码放入函数中,然后使用装饰器进行计时是另一种选择。 (Source) 此方法的优点是您只需定义一次计时器,然后为每个函数使用一个简单的附加行

      首先,定义timer装饰器:

      import functools
      import time
      
      def timer(func):
          @functools.wraps(func)
          def wrapper(*args, **kwargs):
              start_time = time.perf_counter()
              value = func(*args, **kwargs)
              end_time = time.perf_counter()
              run_time = end_time - start_time
              print("Finished {} in {} secs".format(repr(func.__name__), round(run_time, 3)))
              return value
      
          return wrapper
      

      然后,在定义函数时使用装饰器:

      @timer
      def doubled_and_add(num):
          res = sum([i*2 for i in range(num)])
          print("Result : {}".format(res))
      

      我们试试吧:

      doubled_and_add(100000)
      doubled_and_add(1000000)
      

      输出:

      Result : 9999900000
      Finished 'doubled_and_add' in 0.0119 secs
      Result : 999999000000
      Finished 'doubled_and_add' in 0.0897 secs
      

      注意:我不知道为什么要使用 time.perf_counter 而不是 time.time。欢迎评论。

      【讨论】:

        【解决方案6】:

        我正在寻找一种如何用最少的代码输出格式化时间的方法,所以这是我的解决方案。无论如何,很多人都在使用 Pandas,所以在某些情况下,这可以节省额外的库导入。

        import pandas as pd
        start = pd.Timestamp.now()
        # code
        print(pd.Timestamp.now()-start)
        

        输出:

        0 days 00:05:32.541600
        

        如果时间精度不是最重要的,我建议使用这个,否则使用time 库:

        %timeit pd.Timestamp.now() 每个循环输出 3.29 µs ± 214 ns

        %timeit time.time() 每个环路输出 154 ns ± 13.3 ns

        【讨论】:

          【解决方案7】:

          你也可以试试这个:

          from time import perf_counter
          
          t0 = perf_counter()
          
          ...
          
          t1 = perf_counter()
          time_taken = t1 - t0
          

          【讨论】:

            【解决方案8】:

            让我在https://stackoverflow.com/a/63665115/7412781 解决方案中添加更多内容。

            • 删除了对functools 的依赖。
            • 已用进程时间占用time.process_time() 而不是time.perf_counter() 的绝对计数器,因为进程可以通过内核进行上下文切换。
            • 还使用原始函数指针打印来获取正确的类名。

            这是装饰器代码。

            import time
            
            def decorator_time_taken(fnc):
                def inner(*args):
                    start = time.process_time()
                    ret = fnc(*args)
                    end = time.process_time()
                    print("{} took {} seconds".format(fnc, round((end - start), 6)))
                    return ret
                return inner
            

            这是使用示例代码。它正在检查 193939 是否为素数。

            class PrimeBrute:
                @decorator_time_taken
                def isPrime(self, a):
                    for i in range(a-2):
                       if a % (i+2) == 0: return False
                    return True
            
            inst = PrimeBrute()
            print(inst.isPrime(193939))
            

            这是输出。

            <function PrimeBrute.isPrime at 0x7fc0c6919ae8> took 0.015789 seconds
            True
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2012-06-29
              • 2013-04-28
              • 2012-06-19
              • 2020-02-06
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多