今回は Google Colaboratory(Colab) のおすすめのデバッグ方法をご紹介します。Python標準のデバッガ「pdb 」を利用するところは一般的な方法と変わりありませんが、ポイントは「スクラッチコードセル(Scratch code cell)」をうまく活用することです。
PyCharmのようなIDEならデバッグ専用のウィンドウがあるので、そこでデバッグできるようになっていますが、Colabにはありません。そこで、スクラッチコードセルをうまく活用します。
Colabでのプログラミングは、セルごとに逐次実行しながら行うので、都度出力することでミスに気づきやすいという一面もあります。しかし、プログラミングしていればエラー発生は不可避です。Colabでも的確にデバッグできるようにしておくことは大事です。ぜひColabを用いたプログラミングの参考にしてください。
本記事の目次
サンプルコード
本記事では、デバッグ方法の説明のためにわざと例外を発生させる以下のコードを用います。
まず、1つめのセルで引数どうしの割り算を行うcalc_division()
関数を定義します。
def calc_division(a, b):
return a / b
次のセルで、値のペアのリストval_pairs
を作成し、ループでペアの値どうしの割り算の結果をprint()
で表示します。
val_pairs = [(4, 2), (3, 1), (5, 0), (8, 4)]
for x, y in val_pairs:
d = calc_division(x, y)
print(d)
コードを実行すると、以下のように2つ目までの値のペアは割り算できますが、3つ目はゼロ割になるので、ZeroDivisionError
が発生します。
4 / 2 => 2.0
3 / 1 => 3.0
5 / 0 => ゼロ割 => ZeroDivisionError
例外が発生したときのデバッグ方法
最初にプログラムを実行していて例外が発生してから原因を調べるためのデバッグ方法を説明します。いわゆる「検死デバッグ (post-mortem debug) 」の方法です。一般的にはエラーが発生してからデバッグすることが多いので、よく用いる方法です。
1. 例外発生
まず上記のサンプルコードを実行して実際に例外を発生させます。
2. スクラッチコードセルを表示
例外が発生したままの状態で、メニューから[挿入]-[スクラッチコードセル](またはCtrl + Alt + N)を選択して「スクラッチコードセル」を表示させます。
スクラッチコードセルは、現在実行しているコードに影響を与えない「一時的なセル」です(つまり、ここで変数を上書きしても元の値は変わりません)。元のノートブックで定義した変数や関数を参照できるので、その場限りのコードを試行するのに利用できます。
3. スクラッチコードセルに「%debug」を入力
次にスクラッチコードセルに%debug
と入力して、Shift + Enter を押して実行します。
すると以下のようにpdbデバッガが起動して、ipdb>
というプロンプトが表示されます。これでデバッグのためのコマンド(デバッガコマンド)を入力できる状態になります。
例外が発生した時点の状態はPythonのシステムに保存されているので、%debug
と入力してデバッガを起動すれば直近の例外をデバッグできるようになっています。
4. コマンドでデバッグを行う
ここからコマンドを用いて対話的にデバッグをおこないます。
まず「コマンドp」で変数の値を調べてみましょう。p b
を実行すると、変数b
の値が表示されます。ここで、b
の値が0
になっているので、ゼロ割が行われていることが確認できました。
次に「コマンドu」で呼び出し元の関数calc_division()
に戻ります。
ここで、p x,y
を実行して、x
とy
の値を調べると5
と0
が代入されていることがわかります。つまり、calc_division(5, 0)
が呼び出されたために例外が発生したことが判明しました。
5. デバッガを終了してスクラッチコードを閉じる
デバッグが終わったら「コマンドq」を実行してデバッガを終了します。スクラッチコードセルも閉じます。
6. コードを修正
例外が発生した原因が判明したので、コードを適切に修正すればデバッグの終了です。
以上のようにスクラッチコードセルを活用すれば、ノートブックをきれいに保ったままデバッグできるのでデバッグのためにコードを加えたり、あとで書き直さなくて済みます。
デバッガコマンド
今回用いたp
やu
のような「デバッガコマンド」にはおもに以下のようなコマンドがあります。詳しい内容は公式ドキュメント で確認できます。
pdbのおもなデバッガコマンド
コマンド | 動作 |
---|---|
p | (print)値を表示する |
u | (up)呼び出し履歴を1つ上がる |
d | (down)呼び出し履歴を1つ下がる |
n | (next)次の実行ステップに移動[ステップオーバー] |
s | (step)呼び出している関数の中に入る[ステップイン] |
c | (continue)プログラム実行を再開する |
q | (quit)デバッガを終了する |
行番号を表示するには
今回のサンプルコードは短いので使用しませんでしたが、コードが長い場合は「行番号」を表示した方がエラーの場所を特定しやすくなります。
ColabではCtrl + M + Lで、行番号の[表示/非表示]を切り替えられます。
ブレークポイントのように一時停止してデバッグする方法
今度はブレークポイントのようにプログラムを一時停止してデバッグする方法を説明します。
Colabでも一般的な方法と同じくimport pdb; pdb.set_trace()
やPython3.7で追加されたbreakpoint()
関数を用いて、ブレークポイントを配置することが可能です。
しかし、プログラム実行途中の変数の値を確認するだけでよければ、もっと簡単な方法があります。それは、input()
関数と「変数インスペクタ」を活用する方法です。今回はこちらを説明します。
1. セルのミラーセルを作成する
ここでも作業はスクラッチコードセルで行います。そのためコードをスクラッチコードセルにコピーする必要があります。スクラッチコードセルを作成してからコピペしてもよいのですが、「ミラーセル」を使うと簡単にできます。
そこでまず以下のアイコンをクリックしてミラーセルを作成します。
2. ミラーセルからスクラッチコードセルを作成する
すると以下のようにコードの内容がミラーセルに反映されるので、さらに以下のアイコンをクリックしてスクラッチコードセルにコピーします。
なお「ミラーセル」は元のセルをミラーリングしているので、編集すると元のセルも連動して書き換わります。そのためミラーセルでデバッグ作業をすると元のセルを書き換えてしまうので、あえて「スクラッチコードセル」にコピーして作業します。
3. スクラッチコードセルにinput()を追加する
上記の操作で以下のようにコードをコピーしたスクラッチコードセル(スクラッチセル)が作成できました。次にスクラッチセルのコードでプログラムを一時停止したい箇所にinput()
を追加します。
4. 変数インスペクタを開く
左側のガーターにある以下のアイコンをクリックして「変数インスペクタ」を開きます。
5. スクラッチコードセルを実行
これで準備ができたので、以下のようにをクリック(またはShift + Enter)してスクラッチコードセルを実行します。
6. ループごとに変数の中身を確認しながらデバッグ
すると以下のようにinput()
の行でプログラムが停止し、その時点の変数の中身を「変数インスペクタ」で確認できるようになります。変数インスペクタで中身を確認したい変数にマウスを重ねると「値」が表示されます(データの「型」も一緒にわかります)。
続けてEnterを押すとfor文の中を1回実行して、またinput()
の行で停止します。セルにはval_pairs
の1つ目の要素(4,2)
の値どうしを割り算した結果(d=4/2=2.0
)が表示されます。変数インスペクタにより2つ目の要素(3,1)
がx,y
に代入されているのが確認できます。
さらにEnterを2回押すと以下のように3つ目の要素(5,0)
でゼロ割が行われエラーが発生します。
このようにエラーが発生するまでの過程を変数の中身の変遷を確認しながらトレースできました。今回のようにループ処理のエラーを調べるときに特に役立つ方法です。
あわせて読みたい
以下の書籍はGoogle Colabを利用しながら、Pythonとデータ分析が学べます。