はじめに
コードは決して完璧ではありません。バグは常にあります。コードのデバッグは学ぶ必要のあるスキルです。
This tutorial is from open-source community. Access the source code
💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください
コードは決して完璧ではありません。バグは常にあります。コードのデバッグは学ぶ必要のあるスキルです。
さて、あなたのプログラムはクラッシュしてしまいました...
$ python3 blah.py
Traceback (most recent call last):
File "blah.py", line 13, in?
foo()
File "blah.py", line 10, in foo
bar()
File "blah.py", line 7, in bar
spam()
File "blah.py", 4, in spam
line x.append(3)
AttributeError: 'int' object has no attribute 'append'
これでどうしたらいいのでしょうか?
最後の行がクラッシュの具体的な原因です。
$ python3 blah.py
Traceback (most recent call last):
File "blah.py", line 13, in?
foo()
File "blah.py", line 10, in foo
bar()
File "blah.py", line 7, in bar
spam()
File "blah.py", 4, in spam
line x.append(3)
## クラッシュの原因
AttributeError: 'int' object has no attribute 'append'
ただし、読んだり理解したりするのは必ずしも簡単ではありません。
プロのコツ:トレースバック全体をGoogleに貼り付けましょう。
スクリプトを実行する際に、オプション -i
を使って Python を実行中に維持します。
$ python3 -i blah.py
Traceback (most recent call last):
File "blah.py", line 13, in?
foo()
File "blah.py", line 10, in foo
bar()
File "blah.py", line 7, in bar
spam()
File "blah.py", 4, in spam
line x.append(3)
AttributeError: 'int' object has no attribute 'append'
>>>
これによりインタプリタの状態が保持されます。つまり、クラッシュ後に調べることができます。変数の値やその他の状態を確認できます。
print()
によるデバッグは非常に一般的です。
ヒント:repr()
を使うことを確認しましょう。
def spam(x):
print('DEBUG:', repr(x))
...
repr()
は値の正確な表現を表示します。見やすい印刷出力ではありません。
>>> from decimal import Decimal
>>> x = Decimal('3.4')
## `repr` なし
>>> print(x)
3.4
## `repr` あり
>>> print(repr(x))
Decimal('3.4')
>>>
プログラム内でデバッガを手動で起動することができます。
def some_function():
...
breakpoint() ## デバッガに入る (Python 3.7以降)
...
これにより、breakpoint()
の呼び出し箇所でデバッガが起動します。
以前の Python バージョンでは、このようにしていました。他のデバッグガイドでこれが言及されることもあります。
import pdb
...
pdb.set_trace() ## `breakpoint()` の代わり
...
デバッガの下で、全体のプログラムを実行することもできます。
$ python3 -m pdb someprogram.py
最初の文の前に自動的にデバッガに入ります。ブレークポイントを設定したり、設定を変更したりすることができます。
一般的なデバッガコマンド:
(Pdb) help ## ヘルプを取得する
(Pdb) w(here) ## スタックトレースを表示する
(Pdb) d(own) ## 1つ下のスタックレベルに移動する
(Pdb) u(p) ## 1つ上のスタックレベルに移動する
(Pdb) b(reak) loc ## ブレークポイントを設定する
(Pdb) s(tep) ## 1つの命令を実行する
(Pdb) c(ontinue) ## 実行を続ける
(Pdb) l(ist) ## ソースコードを表示する
(Pdb) a(rgs) ## 現在の関数の引数を表示する
(Pdb)!statement ## 文を実行する
ブレークポイントの位置は、次のいずれかです。
(Pdb) b 45 ## 現在のファイルの45行目
(Pdb) b file.py:45 ## file.pyの45行目
(Pdb) b foo ## 現在のファイルのfoo()関数
(Pdb) b module.foo ## モジュール内のfoo()関数
動作します。リリースしましょう!
おめでとうございます!あなたはデバッグの実験を完了しました。あなたのスキルを向上させるために、LabExでさらに多くの実験を練習することができます。