timeit比time.time()更准,因其默认禁用垃圾回收、多次执行取最小值,并在纯净上下文中运行,避免系统调度、GC突发、JIT预热等干扰;而手动用time.time()易受环境噪声和优化干扰。

timeit 命令行模式为什么比 time.time() 更准
因为 timeit 默认禁用垃圾回收、多次重复执行取最小值,并在纯净上下文中运行——避免了单次测量受系统调度、GC 突发、JIT 预热等干扰。而手写 time.time() 测量,哪怕加了循环,也容易漏掉 setup 开销或被 Python 解释器优化掉空操作。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 命令行直接测单行表达式:
python -m timeit -s "import math" "math.sqrt(123)",-s是 setup 代码(只执行一次),主体字符串是待测语句 - 测多行语句时,用分号连接,或把代码写进文件后用
-f 文件名 - 避免在命令行中传入含引号嵌套的复杂语句,易出 shell 解析错误;优先用
-s提前导入/定义,主体只留纯执行逻辑
timeit.repeat() 和 timeit.timeit() 的关键区别
timeit.timeit() 返回单次调用结果(默认执行 100 万次,可设 number=);timeit.repeat() 则重复多次调用 timeit.timeit(),返回一个时间列表,适合观察波动性。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 调试性能敏感代码时,优先用
repeat(repeat=5, number=100000),再取min()—— 最小值最能反映“理想路径”耗时 -
number不宜过小(如1),否则系统计时误差占比过高;也不宜盲目设极大值,可能掩盖 cache miss 或内存压力问题 - 若函数有副作用(如修改全局变量、写文件),
repeat每轮都是干净环境,但timeit.timeit()内部多次执行会累积副作用,需注意逻辑是否等价
setup 参数里写 import 和预定义变量的正确姿势
setup 字符串会在每次测试前执行,用于准备环境。但它不是模块作用域,而是 exec 在局部命名空间里,所以变量不会自动泄露到待测语句中——必须显式传入或用 globals 控制。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 简单情况用字符串 setup:
timeit.timeit("x.append(1)", setup="x = []", number=100000) - 复杂对象建议用
globals参数传递已构造好的对象:x = []; timeit.timeit("x.append(1)", globals=locals(), number=100000) - 避免在 setup 字符串里写多行逻辑(如 if/for),可读性差且难调试;改用函数封装后传入
globals - 不要在 setup 中做耗时初始化(如读大文件、建数据库连接),它会被重复执行(除非用
repeat外层控制)
Windows 下 timeit 命令行报错 “ValueError: timer not calibrated” 怎么办
这是老版本 Python(≤3.7)在某些 Windows 系统上高精度计时器未就绪导致的,尤其在 WSL 或远程桌面环境下常见。新版本已修复,但若无法升级,有临时解法。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 升级到 Python 3.8+ 可彻底规避;若必须用旧版,改用
timeit.default_timer手动校准:timeit.timeit(..., timer=timeit.default_timer) - 命令行模式下遇到此错,立即换用 Python 接口方式,绕过命令行启动路径
- 检查是否在虚拟机或容器中运行——部分虚拟化平台对
QueryPerformanceCounter支持不完整,此时timeit会退回到低精度计时器,但报错说明退避失败,需手动指定timer
真正影响精度的往往不是函数选错,而是 setup 是否隔离了干扰项、number 是否让测量落在计时器有效分辨率区间内、以及是否忽略了不同 Python 版本对 timer 底层实现的差异。


















