13.13 实现一个计时器¶

问题¶

你想记录程�执行多个任务所花费的时间

解决方案¶

time 模�包�很多函数�执行跟时间有关的函数。 尽管如此,通常我们会在此基础之上构造一个更高级的接��模拟一个计时器。例如:

import time

class Timer:
    def __init__(self, func=time.perf_counter):
        self.elapsed = 0.0
        self._func = func
        self._start = None

    def start(self):
        if self._start is not None:
            raise RuntimeError('Already started')
        self._start = self._func()

    def stop(self):
        if self._start is None:
            raise RuntimeError('Not started')
        end = self._func()
        self.elapsed += end - self._start
        self._start = None

    def reset(self):
        self.elapsed = 0.0

    @property
    def running(self):
        return self._start is not None

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

    def __exit__(self, *args):
        self.stop()

这个类定义了一个�以被用户根�需��动��止和�置的计时器。 它会在 elapsed 属性中记录整个消耗时间。 下�是一个例��演示怎样使用它:

def countdown(n):
    while n > 0:
        n -= 1

# Use 1: Explicit start/stop
t = Timer()
t.start()
countdown(1000000)
t.stop()
print(t.elapsed)

# Use 2: As a context manager
with t:
    countdown(1000000)

print(t.elapsed)

with Timer() as t2:
    countdown(1000000)
print(t2.elapsed)

讨论¶

本节�供了一个简�而实用的类�实现时间记录以�耗时计算。 �时也是对使用with语�以�上下文管�器�议的一个很好的演示。

在计时中�考虑一个底层的时间函数问题。一般�说, 使用 time.time() 或 time.clock() 计算的时间精度因�作系统的��会有所��。 而使用 time.perf_counter() 函数�以确�使用系统上�最精确的计时器。

上述代�中由 Timer 类记录的时间是钟表时间,并包�了所有休眠时间。 如果你�想计算该进程所花费的CPU时间,应该使用 time.process_time() �代替:

t = Timer(time.process_time)
with t:
    countdown(1000000)
print(t.elapsed)

time.perf_counter() 和 time.process_time() 都会返回�数形�的秒数时间。 实际的时间值没有任何�义,为了得到有�义的结果,你得执行两次函数然�计算它们的差值。

更多关于计时和性能分�的例�请�考14.13�节。