什么是魔法命令
魔法命令(Magic Commands)是 IPython 内核提供的特殊命令,以 % 或 %% 开头,提供了许多普通 Python 代码无法直接完成的功能。
行魔法(Line Magic):%
只对当前行生效。
%timeit sum(range(10000)) %pwd %ls %who
单元格魔法(Cell Magic):%%
对整个单元格生效,必须在第一行。
%%time
for i in range(10**6):
pass
性能测试:%timeit 和 %%time
性能测试是 Jupyter 最常用的魔法命令场景:
%timeit 对 sum(range(10000)) 进行性能测试,输出平均时间和标准差(7次运行,每次10000循环)
# %timeit — 自动运行多次取平均 %timeit sum(range(10000)) 63.4 µs ± 425 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each) # 可以指定运行次数和循环次数 %timeit -n 100 -r 5 sum(range(10000)) # %%time — 整个单元格的一次性计时 %%time data = list(range(10**7)) total = sum(data) CPU times: user 212 ms, sys: 45 ms, total: 257 ms Wall time: 258 ms
- %timeit vs %%time
%timeit自动多次执行取均值,适合微基准测试(microsecond 级别);%%time只执行一次,适合较慢的操作(second 级别)。
文件系统操作
# 显示当前工作目录 %pwd '/private/tmp/jupyter_demo' # 列出文件(等同于 ls 命令) %ls demo.ipynb data.csv images/ # 切换目录 %cd /Users/mi/projects # 创建目录 %mkdir new_folder
数据可视化:%matplotlib
这是数据科学中最重要的魔法命令之一:
# 让图表内联显示在 Notebook 中(推荐) %matplotlib inline # 交互式图表(可以缩放、平移) %matplotlib widget # 在外部窗口显示(传统方式) %matplotlib qt # 之后所有 matplotlib 图表都会内联显示 import matplotlib.pyplot as plt import numpy as np x = np.linspace(0, 2*np.pi, 100) plt.plot(x, np.sin(x)) plt.title('y = sin(x)') plt.show() # 图表直接显示在输出区域
TIP
%matplotlib inline 通常放在 Notebook 的第一个单元格,和 import 语句一起。一旦设置,整个会话都有效,无需每个单元格都加。
运行外部脚本:%run
# 运行外部 Python 脚本,脚本中的变量进入当前命名空间 %run analysis.py # 运行并传入参数 %run script.py arg1 arg2 # 运行另一个 Notebook(作为普通 Python 脚本执行) %run helper_notebook.ipynb
写入文件:%%writefile
%%writefile hello.py # 这个单元格的内容会被写入 hello.py 文件 def greet(name): return f"Hello, {name}!" if __name__ == "__main__": print(greet("World")) Writing hello.py
Shell 命令:! 前缀
除了魔法命令,还可以用 ! 前缀直接运行 Shell 命令:
# 直接运行 Shell 命令 !pip install seaborn !git status !cat data.csv | head -5 # 捕获 Shell 命令输出到 Python 变量 files = !ls *.csv print(files) # 返回字符串列表
变量查看
# 查看当前所有变量 %who x y data model # 查看变量及其类型 %whos Variable Type Data/Info -----------|---------|--------- x int 42 y float 3.14 data list n=100 # 删除变量 %reset_selective x # 删除变量 x %reset # 删除所有变量(会确认提示)
查看历史与保存
# 查看执行历史 %history %history -n 1-10 # 第 1-10 次执行的代码 # 保存到文件 %save my_session.py 1-10 # 将第 1-10 次执行的代码保存 # 查看所有可用的魔法命令 %lsmagic
常用魔法命令汇总
| 命令 | 说明 |
|---|---|
%timeit | 自动多次运行,性能基准测试 |
%%time | 单元格一次性计时 |
%matplotlib inline | 设置图表内联显示 |
%run file.py | 运行外部脚本 |
%%writefile f.py | 将单元格内容写入文件 |
%pwd / %cd / %ls | 文件系统操作 |
%who / %whos | 查看当前变量 |
%reset | 清除所有变量 |
%history | 查看执行历史 |
%load file.py | 将文件内容加载到单元格 |
%%html | 将单元格内容渲染为 HTML |
%%bash | 将单元格内容作为 Bash 执行 |
魔法命令的工作原理
IPython 扩展机制
魔法命令是 IPython 内核的扩展功能,不是 Python 语言的一部分。IPython 在执行代码前先检查行首是否有 % 或 %% 前缀,如果有则将该行交给对应的魔法命令处理器,而不是 Python 解释器。这意味着魔法命令只在 Jupyter/IPython 环境中有效——将 Notebook 导出为 .py 脚本后,魔法命令行会失效(导出时会带注释标记)。
%timeit 的统计方法
%timeit 通过多次执行代码(默认 7 轮,每轮执行足够多次使总时间约 0.2s)取最快的 3 次的平均值,以消除系统负载波动的影响。输出格式:"X µs ± Y µs per loop (mean ± std. dev. of 7 runs, Z loops each)"。这比 %%time(单次执行)更精确,适用于微基准测试(microsecond 到 millisecond 级别的操作)。对于耗时超过 1 秒的操作,%timeit 和 %%time 结果差异不大。
Shell 命令的变量传递
Shell 命令(! 前缀)可以通过 $variable 语法引用 Python 变量,也可以将输出赋值给 Python 变量:output = !ls -la(返回输出行组成的列表)。注意:! Shell 命令在子进程中执行,!cd /path 不会改变 Python 进程的当前目录(子进程的目录变化不影响父进程)。需要改变 Notebook 的工作目录时,必须使用 %cd /path 魔法命令。
%load_ext autoreload:开发自己的 Python 包时必备
修改了自己的 Python 包代码后,默认情况下 Kernel 不会重新加载已导入的模块。每次修改都要重启 Kernel 非常低效。autoreload 扩展解决了这个问题:
%load_ext autoreload %autoreload 2 # 模式 2:每次执行 cell 前,自动重载所有修改过的模块
这样修改包代码后,只需重新运行相关的 cell,无需重启 Kernel。
自定义魔法命令
你可以创建自己的魔法命令来封装常用操作:
from IPython.core.magic import register_line_magic, register_cell_magic
# 定义行魔法命令
@register_line_magic
def hello(line):
"""自定义魔法命令:%hello name"""
return f"Hello, {line}!"
# 使用:%hello World → 输出 "Hello, World!"
# 定义单元格魔法命令
@register_cell_magic
def count_lines(line, cell):
"""统计单元格代码行数"""
lines = cell.strip().split('\n')
return f"This cell has {len(lines)} lines"
# 使用:%%count_lines 后跟多行代码
魔法命令的性能陷阱
魔法命令虽然方便,但有性能开销。%timeit 本身会多次执行代码,不适合有副作用的操作(如写文件、发网络请求)。!shell_command 每次都启动新的子进程,频繁调用会很慢——如果需要多次执行 Shell 命令,考虑用 subprocess 模块或 %%bash 单元格魔法一次性执行多条命令。
本章小结
本章核心要点
- % vs %%:% 是行魔法(作用于当前行的参数);%% 是单元格魔法(整个单元格的内容都是参数,且必须是单元格的第一行)。常见混淆:用 %time 给整个单元格计时(应该用 %%time)。
- 性能测量选择:%timeit 精确基准测试(多轮统计,消除波动,适合 µs-ms 级操作);%%time 快速估算(单次运行,适合耗时较长的操作,看一眼够了)。
- %matplotlib inline:在 Notebook 中显示图表的核心设置,经典 Notebook 需手动在开头执行;JupyterLab 4.x 已默认启用,也可用 %matplotlib widget 显示交互式图表。
- ! vs %cd:!cmd 在子进程中执行 Shell 命令,对当前目录无影响;%cd path 改变 Notebook 的当前工作目录(持久有效)。其他文件系统操作(%ls、%pwd)同理要用 % 版本。
- 变量管理魔法:%who/%whos 查看现有变量;%reset_selective var 精确删除;%history -n 查看执行历史;%save file.py 1-10 导出历史为脚本。%load_ext autoreload + %autoreload 2 是开�� Python 包时的必备组合。