评分最高的答案可能会给出错误的时间
正如@Mercury 已经指出的那样,@Vlad Bezden 的最佳答案虽然巧妙,但在技术上是不正确的,因为t() 产生的值也可能受到在with 语句之外执行的代码的影响。例如,如果您在 with 语句之后但在 print 语句之前执行 time.sleep(5),那么在 print 语句中调用 t() 将给您大约 6 秒,而不是大约 1 秒。
这可以通过在上下文管理器中执行打印命令来避免,如下所示:
from time import perf_counter
from contextlib import contextmanager
@contextmanager
def catchtime() -> float:
start = perf_counter()
yield lambda: perf_counter() - start
# Note: print is included here to guarantee only time of code inside the CM is measured
print(f'Time: {perf_counter() - start:.3f} seconds')
注意 sleep(5) 如何导致打印不正确的时间:
from time import sleep
with catchtime() as t:
sleep(1)
# >>> "Time: 1.000 seconds"
sleep(5)
print(f'Time: {t():.3f} seconds')
# >>> "Time: 6.000 seconds"
更强大的解决方案(推荐)
此代码类似于@BrenBarn 给出的出色答案,除了它:
- 自动将执行时间打印为格式化字符串(通过删除最后的
print(self.readout) 来删除它)
- 保存格式化的字符串供以后使用 (
self.readout)
- 保存
float 结果供以后使用 (self.time)
from time import perf_counter
class catchtime:
def __enter__(self):
self.time = perf_counter()
return self
def __exit__(self, type, value, traceback):
self.time = perf_counter() - self.time
self.readout = f'Time: {self.time:.3f} seconds'
print(self.readout)
注意中间的sleep(5) 命令如何不再影响打印时间。
from time import sleep
with catchtime() as t:
sleep(1)
# >>> "Time: 1.000 seconds"
sleep(5)
print(t.time)
# >>> 1.000283900000009
sleep(5)
print(t.readout)
# >>> "Time: 1.000 seconds"