python程序cpu高通常因密集计算而非卡死,需区分代码计算、阻塞、轮询、gc或扩展拖累;可用top/strace查系统行为,signal traceback看线程堆栈,cprofile定位热点,警惕空循环、gil争抢、高频gc及日志格式化开销。

Python 程序 CPU 使用率高,通常不是“卡死”而是“算得太猛”,定位关键在于区分是 Python 代码本身在密集计算,还是被阻塞、轮询、GC 或底层扩展拖累。下面分几个实用方向快速排查。
看进程和线程实际在做什么
先确认是不是 Python 进程真正在吃 CPU,而不是被系统或其它进程干扰:
- 用 top / htop 查看 PID 和 %CPU,记下高占用的 Python 进程 ID
-
用 pstree -p
或 ps -T -p 看它启了多少线程,哪些线程 CPU 高(Linux 下线程也显示为独立 LWP) -
用 strace -p
-c (短时间运行)看系统调用热点,比如大量 futex(线程争用)、sched_yield(忙等)、read/write(意外频繁 IO)
用 Python 自带工具抓帧分析
无需安装第三方包,直接从运行时入手:
- 用 signal + traceback 快速打印当前所有线程堆栈:向进程发 SIGUSR1(Linux/macOS)会自动打印到 stderr(需启用 faulthandler 或手动注册 handler)
- 用 threading.settrace() 或 sys.settrace() 临时加行级追踪(仅调试,性能开销大,不用于生产)
- 启动时加 -v 参数(python -v script.py)可观察模块导入是否异常重复或卡在某个 C 扩展初始化
用 cProfile 定位计算热点
适合明显“越跑越慢”或持续高 CPU 的脚本/服务:
立即学习“Python免费学习笔记(深入)”;
-
命令行直接 profile:
python -m cProfile -s cumtime your_script.py,重点关注 cumtime 大且 ncalls 高的函数 -
对某段逻辑单独 profile:
import cProfile pr = cProfile.Profile() pr.enable() # your heavy code here pr.disable() pr.print_stats(sort='cumtime')
- 注意:cProfile 对纯 C 扩展(如 numpy 向量化操作、pandas groupby)不深入,看到它们占高比例,说明瓶颈就在这些库内部,需换思路优化(比如改用更高效 API 或减少数据量)
警惕常见“伪高 CPU”陷阱
有些情况看起来 CPU 高,实则是设计或配置问题:
- 无限空循环 + time.sleep(0):sleep(0) 不让出调度权,变成忙等,CPU 拉满。应改用 sleep(0.001) 或用 event.wait() 等待信号
- GIL 争抢严重:多线程做 CPU 密集任务,线程越多反而越慢,CPU 显示高但吞吐不增。该上 multiprocessing 或改用异步 I/O
-
频繁创建对象 + 短生命周期:触发高频 GC,gc.collect() 本身吃 CPU。可用
gc.get_stats()或gc.set_debug(gc.DEBUG_STATS)观察回收频率 -
日志级别太低 + 大量输出:logger.debug() 在没开 debug 时仍执行字符串格式化,消耗 CPU。用 lazy logging(如
logger.debug("value=%r", expensive_func()))避免误伤










