【问题标题】:Measuring elapsed time with the Time module使用时间模块测量经过的时间
【发布时间】:2011-04-06 23:06:57
【问题描述】:

使用 python 中的 Time 模块是否可以测量经过的时间?如果是这样,我该怎么做?

我需要这样做,以便如果光标在小部件中停留了一定时间,就会发生事件。

【问题讨论】:

  • 注:任何使用time.time() 的答案都是不正确的。最简单的例子是系统时间在测量期间发生变化。
  • 我认为,如果光标在小部件上停留一段时间,则关于触发事件的原始问题,docs.python.org/3/library/threading.html 提供了您所需要的一切。多线程和带超时的条件变量可能是解决方案之一。但是,您的情况目前尚不清楚。
  • 没有理由任何人都应该使用time.time() 来测量现代python 中的经过时间(受手动更改、漂移、闰秒等影响)。 This answer below 需要更高,考虑到这个问题现在是 Google 测量经过时间的最佳结果。
  • @NPras 忘记了“现代 python”。使用time.time() 总是不正确的。

标签: python time elapsed


【解决方案1】:
start_time = time.time()
# your code
elapsed_time = time.time() - start_time

您还可以编写简单的装饰器来简化各种函数执行时间的测量:

import time
from functools import wraps

PROF_DATA = {}

def profile(fn):
    @wraps(fn)
    def with_profiling(*args, **kwargs):
        start_time = time.time()

        ret = fn(*args, **kwargs)

        elapsed_time = time.time() - start_time

        if fn.__name__ not in PROF_DATA:
            PROF_DATA[fn.__name__] = [0, []]
        PROF_DATA[fn.__name__][0] += 1
        PROF_DATA[fn.__name__][1].append(elapsed_time)

        return ret

    return with_profiling

def print_prof_data():
    for fname, data in PROF_DATA.items():
        max_time = max(data[1])
        avg_time = sum(data[1]) / len(data[1])
        print "Function %s called %d times. " % (fname, data[0]),
        print 'Execution time max: %.3f, average: %.3f' % (max_time, avg_time)

def clear_prof_data():
    global PROF_DATA
    PROF_DATA = {}

用法:

@profile
def your_function(...):
    ...

您可以同时分析多个功能。然后要打印测量值,只需调用 print_prof_data():

【讨论】:

  • 你也可以看看profilehookspip install profilehooks,以及它的homepage here
  • 请注意,从 Python 3.3 开始,在测量超时或持续时间时,可能应该使用 time.monotonic() 而不是 time.time()docs.python.org/3/library/time.html#time.monotonic
  • 值得在此处添加/注意,经过时间的度量单位将是秒。
  • @EricKramer 谢谢!我非常讨厌,在没有定义测量单位的情况下解释测量。作为一个第一次涉足 Python 的 .NET 人员,我不由自主地想到了“毫秒”。
  • 如果(例如)系统时钟发生更改,则不起作用,并且可能没有亚秒级分辨率。正确答案:stackoverflow.com/a/47637891/476716
【解决方案2】:

time.time() 将完成这项工作。

import time

start = time.time()
# run your code
end = time.time()

elapsed = end - start

您可能想查看this 问题,但我认为没有必要。

【讨论】:

  • 是的,时间以秒为单位
  • 你应该把 start 改成 start_time。
  • time.time() 是个坏主意,因为系统时钟可以重置,这会让你回到过去。 time.monotonic() 负责这个(单调 = 它只会向前)。 time.perf_counter() 也是单调的,但精度更高,因此推荐用于挂钟时间。
【解决方案3】:

对于想要更好格式的用户,

import time
start_time = time.time()
# your script
elapsed_time = time.time() - start_time
time.strftime("%H:%M:%S", time.gmtime(elapsed_time))

将打印出来,持续 2 秒:

'00:00:02'

7 分钟一秒:

'00:07:01'

请注意,gmtime 的最小时间单位是秒。如果您需要微秒,请考虑以下事项:

import datetime
start = datetime.datetime.now()
# some code
end = datetime.datetime.now()
elapsed = end - start
print(elapsed)
# or
print(elapsed.seconds,":",elapsed.microseconds) 

strftime documentation

【讨论】:

  • 感谢您的回答,这对我很有启发。我将使用e = time.time() - start_time ; print("%02d:%02d:%02d" % (e // 3600, (e % 3600 // 60), (e % 60 // 1))),它的产量几乎相同,并且涵盖了超过 24 小时的情况。
  • @Tora 您可能需要检查 "{}".format() 而不是 %02d 以解决未来的兼容性问题。
  • 谢谢!现在我已经习惯了新的。 '{:02d}:{:02d}:{:02d}'.format(e // 3600, (e % 3600 // 60), e % 60)
  • 你能像其他答案一样使用time.monotonic()吗?
  • 如果持续时间大于 1 天,elapsed.seconds 将不正确。您希望elapsed.total_seconds() 具有弹性
【解决方案4】:

为了获得最佳的经过时间度量(自 Python 3.3 起),请使用 time.perf_counter()

返回性能计数器的值(以秒为单位),即具有最高可用分辨率的时钟以测量短持续时间。它确实包括睡眠期间经过的时间,并且是系统范围的。返回值的参考点是未定义的,因此只有连续调用的结果之间的差异才有效。

对于以小时/天为单位的测量,您不关心亚秒级分辨率,因此请改用time.monotonic()

返回单调时钟的值(以秒为单位),即不能倒退的时钟。时钟不受系统时钟更新的影响。返回值的参考点是未定义的,因此只有连续调用的结果之间的差异才有效。

在许多实现中,这些实际上可能是同一件事。

在 3.3 之前,您会被 time.clock() 卡住。

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

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


Python 3.7 更新

Python 3.7 中的新功能是 PEP 564 -- 添加具有纳秒分辨率的新时间函数。

使用这些可以进一步消除舍入和浮点错误,尤其是在您测量非常短的周期,或者您的应用程序(或 Windows 机器)长时间运行时。

大约 100 天后,perf_counter() 的分辨率开始失效。因此,例如在正常运行一年后,它可以测量的最短间隔(大于 0)将比开始时更大。


Python 3.8 更新

time.clock 现在不见了。

【讨论】:

  • “在许多实现中,这些实际上可能是同一回事。” 确实,在我的 Linux Mint PC 上,time.monotonic() 和 time.perf_counter() 似乎返回相同的值。
【解决方案5】:

更长的时间。

import time
start_time = time.time()
...
e = int(time.time() - start_time)
print('{:02d}:{:02d}:{:02d}'.format(e // 3600, (e % 3600 // 60), e % 60))

会打印

00:03:15

如果超过 24 小时

25:33:57

这受到了 Rutger Hofste 的回答的启发。谢谢罗格!

【讨论】:

    【解决方案6】:

    您需要导入时间,然后使用 time.time() 方法知道当前时间。

    import time
    
    start_time=time.time() #taking current time as starting time
    
    #here your code
    
    elapsed_time=time.time()-start_time #again taking current time - starting time 
    

    【讨论】:

      【解决方案7】:

      在编程中,测量时间的方法主要有两种,结果各不相同:

      >>> print(time.process_time()); time.sleep(10); print(time.process_time())
      0.11751394000000001
      0.11764988400000001  # took  0 seconds and a bit
      >>> print(time.perf_counter()); time.sleep(10); print(time.perf_counter())
      3972.465770326
      3982.468109075       # took 10 seconds and a bit
      
      • 处理器时间:这是该特定进程在 CPU 上主动执行所花费的时间。睡眠、等待网络请求或仅执行其他进程的时间不会对此产生影响。

        • 使用time.process_time()
      • 挂钟时间:这是指“挂在墙上的时钟”已经过去了多少时间,即超出实时时间。

        • 使用time.perf_counter()

          • time.time() 也可以测量挂钟时间,但可以重置,所以你可以回到过去
          • time.monotonic() 无法重置(单调 = 仅向前)但精度低于 time.perf_counter()

      【讨论】:

        【解决方案8】:

        另一个计时的好方法是使用 with python 结构。

        with 结构会自动调用 __enter____exit__ 方法,这正是我们需要什么来计时。

        让我们创建一个 Timer 类。

        from time import time
        
        class Timer():
            def __init__(self, message):
                self.message = message
            def __enter__(self):
                self.start = time()
                return None  # could return anything, to be used like this: with Timer("Message") as value:
            def __exit__(self, type, value, traceback):
                elapsed_time = (time() - self.start) * 1000
                print(self.message.format(elapsed_time))
        

        然后,可以像这样使用 Timer 类:

        with Timer("Elapsed time to compute some prime numbers: {}ms"):
            primes = []
            for x in range(2, 500):
                if not any(x % p == 0 for p in primes):
                    primes.append(x)
            print("Primes: {}".format(primes))
        

        结果如下:

        质数:[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71、73、79、83、89、97、101、103、107、109、113、127、131、137、139、149、151、 157、163、167、173、179、181、191、193、197、199、211、223、227、229、233、239、 241、251、257、263、269、271、277、281、283、293、307、311、313、317、331、337、 347、349、353、359、367、373、379、383、389、397、401、409、419、421、431、433、 439、443、449、457、461、463、467、479、487、491、499]

        计算一些素数所用的时间:5.01704216003418ms

        【讨论】:

          【解决方案9】:

          Vadim Shender 的反应很棒。您还可以使用更简单的装饰器,如下所示:

          import datetime
          def calc_timing(original_function):                            
              def new_function(*args,**kwargs):                        
                  start = datetime.datetime.now()                     
                  x = original_function(*args,**kwargs)                
                  elapsed = datetime.datetime.now()                      
                  print("Elapsed Time = {0}".format(elapsed-start))     
                  return x                                             
              return new_function()  
          
          @calc_timing
          def a_func(*variables):
              print("do something big!")
          

          【讨论】:

            【解决方案10】:

            这是对 Vadim Shender 的智能代码的更新,带有表格输出:

            import collections
            import time
            from functools import wraps
            
            PROF_DATA = collections.defaultdict(list)
            
            def profile(fn):
                @wraps(fn)
                def with_profiling(*args, **kwargs):
                    start_time = time.time()
                    ret = fn(*args, **kwargs)
                    elapsed_time = time.time() - start_time
                    PROF_DATA[fn.__name__].append(elapsed_time)
                    return ret
                return with_profiling
            
            Metrics = collections.namedtuple("Metrics", "sum_time num_calls min_time max_time avg_time fname")
            
            def print_profile_data():
                results = []
                for fname, elapsed_times in PROF_DATA.items():
                    num_calls = len(elapsed_times)
                    min_time = min(elapsed_times)
                    max_time = max(elapsed_times)
                    sum_time = sum(elapsed_times)
                    avg_time = sum_time / num_calls
                    metrics = Metrics(sum_time, num_calls, min_time, max_time, avg_time, fname)
                    results.append(metrics)
                total_time = sum([m.sum_time for m in results])
                print("\t".join(["Percent", "Sum", "Calls", "Min", "Max", "Mean", "Function"]))
                for m in sorted(results, reverse=True):
                    print("%.1f\t%.3f\t%d\t%.3f\t%.3f\t%.3f\t%s" % (100 * m.sum_time / total_time, m.sum_time, m.num_calls, m.min_time, m.max_time, m.avg_time, m.fname))
                print("%.3f Total Time" % total_time)
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2016-10-07
              • 2017-07-13
              • 2021-03-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-05-19
              • 1970-01-01
              相关资源
              最近更新 更多