Python编程实战:从 timeit 到 cProfile,一次搞懂代码为什么慢

当你写 Python 写得越来越多,就会突然发现------有些代码运行得慢得离谱,但自己却不知道"慢"到底发生在哪一步。 这时你就需要真正的性能分析工具上场了,而不是继续凭感觉优化。

本篇我们一起搞定两大核心工具:

  • timeit:测函数执行时间
  • cProfile:分析整段程序的性能瓶颈

最后我会给你一个完整的优化示例,让性能提升看得见。


1. 为什么代码会慢?

Python 是解释型语言,灵活但速度不是强项。 代码变慢常见原因包括:

  • 不必要的循环
  • 低效的数据结构
  • 重复计算
  • IO 阻塞(文件/网络)
  • 第三方库使用不当

搞清楚瓶颈在哪里,是所有优化的起点。


2. 用 timeit 测局部性能:谁更快,一测便知

timeit 是个轻量级工具,非常适合比较小片段代码的速度。

例如:列表推导 vs for 循环,谁更快?

示例:用 timeit 测试代码片段

python 复制代码
import timeit

# 列表推导
expr1 = "[i*i for i in range(1000)]"
# 普通循环
expr2 = """
result = []
for i in range(1000):
    result.append(i*i)
"""

t1 = timeit.timeit(expr1, number=10000)
t2 = timeit.timeit(expr2, number=10000)

print("列表推导:", t1)
print("for 循环:", t2)

输出示例(依据电脑不同会变化)

makefile 复制代码
列表推导: 0.32
for 循环: 0.45

你一下就看出列表推导更快。 这就是 timeit 的价值: 用数字说话,而不是猜测。


3. 用 cProfile 查整段程序的瓶颈:慢在哪,一清二楚

当你不确定慢的是哪部分时,就用 cProfile

它会告诉你:

  • 每个函数调用几次
  • 每次耗时多久
  • 总耗时
  • 占比情况

超级适合分析中大型脚本。


示例:一个"看似没问题但其实很慢"的函数

python 复制代码
def slow_func():
    total = 0
    for i in range(10000):
        for j in range(10000):
            total += i + j
    return total

现在我们用 cProfile 分析:

python 复制代码
import cProfile

cProfile.run("slow_func()")

你会看到类似:

bash 复制代码
200000000 function calls in 3.821 seconds
ncalls  tottime  percall  cumtime  function
1       3.821    3.821    3.821    slow_func

一下就能看出: 问题全在 slow_func 本身,特别是双层循环。


4. 更清晰的结果?用 pstats 或 SnakeViz 可视化

默认输出较难读,你可以这样格式化:

python 复制代码
import cProfile
import pstats

with cProfile.Profile() as pr:
    slow_func()

stats = pstats.Stats(pr)
stats.sort_stats(pstats.SortKey.TIME)
stats.print_stats()

如果你想可视化展示(像瀑布图一样),可以安装 SnakeViz:

lua 复制代码
pip install snakeviz
snakeviz output.prof

非常适合技术分享或团队协作。


5. 实战:一步步从 2.5s 优化到 0.01s

假设我们有一个脚本统计每行是否包含某些关键词:

python 复制代码
def check_keywords(lines, keywords):
    result = []
    for line in lines:
        for k in keywords:
            if k in line:
                result.append((line, k))
    return result

分析:

  • 双层循环
  • 多次重复"是否包含"检查
  • 关键词过多时会超级慢

现在,我们用 cProfile 跑一下:

python 复制代码
cProfile.run("check_keywords(lines, keywords)")

你会看到绝大多数时间花在:

markdown 复制代码
str.__contains__

因为你对每个 line、每个 keyword 都在做 in 操作。


优化方案:把关键词变成正则 OR 模式

python 复制代码
import re

def fast_check_keywords(lines, keywords):
    pattern = re.compile("|".join(map(re.escape, keywords)))
    result = []
    for line in lines:
        m = pattern.search(line)
        if m:
            result.append((line, m.group()))
    return result

再跑性能测试

从 2.5 秒 → 0.01 秒 优化效果巨大。


6. 性能优化原则:永远遵循这三条

① 优化前先量化

不要凭直觉优化 永远先用 timeit / cProfile 查看瓶颈。

② 优化数据结构

例如:

  • 列表 → 集合(O(1) 查找)
  • 循环计算 → 内建函数/向量化

③ 避免重复计算

缓存、预编译、提前转换格式,都能救命。


7. 总结

性能优化是 Python 开发者进阶的必备技能。 timeit 解决"小范围速度比较", cProfile 负责"全局瓶颈定位"。

只要你掌握:

  • 定位
  • 调试
  • 替换更快的数据结构/算法

你就可以让脚本从"能跑"变成"飞快"。


相关推荐
程序员爱钓鱼1 小时前
Python编程实战:用好 pdb 和 logging,程序再也不黑箱运行了
后端·python·trae
Mintopia1 小时前
⚡Trae Solo Coding 的效率法则
前端·人工智能·trae
2501_941111511 小时前
Python多线程与多进程:如何选择?(GIL全局解释器锁详解)
jvm·数据库·python
JaguarJack2 小时前
进阶学习 PHP 中的二进制和位运算
后端·php
Moment2 小时前
专为 LLM 设计的数据格式 TOON,可节省 60% Token
前端·javascript·后端
2501_941111332 小时前
使用Python处理计算机图形学(PIL/Pillow)
jvm·数据库·python
青梅主码2 小时前
麦肯锡联合QuantumBlack最新发布《2025年人工智能的现状:智能体、创新和转型》报告:32% 的企业预计会继续裁员
前端·人工智能·后端
William_cl2 小时前
【ASP.NET进阶】Controller 层基础:从 MVC 5 到 Core,继承的奥秘与避坑指南
后端·asp.net·mvc
小小测试开发2 小时前
Python数据科学与图像处理利器组合:Prophet、Arch、Scikit-image、Pillow-heif用法全解析
图像处理·python·pillow