閉じる

JupyterLabでも使えるマジック一覧 (%timeit %debug) 便利ワザ集

Jupyter NotebookやJupyterLabでは、短い記号で便利機能を呼び出せる「マジックコマンド」を使うと、計測やデバッグ、入出力管理がぐっと効率化します。

本記事ではJupyterLabでもそのまま使える主要マジックを、Python初心者の方にも分かりやすい順で、例と出力つきで解説します。

まずは行マジックとセルマジックの基本からはじめましょう。

JupyterLabのマジックコマンド入門

マジックコマンドとは?基本の使い方(% と %%)

マジックコマンドは、IPython(Jupyterの中核)が提供する特別なコマンドで、行頭で使います。

1行で完結するマジックは%、セル全体に作用するマジックは%%で始まります。

標準のPython文法ではなく、JupyterやIPythonでのみ有効です。

次の例では、作業フォルダの確認と移動を行います。

Python
# 行マジックの例: 1行で完結
%pwd  # 現在の作業ディレクトリを表示
Python
# 行マジックの例: ディレクトリ変更
%cd c:\dev\python\sample  # 実際の環境に合わせて読み替えてください
実行結果
c:\dev\python\sample
Python
# セルマジック:
%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
%condaconda環境でのパッケージ管理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です。

複数回実行して統計的に安定した測定結果を表示します。

Python
# 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やスリープなど、平均より単発の実測を見たいときに向きます。

Python
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を実行すると、その場の変数やスタックを対話的に調べられます。

Python
# まず、あえて例外を発生させます
def div(a, b):
    return a / b

div(1, 0)  # ZeroDivisionError
Python
# 直後のセルで実行
# ポストモーテムデバッガに入ります
%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で例外の出力詳細度を切り替えられます。

トレースを簡潔にしたい/詳細に見たい場面で役立ちます。

Python
# もっとも簡潔
%xmode Minimal
def f():
    1/0
f()
実行結果
Exception reporting mode: Plain
ZeroDivisionError: division by zero
Python
# 変数など詳細
%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が便利です。

Python
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を使います。

環境ズレによる「インポートできない」事故を防げます

Python
# カーネルに対して安全にインストール
%pip install -U requests
実行結果
Collecting requests
...
Successfully installed requests-2.32.3 ...
Python
# インストール確認
import requests
requests.__version__
実行結果
'2.32.3'

%pipはノートブックの出力にも記録されるので、後から環境構築の手順が追いやすくなります。

conda環境なら(%conda)

condaを使っている場合は%condaが使えます。

カーネルが指すconda環境にパッケージを導入します。

Python
# conda環境でのインストール例(必要ならバージョン指定)
%conda install -y numpy=1.26
実行結果
Collecting package metadata (current_repodata.json): done
Solving environment: done
...
Proceed ([y]/n)?

conda環境とカーネルの環境が一致していないと期待通りに入らないことがあります。

カーネル選択を確認してください。

作業フォルダを確認・移動(%pwd %cd %ls)

ファイル操作の前に、現在の作業ディレクトリを把握しておくとトラブルが減ります。

Python
%pwd
実行結果
'/home/jovyan/work'
Python
%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
Python
%cd ..  # 1つ上へ
%pwd
実行結果
/home/jovyan
'/home/jovyan'

自動保存の間隔を変える(%autosave)

ノートの自動保存は%autosaveで調整できます。

単位は秒で、0で無効化です。

Python
%autosave 60  # 60秒ごとに自動保存
実行結果
Autosaving every 60 seconds
Python
%autosave 0  # 無効化
実行結果
Autosave disabled

共同作業やクラッシュ対策として、自動保存は有効にしておくことをおすすめします。

入出力と表示を便利にするマジック

Pythonスクリプトを実行(%run)

外部の.pyファイルをノートから直接実行できます。

-iで現在の変数を引き継ぎ、-nで実行せず構文チェックのみ行います。

Python
%%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
Python
# 引数付きで実行
%run hello.py Jupyter Lab
実行結果
Hello Jupyter Lab
Python
# 変数を引き継いで実行(-i)
name = "Notebook"
%run -i hello.py
実行結果
Hello Notebook

出力を抑える・ログに残す(%%capture)

たくさん出るログを抑えたいときは%%captureで出力をキャプチャし、必要なときだけ取り出します。

Python
%%capture cap --no-stderr
# 標準出力だけ捕まえる
for i in range(3):
    print("line", i)
Python
# 必要なときに取り出す
cap.stdout
実行結果
'line 0\nline 1\nline 2\n'
Python
# エラー側を抑制しない場合(--no-stderrを付けなければstderrも保存されます)
print(cap.stderr)  # 空文字
実行結果
''

セル内容をファイルに書く(%%writefile)

ノート上で短いスクリプトや設定をそのままファイル化できます。

Python
%%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
Python
%run square.py 4
実行結果
0
1
4
9

グラフ表示を安定させる(%matplotlib inline)

%matplotlib inlineで、Matplotlibの図をノート内に埋め込み表示します。

注意

Matplotlibのインストールが必要です。

Shell
pip install matplotlib

JupyterLabでは多くの場合既定ですが、明示しておくと安心です。

Python
%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は型やサイズも表示します。

Python
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はカーネルを再起動するまで、コードを削除しても過去の変数が保持され続けます。

コードにない変数が含まれている?

関係ない変数が残っている場合は、▶▶を押してリセットするようにしましょう。

Python
%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が便利です。

番号付きで表示したり、出力も含められます。

Python
%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なども取り入れ、再現性と読みやすさの高いノート作成を目指してください。

この記事を書いた人
エーテリア編集部
エーテリア編集部

人気のPythonを初めて学ぶ方向けに、文法の基本から小さな自動化まで、実際に手を動かして理解できる記事を書いています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!