JupyterLab使用%lprun行性能分析时触发Name not defined错误
JupyterLab中
%lprun运行抛出name 'x' is not defined错误的原因与解决方案 问题触发原因
这个问题是依赖版本升级后执行上下文逻辑变更导致的,和代码本身逻辑无关:
- 早期Jupyter Notebook配套的低版本
line_profiler、IPython内核中,%lprun行魔法会自动捕获外层自定义函数的局部作用域,因此写在函数内部也能读取到x、y这类局部变量 - 升级到JupyterLab配套的
line_profiler 3.5+、IPython 8.x版本后,行魔法的执行上下文被收紧,默认仅能读取全局命名空间的变量,无法自动访问自定义函数内的局部变量,因此会抛出变量未定义的错误。
问题复现代码
# 单独单元格运行加载扩展 %reload_ext line_profiler def fn1(x,y): z=x+y return z def fn2(u,v): x=u+v y= u*v # 该写法在新版本依赖下失效 %lprun -f fn1 z=fn1(x,y) fn2(100,200)
可行解决方法
- 方法1:将
%lprun调用移到全局作用域(最推荐,兼容性最好)
不要把行魔法写在自定义函数内部,把需要分析的逻辑和%lprun调用放到单元格的全局层级执行,示例:%reload_ext line_profiler def fn1(x,y): z=x+y return z def fn2(u,v): x=u+v y= u*v return fn1(x,y) # 全局作用域调用分析 %lprun -f fn1 res = fn2(100,200) - 方法2:函数内部显式调用
LineProfiler对象(适配必须在函数内做分析的场景)
跳过魔法命令,直接导入line_profiler的原生类手动执行分析,显式传入当前作用域的变量,示例:%reload_ext line_profiler def fn1(x,y): z=x+y return z def fn2(u,v): x=u+v y= u*v from line_profiler import LineProfiler lp = LineProfiler() # 绑定要分析的函数 lp.add_function(fn1) z = lp(fn1)(x,y) # 打印分析结果 lp.print_stats() return z fn2(100,200) - 方法3:降级依赖版本(不推荐)
将line_profiler降级到3.4.0、IPython降级到7.x系列版本,即可恢复旧版本中函数内写%lprun的用法,但降级会破坏JupyterLab新版本的部分功能兼容性,存在其他依赖冲突风险。
注意:所有
%开头的IPython行魔法默认都以全局命名空间作为执行上下文,除了少数专门做了局部作用域适配的魔法,其余魔法命令写在自定义函数内部都可能出现变量访问错误,这是IPython的固有执行机制决定的。
内容的提问来源于stack exchange,提问作者knowledge_seeker
相关产品推荐
相关产品推荐

