Jupyter NotebookやJupyterLabでは、短い記号で便利機能を呼び出せる「マジックコマンド」を使うと、計測やデバッグ、入出力管理がぐっと効率化します。
本記事ではJupyterLabでもそのまま使える主要マジックを、Python初心者の方にも分かりやすい順で、例と出力つきで解説します。
まずは行マジックとセルマジックの基本からはじめましょう。
JupyterLabのマジックコマンド入門
マジックコマンドとは?基本の使い方(% と %%)
マジックコマンドは、IPython(Jupyterの中核)が提供する特別なコマンドで、行頭で使います。
1行で完結するマジックは%
、セル全体に作用するマジックは%%
で始まります。
標準のPython文法ではなく、JupyterやIPythonでのみ有効です。
次の例では、作業フォルダの確認と移動を行います。
# 行マジックの例: 1行で完結
%pwd # 現在の作業ディレクトリを表示

# 行マジックの例: ディレクトリ変更
%cd c:\dev\python\sample # 実際の環境に合わせて読み替えてください
c:\dev\python\sample
# セルマジック:
%time
# このセルの実行時間を1回だけ計測
total = 0
for i in range(1000000):
total += i
total

記号の数(%
か%%
)で作用範囲が変わる点が重要です。
NotebookとJupyterLabでの違いはほぼなし
JupyterLabでも、Jupyter Notebookと同じIPythonカーネル上で動くため、マジックの挙動は基本的に同一です。
UIが異なることで細かな見え方は変わる場合がありますが、コマンドや引数は同じように使えます。
拡張系マジック(例えば%%bash
など)は環境依存のことがあるため、最初は標準マジックから覚えると安心です。
行マジックとセルマジックの違い
行マジックは1行に対して効果を持ち、セルマジックはセル全体を操作します。
よく使うものは次のとおりです。
コマンド | 種類 | 用途 | 代表的なオプション |
---|---|---|---|
%timeit | 行 | 高精度な時間計測(複数回実行) | -n(1回当たり実行回数), -r(リピート回数) |
%%time | セル | セル全体の時間計測(1回) | なし |
%debug | 行 | 直前の例外でポストモーテムデバッグ | なし |
%xmode | 行 | 例外トレースの詳細度切替 | Plain/Context/Verbose |
%prun | 行 | 軽量プロファイル | -s(ソート), -l(表示件数) |
%pip | 行 | カーネルに対して安全にpip実行 | install, list, show |
%conda | 行 | conda環境でのパッケージ管理 | install, list |
%pwd/%cd/%ls | 行 | 作業ディレクトリ操作 | %cd -, %ls -la など |
%autosave | 行 | 自動保存間隔の設定 | 0で無効 |
%run | 行 | .pyスクリプトを実行 | -i(同一名前空間), -n(実行せず解析) |
%%capture | セル | 標準出力・エラーの抑制/保存 | –no-stderr/–no-stdout |
%%writefile | セル | セル内容をファイルへ保存 | -a(追記) |
%matplotlib inline | 行 | 図をノート内に描画 | なし |
%who/%whos | 行 | 変数一覧の可視化 | %who_ls など |
%history | 行 | 実行履歴の表示/検索 | -n(番号), -o(出力), -t(トークン) |
迷ったら「セル全体を丸ごと扱いたいか」で%%
を選ぶと覚えると混乱しにくいです。
計測とデバッグ(%timeit %debug)
実行時間を測る(%timeit)
速度比較に最適なのが%timeit
です。
複数回実行して統計的に安定した測定結果を表示します。
# numpyのインストールは済ませておくこと
# pip install numpy
import numpy as np
# サンプルデータ
arr = np.arange(1_000_000)
# ベクトル化の速さを測る
%timeit arr.sum()
# Pythonループの遅さを体感
def py_sum(a):
s = 0
for x in a:
s += x
return s
%timeit py_sum(arr)
144 μs ± 1.82 μs per loop (mean ± std. dev. of 7 runs, 10,000 loops each)
37.5 ms ± 295 μs per loop (mean ± std. dev. of 7 runs, 10 loops each)
環境により数値は変動しますが、傾向を見るには十分です。
短い処理ほど%timeit
が有利です。
1回の処理時間を見る(%%time)
1回だけの計測でよければ%%time
が簡単です。
I/Oやスリープなど、平均より単発の実測を見たいときに向きます。
import time
%time
# ネットワーク待ちやsleepなど、1回の"壁時計時間"が知りたいケースに
time.sleep(0.2)
sum(i*i for i in range(200_000))
CPU times: total: 0 ns
Wall time: 3.34 μs
エラー後に原因を調べる(%debug)
コードが例外で止まった直後に%debug
を実行すると、その場の変数やスタックを対話的に調べられます。
# まず、あえて例外を発生させます
def div(a, b):
return a / b
div(1, 0) # ZeroDivisionError

# 直後のセルで実行
# ポストモーテムデバッガに入ります
%debug
> <ipython-input-...>(2)div()
1 def div(a, b):
----> 2 return a / b
ipdb> p a
1
ipdb> p b
0
ipdb> u # 1つ上のフレームへ
ipdb> q # 終了

よく使う操作はp 変数名
(値表示)、u/d
(フレーム移動)、q
(終了)です。
実行中のノートブックがブロックされるので、終わったらq
で抜けてください。
例外の見やすさを切り替える(%xmode)
%xmode
で例外の出力詳細度を切り替えられます。
トレースを簡潔にしたい/詳細に見たい場面で役立ちます。
# もっとも簡潔
%xmode Minimal
def f():
1/0
f()
Exception reporting mode: Plain
ZeroDivisionError: division by zero
# 変数など詳細
%xmode Verbose
f()
Exception reporting mode: Verbose
---------------------------------------------------------------------------
ZeroDivisionError: division by zero
Traceback (most recent call last):
File "<ipython-input-...>", line 3, in <module>
f()
File "<ipython-input-...>", line 2, in f
1/0
ZeroDivisionError: division by zero

軽めのプロファイル(%prun)
処理のどこに時間がかかっているか、ざっくり把握するには%prun
が便利です。
def heavy(n=30_000):
# わざと非効率な処理を混ぜる
s = 0
for i in range(n):
s += sum(j for j in range(50)) # 内側で都度sum
return s
# 累積時間で上位5件を表示
%prun -s cumulative -l 5 heavy()
60004 function calls in 0.210 seconds
Ordered by: cumulative time
List reduced from 12 to 5 due to restriction <5>
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.002 0.002 0.210 0.210 <ipython-input-...>:1(heavy)
30000 0.090 0.000 0.200 0.000 <ipython-input-...>:4(<genexpr>)
30000 0.118 0.000 0.118 0.000 {built-in method builtins.sum}
1 0.000 0.000 0.210 0.210 {built-in method builtins.exec}

ボトルネック候補が上位に来るので、まずはその行を改善してみましょう。
環境とパス操作(%pip %cd)
ノート上で安全にインストール(%pip)
Jupyterではカーネルと同じ環境に確実に入れるため、シェルの!pip
ではなく%pip
を使います。
環境ズレによる「インポートできない」事故を防げます。
# カーネルに対して安全にインストール
%pip install -U requests
Collecting requests
...
Successfully installed requests-2.32.3 ...
# インストール確認
import requests
requests.__version__
'2.32.3'
%pipはノートブックの出力にも記録されるので、後から環境構築の手順が追いやすくなります。
conda環境なら(%conda)
condaを使っている場合は%conda
が使えます。
カーネルが指すconda環境にパッケージを導入します。
# conda環境でのインストール例(必要ならバージョン指定)
%conda install -y numpy=1.26
Collecting package metadata (current_repodata.json): done
Solving environment: done
...
Proceed ([y]/n)?
conda環境とカーネルの環境が一致していないと期待通りに入らないことがあります。
カーネル選択を確認してください。
作業フォルダを確認・移動(%pwd %cd %ls)
ファイル操作の前に、現在の作業ディレクトリを把握しておくとトラブルが減ります。
%pwd
'/home/jovyan/work'
%ls -la # ファイル一覧を確認
total 24
drwxr-xr-x 4 jovyan users 4096 Sep 18 09:00 .
drwxr-xr-x 1 jovyan users 4096 Sep 18 08:30 ..
-rw-r--r-- 1 jovyan users 123 Sep 18 08:59 sample.txt
%cd .. # 1つ上へ
%pwd
/home/jovyan
'/home/jovyan'
自動保存の間隔を変える(%autosave)
ノートの自動保存は%autosave
で調整できます。
単位は秒で、0で無効化です。
%autosave 60 # 60秒ごとに自動保存
Autosaving every 60 seconds
%autosave 0 # 無効化
Autosave disabled
共同作業やクラッシュ対策として、自動保存は有効にしておくことをおすすめします。
入出力と表示を便利にするマジック
Pythonスクリプトを実行(%run)
外部の.pyファイルをノートから直接実行できます。
-i
で現在の変数を引き継ぎ、-n
で実行せず構文チェックのみ行います。
%%writefile hello.py
# hello.py: 引数を受け取って表示するだけのサンプル
import sys
def main():
args = sys.argv[1:]
print("Hello", " ".join(args) if args else "World")
if __name__ == "__main__":
main()
Writing hello.py
# 引数付きで実行
%run hello.py Jupyter Lab
Hello Jupyter Lab

# 変数を引き継いで実行(-i)
name = "Notebook"
%run -i hello.py
Hello Notebook
出力を抑える・ログに残す(%%capture)
たくさん出るログを抑えたいときは%%capture
で出力をキャプチャし、必要なときだけ取り出します。
%%capture cap --no-stderr
# 標準出力だけ捕まえる
for i in range(3):
print("line", i)
# 必要なときに取り出す
cap.stdout
'line 0\nline 1\nline 2\n'
# エラー側を抑制しない場合(--no-stderrを付けなければstderrも保存されます)
print(cap.stderr) # 空文字
''

セル内容をファイルに書く(%%writefile)
ノート上で短いスクリプトや設定をそのままファイル化できます。
%%writefile square.py
# square.py: 標準入力で整数Nを受け取り、0..N-1の2乗を出力
import sys
def squares(n):
return [i*i for i in range(n)]
if __name__ == "__main__":
n = int(sys.argv[1]) if len(sys.argv) > 1 else 5
for v in squares(n):
print(v)
Writing square.py
%run square.py 4
0
1
4
9
グラフ表示を安定させる(%matplotlib inline)
%matplotlib inline
で、Matplotlibの図をノート内に埋め込み表示します。
Matplotlibのインストールが必要です。
pip install matplotlib
JupyterLabでは多くの場合既定ですが、明示しておくと安心です。
%matplotlib inline
import matplotlib.pyplot as plt
plt.plot([0, 1, 2], [0, 1, 4], marker="o")
plt.title("Simple Plot")
plt.xlabel("x")
plt.ylabel("y")
plt.grid(True)
plt.show()

インタラクティブにズームしたい場合は%matplotlib widget
も検討してください(JupyterLabでは拡張が必要な場合があります)。
変数一覧を確認(%who %whos)
現在の名前空間にある変数をさっと確認できます。
%who
は名前だけ、%whos
は型やサイズも表示します。
a = 10
b = [1, 2, 3]
import numpy as np
c = np.arange(5)
%who
Interactive namespace is empty.
a b c np

Jupyter Notebookはカーネルを再起動するまで、コードを削除しても過去の変数が保持され続けます。
関係ない変数が残っている場合は、▶▶を押してリセットするようにしましょう。

%whos
Variable Type Data/Info
-------- ---- ---------
a int 10
b list n=3
c ndarray 5: 0 1 2 3 4
np module <module 'numpy' from '...'>

実行履歴を探す(%history)
過去の入力を参照・再利用したいときは%history
が便利です。
番号付きで表示したり、出力も含められます。
%history -n -t -o 1-20
1: import numpy as np
2: arr = np.arange(1_000_000)
3: %timeit arr.sum()
4: def py_sum(a):
s = 0
for x in a:
s += x
return s
5: %timeit py_sum(arr)
...
-nは行番号、-oは出力も含める、-tはトークン化(コピーしやすい形式)です。
まとめ
本記事では、JupyterLabでもそのまま使える厳選マジックコマンド(%timeit
、%%time
、%debug
、%xmode
、%prun
、%pip
、%conda
、%pwd
/%cd
/%ls
、%autosave
、%run
、%%capture
、%%writefile
、%matplotlib inline
、%who
/%whos
、%history
)を、目的別に紹介しました。
まずは時間計測・デバッグ・入出力の3分野を押さえると、日々の試行錯誤が大幅にスムーズになります。
特に%pipで環境をそろえる、%timeitで比較する、%debugで原因を突き止めるの3点を習慣化すると、トラブル対応力が一気に上がります。
慣れてきたら%prunや%%captureなども取り入れ、再現性と読みやすさの高いノート作成を目指してください。