line_profiler需pip安装且用kernprof命令行分析,仅追踪@profile装饰的函数;报告中% Time超30%需警惕性能瓶颈;Jupyter中需先%load_ext line_profiler再用%lprun。

line_profiler 安装和基本命令行用法
line_profiler 不是 Python 内置模块,必须单独安装,且不能直接用 python -m line_profiler 运行(会报错 No module named line_profiler.__main__)。
正确安装方式是:
- 用 pip 安装:
pip install line_profiler - 安装后需手动注册 IPython 魔法命令(如果要用在 Jupyter 里):
pip install line_profiler && python -m line_profiler --version确认可用,再在 IPython/Jupyter 中运行%load_ext line_profiler - 命令行分析脚本的典型流程:
kernprof -l -v script.py,其中-l表示启用 line-by-line profiling,-v表示执行完立即打印结果
注意:kernprof 是 line_profiler 提供的命令行入口,不是系统自带命令——装完才会有。如果提示 command not found: kernprof,说明安装未生效或 shell 缓存未刷新(可试 hash -d kernprof 或重启终端)。
@profile 装饰器必须显式添加且仅对函数有效
line_profiler 不会自动分析所有代码,它只追踪被 @profile 标记的函数。没有这个装饰器,哪怕函数被调用,也不会出现在报告中。
立即学习“Python免费学习笔记(深入)”;
常见错误写法:
def my_func():
x = [i**2 for i in range(100000)]
return sum(x)
这段代码加了 kernprof -l -v script.py 也不会出耗时数据。必须改成:
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
@profile
def my_func():
x = [i**2 for i in range(100000)]
return sum(x)
几点关键细节:
-
@profile是全局可用的装饰器,无需 import(但需确保已安装 line_profiler) - 只能加在函数定义上,不能加在类、if 块、循环内部或 lambda 上
- 如果函数在模块顶层被调用,必须确保该函数被实际执行(比如加
if __name__ == "__main__": my_func()),否则kernprof不会触发采集 - 不支持嵌套作用域内的局部函数(即 def 在另一个 def 里面),除非外层函数也加了
@profile并调用了它
输出报告中各列含义和性能判断依据
执行 kernprof -l -v script.py 后,你会看到类似这样的表格:
Line # Hits Time Per Hit % Time Line Contents
==============================================================
5 @profile
6 def my_func():
7 1 249 249.0 2.1 x = [i**2 for i in range(100000)]
8 1 11521 11521.0 97.9 return sum(x)
重点看这四列:
-
Hits:该行被执行次数(对循环内代码尤其关键) -
Time:该行累计耗时(单位是 CPU clock ticks,非绝对秒数,但比例可靠) -
Per Hit:平均每次执行耗时,用于识别单次开销大的操作(如磁盘读、正则编译) -
% Time:占整个被 profile 函数总耗时的百分比,快速定位瓶颈位置
注意:Time 值本身不可跨机器/跨运行比较;但同一份报告里的 % Time 和相对大小完全可信。如果某行 % Time 超过 30%,且逻辑简单(比如只是赋值或索引),就要怀疑是不是数据规模或算法出了问题。
Jupyter 中使用 %lprun 魔法命令的限制条件
在 Jupyter 里用 %lprun -f func_name func_name(args) 更方便,但有硬性前提:
- 必须先执行
%load_ext line_profiler -
func_name必须已在当前 kernel 中定义(不能是刚 copy-paste 进来的、未执行的 cell) - 不能对内置函数(如
len、print)或 C 扩展函数(如numpy.array构造)做行级分析——这些只会显示为 1 行 “function call”,Time 归到调用点,无法下钻 - 如果函数依赖外部变量(比如闭包或 global 变量),确保它们在调用前已存在且值稳定,否则可能因重复计算或异常中断导致报告不全
一个容易忽略的问题:%lprun 默认只分析指定函数及其直接调用的、也打了 @profile 的子函数。如果你没给子函数加装饰器,那部分代码就“隐身”了——看起来像某一行突然耗时飙升,其实是跳进未标记函数里执行了很久。

















