python程序变慢需从执行路径、资源消耗、代码结构三方面排查,优先定位最耗时和最频繁部分;用cprofile和pstats分析热点函数,关注tottime高的函数;检查i/o瓶颈;避免隐式低效操作;用tracemalloc监控内存压力。

Python 程序变慢,往往不是单点问题,而是多个环节叠加导致的。排查时需从执行路径、资源消耗、代码结构三方面入手,优先定位“最耗时”和“最频繁”部分,再针对性优化。
用 cProfile 快速定位热点函数
cProfile 是 Python 自带的确定性分析器,能精确统计每个函数的调用次数、总耗时和内部耗时。它不干扰逻辑,适合生产环境轻量采样。
- 在脚本入口处添加:import cProfile; cProfile.run('main()', 'profile_stats')(假设主逻辑在 main() 中)
- 用 pstats 解析结果:python -m pstats profile_stats,然后输入 sort cumulative 查看累计耗时最高的函数
- 重点关注 tottime(函数自身耗时,不含子调用)高的函数——它们是优化的首要目标
检查 I/O 和外部依赖是否成为瓶颈
磁盘读写、网络请求、数据库查询等 I/O 操作常以毫秒级延迟拖慢整体响应,而 CPU 时间统计中几乎不体现。
- 用 strace -e trace=write,read,connect,sendto,recvfrom python script.py(Linux)观察系统调用等待行为
- 对 HTTP 请求,启用 requests 的日志:logging.basicConfig(level=logging.DEBUG),查看连接建立、SSL 握手、响应等待时间
- 数据库操作加简单计时:start = time.time(); cursor.execute(...); print(f"Query took {time.time()-start:.3f}s")
警惕隐式低效操作:循环、字符串拼接与重复计算
语法看似简洁,但某些写法在底层触发大量对象创建或线性扫描,尤其在高频循环中会被放大。
立即学习“Python免费学习笔记(深入)”;
- 避免在循环中用 += 拼接字符串——改用 list.append() + ''.join()
- 不要在 for 循环条件里反复调用 len() 或 dict.keys();提前赋值复用
- 检查是否有重复计算:比如在循环内反复解析同一 JSON、反复正则 compile、反复打开同一文件
内存压力引发的间接性能下降
内存占用过高会触发频繁 GC,甚至导致操作系统交换(swap),使程序整体卡顿,但 CPU 使用率可能并不高。
- 用 tracemalloc 追踪内存分配源头:tracemalloc.start(); ... ; snapshot = tracemalloc.take_snapshot()
- 对比前后快照,找出增长最多的分配位置:top_stats = snapshot.statistics('lineno')
- 留意大对象缓存(如全局 list/dict 存大量数据)、未关闭的文件句柄、闭包意外持有大数据引用










