%run将脚本在当前kernel全局命名空间中动态执行,使变量、函数、类直接可用;支持命令行参数传递,但需避免if name == "__main__"包裹和exit()调用,并注意路径与工作目录问题。

%run 会把脚本变量注入当前命名空间
直接执行 %run script.py 后,脚本里定义的所有变量、函数、类都会出现在 notebook 的全局作用域中,后续单元格可以直接调用。这不是“运行完就消失”的子进程,而是代码被动态执行在当前 kernel 里。
常见错误现象:NameError: name 'model' is not defined —— 很可能因为脚本里用了 if __name__ == "__main__": 把关键逻辑包住了,导致变量没被创建;或者脚本抛了异常提前退出,变量根本没来得及定义。
- 确保脚本顶层(非函数/类内部)有实际执行语句,或删掉
if __name__ == "__main__":包裹(调试阶段更安全) - 如果脚本依赖命令行参数,用
%run script.py --epochs 5 --lr 0.01传参,它能被argparse正确解析 - 避免在脚本里写
exit()或sys.exit(),否则会中断整个 notebook 内核
路径问题比想象中更容易出错
%run 默认按当前工作目录(不是 notebook 文件所在目录)查找脚本。很多人卡在这一步:明明文件就在旁边,却报 FileNotFoundError。
使用前务必确认路径:
- 运行
%pwd查看当前工作目录 - 用
%ls或!ls列出当前目录下的文件,确认脚本名拼写和大小写完全一致(Linux/macOS 区分大小写) - 相对路径以
.开头才可靠,比如%run ./utils/preprocess.py;只写preprocess.py可能失败 - 绝对路径更稳妥,但注意 Windows 下要用正斜杠或双反斜杠:
%run C:/project/train.py或%run C:\project\train.py
%run 和 !python 的本质区别
%run 是 IPython 魔法命令,在当前 kernel 上下文中执行;!python script.py 是启动一个全新 Python 进程,两个环境完全隔离。
这意味着:
-
%run能访问 notebook 里已定义的变量(比如你之前加载好的df数据框),!python完全看不到 -
!python中的print输出会显示,但定义的变量不会留在 notebook 里 -
%run支持断点调试(配合%debug),!python不支持 - 如果脚本里修改了全局状态(如
torch.set_grad_enabled(False)),%run会真实影响后续 notebook 执行,!python不会
多次 %run 会导致变量重复定义或意外覆盖
每次 %run 都是重新执行整个脚本——包括所有赋值语句。如果你运行了两次 %run train.py,那么 model 被重建两次,optimizer 也被重置,但旧的模型对象还在内存里没释放。
容易踩的坑:
- 训练循环跑两遍,loss 曲线看起来像“重启训练”,其实是叠加了两次结果
- 反复
%run后显存占用越来越高(尤其 PyTorch/TensorFlow),最终 OOM - 函数被重复定义,但 Python 不报错,只是后一次定义覆盖前一次,可能掩盖逻辑错误
- 建议调试时加一句
print("Running train.py at", __file__)确认是否真被触发;长期运行应改用模块导入 + 显式函数调用
%run,而是搞不清它到底“在哪执行”“变量从哪来”“状态有没有残留”。这些细节不厘清,调试时花三倍时间找问题根源。











