クリーム色の背景、色付き表示、高コントラスト、大きな文字のほうが読みやすいですか?配色と文字を選ぶと、すべてのページに一度で反映されます。

無料レッスン

デバッグの進め方

このレッスンのあとで: エラーを読み、一度に1つずつ確かめて、バグを見つけられる。

60分のレッスンコマンド13件毎日使う Linux コマンドのラボ:エンジニアが暗記している30のコマンド

プログラムの間違いを探す方法

デバッグとは、プログラムが間違った動きをする理由を見つけて、直すことです。大変なのは、直すコードを打つことではありません。百か所ある中で、どこを見るかを決めることです。

当てずっぽうにコードを変えると、午後が丸ごと消えることがあります。一度に1つずつ確かめれば、数分で済みます。

このレッスンのゴール

メモ

エラーを読み、一度に1つずつ確かめて、バグを見つけられる。

重要な言葉

ことばいみ
バグプログラムを間違った動きにさせる欠陥
再現同じ間違いを、好きなときに起こすこと
トレースバックエラーで止まったときに Python が出す、呼び出しの一覧
仮説1回の確認で間違いとわかる、原因の予想
表示で確認値を画面に出して、中身を見ること
半分に絞る残りの真ん中を調べて、毎回半分を除くこと

学生が入力するセルは、このプレビューでは空白です。

まず、好きなときに起こす

見えない間違いは直せません。何かを変える前に、毎回間違いが起こる入力を見つけて、取っておきます。

小さなプログラムが、ファイルの売上を平均します。1行が1日分です。データには穴があります。先にフォルダーとファイルを作りましょう。

レッスン用のフォルダーを作る

コマンド
mkdir -p ~/debugtest

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

フォルダーに入る

コマンド
cd ~/debugtest

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

売上ファイルを書く

コマンド
printf '月 120\n火 80\n水 なし\n木 200\n' > sales.txt

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

レポートのプログラムを書く

コマンド
printf 'def parse(line):\n    parts = line.split()\n    return [parts[0], int(parts[1])]\n\n\ndef average(lines):\n    result = 0\n    for line in lines:\n        pair = parse(line)\n        result = result + pair[1]\n    return result / len(lines)\n\n\nprint(average(open("sales.txt").read().splitlines()))\n' > report.py

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

実行して、止まるのを見る

コマンド
python3 report.py

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

トレースバックは下から読む

トレースバックは、プログラムが止まったときに開いていた呼び出しの一覧です。いちばん新しい呼び出しが下にあるので、下から読みます。

最後の行は、何が起きたかを言います。ValueError という名前とメッセージです。その上の File の行は、場所を言います。ファイル、行番号、関数名です。さらに上の行は、そこに来た道筋です。

File の行だけを出す

コマンド
python3 report.py 2>&1 | grep "File"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

1つ確かめて、次へ進む

エラーが示すのは、プログラムが止まった場所です。データが間違っていた理由ではありません。そこで仮説を立てます。1回の確認で間違いとわかる予想を、1つ立てるのです。

今回の仮説は、データのどこかの行が数ではない、です。ファイルを検索して確かめます。何も出なければ仮説は外れですが、それも前進です。

データの中を検索する

コマンド
grep -n "なし" sales.txt

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

手早い修正は次のバグを隠す

3行目は 水 なし です。その日は売上の数がありませんでした。いちばん手早い直し方は、0として数えることです。試して、もう一度実行しましょう。

数のない日を0として数える

コマンド
sed -i 's|    return \[parts\[0\], int(parts\[1\])\]|    if parts[1] == "なし":\n        return [parts[0], 0]\n    return [parts[0], int(parts[1])]|' report.py

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

もう一度実行する

コマンド
python3 report.py

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

エラーがなくてもバグはある

プログラムは動いて、100.0 を表示しました。しかし、数のある3日分、120、80、200 の平均は 133.3 です。プログラムは間違っているのに、何も言いません。

もう読めるトレースバックはありません。足し算をしている場所に表示で確認を入れて、実際の中身を見ます。

足すたびに、その日を表示する

コマンド
sed -i 's|        result = result + pair\[1\]|        print(pair[0], pair[1])\n        result = result + pair[1]|' report.py

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

実行して、1行ずつ読む

コマンド
python3 report.py

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

段階が多いときは半分に絞る

このプログラムには4つの段階があります。まず真ん中を調べます。合計が正しければ、間違いはその後ろです。間違っていれば、前です。1回の確認で半分が消えます。

チームは、この方法で、千個の変更の中から機能を壊した1つを見つけます。

例: 段階を順に確かめる

段階本来の中身実際の中身判定
ファイルを読む4行4行問題なし
金額を読む120, 80, なし, 200120, 80, 0, 2000は作り話の数
足し合わせる400400問題なし
数えた日数で割る400 / 3 = 133.3400 / 4 = 100.0数のない日も数えた

学生が入力するセルは、このプレビューでは空白です。

直したプログラムを書き直す

コマンド
printf 'def parse(line):\n    parts = line.split()\n    if not parts[1].isdigit():\n        return None\n    return [parts[0], int(parts[1])]\n\n\ndef average(lines):\n    result = 0\n    count = 0\n    for line in lines:\n        pair = parse(line)\n        if pair is not None:\n            result = result + pair[1]\n            count = count + 1\n    return result / count\n\n\nprint(round(average(open("sales.txt").read().splitlines()), 1))\n' > report.py

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

直したプログラムを実行する

コマンド
python3 report.py

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

よくある間違い

注意

原因がわかる前にコードを変え、うまくいかないと別の所を変える人がいます。5回変えると、どれが効いたのかわかりません。先に確かめ、1つだけ変えて、また実行します。

さらに: 壊した変更を探す

チームは、すべての変更を Git に残します。バグが出たとき、古い版は良く、いちばん新しい版は悪いとわかっています。git bisect は、真ん中の版を試すよう求め、変更が1つになるまで履歴を半分にします。

1000個の変更で、手順を書きましょう。試す版は、多くて何個でしょうか。

このラボとソースについて: 毎日使う Linux コマンドのラボ:エンジニアが暗記している30のコマンド

授業で使いますか?このモジュールを学生に割り当てると、教員用ガイド、自動採点つきの課題、学生ごとのラボを使えます。