Pythonのプログラムをデバッグするには [Python, Debugging]
ここではPythonのプログラムをデバッグする方法について解説します。
Pythonのプログラムに不具合(バグ)があるときは、通常print()などでデバッグ情報を表示させてバグ(bug)を見つけます。
ここでは3種類の方法でバグを見つける方法を紹介します。
この記事ではMicrosoftのVisual Studio Code(VS Code)を使用していますが、Jupyter NotebookなどのツールでもOKです。
説明文の左側に図の画像が表示されていますが縮小されています。
画像を拡大するにはマウスを画像上に移動してクリックします。
画像が拡大表示されます。拡大された画像を閉じるには右上の[X]をクリックします。
画像の任意の場所をクリックして閉じることもできます。
Pythonのプログラムをデバッグするには
-
Pythonで絵文字を表示するプログラムを作成する
Visual Studio Code(VS Code)を起動したら新規ファイルを作成して行1-10を入力(コピペ)します。
行1-3では関数「main()」を定義しています。
行2では絵文字を表示する件数を入力させています。
行3では関数「print_emoji()」を呼び出しています。
行5-7では関数「print_emoji()」を定義しています。
行6-7のforループでは絵文字を引数で指定した件数分表示しています。
ちなみにこのコードにはバグがあります。詳細は図1で解説します。
行9-10では関数「main()」を呼び出しています。
def main():
number = int(input("What's number: "))
print_emoji(number)
def print_emoji(n):
for i in range(n):
print('😄' * i)
if __name__ == '__main__':
main()
図1は実行結果です。
「What's number」で「3」を入力しているので本来絵文字が3件表示されるべきなのですがバグがあるので2件しか表示されていません。
-
Pythonの「print()」でデバッグ情報を表示する
ここでは前出のプログラムのバグを見つけるために行7の「print(i, end=' ')」を追加します。
def main():
number = int(input("What's number: "))
print_emoji(number)
def print_emoji(n):
for i in range(n):
print(i, end=' ')
print('😄' * i)
if __name__ == '__main__':
main()
図2は実行結果です。
行10(図2)のprintでは変数「i」の値が「0, 1, 2」と3件表示されています。
行11(図2)の「 print('😄' * i)」ではiの値が「0」のため絵文字が表示されないことが判明しました。
このバグは「 print('😄' * (i + 1))」のように修正すれば正常に動作します。
-
Pythonのライブラリ「logging」でデバッグ情報を表示する
ここではPythonのライブラリ「logging」を使用してデバッグ情報を表示します。
行1ではPythonのライブラリを取り込んでいます。
行5ではloggingのbasicConfig()メソッドでログの書式を設定しています。
ここではログ情報として「levelname」+「message」を表示するように設定しています。
さらに「levelname」を緑色で表示するようにしています。
loggingの詳細については「記事(Article103)」で解説しています。
行12ではloggingのdebug()メソッドでデバッグ情報を表示しています。
ここでは変数「i」の値を表示しています。
import logging
def main():
# logging.basicConfig(format=':%(levelname)s: %(message)s', level=logging.DEBUG)
logging.basicConfig(format='\033[92m%(levelname)s\033[0m %(message)s', level=logging.DEBUG)
# logging.basicConfig(format='\033[92m%(levelname)s\033[0m %(message)s', level=logging.CRITICAL)
number = int(input("What's number: "))
print_emoji(number)
def print_emoji(n):
for i in range(n):
logging.debug(f"i={i}")
print('😄' * i)
if __name__ == '__main__':
main()
図3は実行結果です。
デバッグ情報として「DEBUG i=0」が表示されています。
変数「i」の値が「0」なので絵文字が2件しか表示されないことが判明しました。
-
プログラムのバグ(bug)を修正して再実行して見る
ここでは行13を「 print('😄' * (i + 1))」のように修正してバグを取り除いています。
さらに行6を追加してデバッグ情報が表示されないようにしています。
loggingのbasicConfig()メソッドの引数「level=」に「logging.CRITICAL」を設定すると、
行12のloggingのdebug()メソッドで表示したデバッグ情報は無効になります。
つまり、表示されないようになります。
import logging
def main():
# logging.basicConfig(format=':%(levelname)s: %(message)s', level=logging.DEBUG)
# logging.basicConfig(format='\033[92m%(levelname)s\033[0m %(message)s', level=logging.DEBUG)
logging.basicConfig(format='\033[92m%(levelname)s\033[0m %(message)s', level=logging.CRITICAL)
number = int(input("What's number: "))
print_emoji(number)
def print_emoji(n):
for i in range(n):
logging.debug(f"i={i}")
print('😄' * (i + 1))
if __name__ == '__main__':
main()
図4は実行結果です。
バグが取り除かれて絵文字が3件表示されています。
さらにデバッグ情報も表示されなくなりました。
このようにlogging.debug()を使用するとコードを削除することなしに、デバッグ情報を無効にすることができます。
-
Visual Studio Code(VS Code)のデバッグ機能を使用してデバッグする
ここではVS Codeのデバッガーを使用してデバッグする方法を説明します。
前出のプログラムはバグのある状態に戻しています。
行7の「print('😄' * i)」にバグがあります。
VS Codeでデバッグする手順については図5-1~図5-7で説明します。
def main():
number = int(input("What's number: "))
print_emoji(number)
def print_emoji(n):
for i in range(n):
print('😄' * i)
if __name__ == '__main__':
main()
行24(図5-1)の行番号の左をクリックしてブレークポイントを設定します。
すると赤の「●」が表示されます。
この状態で「Run and Debug」のアイコンをクリックしてデバッガー起動します。
「Run and Debug」の文字が表示されたらクリックして起動します。
行24(図5-3)の「●」が「▶」に変わります。
そしてデバッガーを操作するナビゲーションボタンが表示されます。
さらに画面の左側には「VARIABLES」が表示されて変数の値が見れる状態になります。
この状態でナビゲーションボタンから[Step Into]ボタンをクリックして続行します。
行16(図5-4)に矢印(ブレークポイント)が移動します。
この状態でナビゲーションボタンから[Step Over]ボタンをクリックして続行します。
行16(図5-5)が実行されてTERMINALウィンドウに「What's number:」が表示されたら「3」を入力して[Enter]を押します。
ブレークポイントが行17(図5-5)に移動したらナビゲーションボタンから[Step Into]ボタンをクリックして続行します。
行20(図5-6)にブレークポイントが移動したらナビゲーションボタンから[Step Into]ボタンをクリックして続行します。
行21(図5-7)のprint()が実行されてブレークポイントが行20(図5-7)に移動します。
この状態で左側の「VARIABLES」に表示されている変数「i」の値をチェックします。
ここでは「0」になっています。これで絵文字が表示されないことが判明しました。
「print('😄' * i) が print()」になる。
バグが判明したのでナビゲーションボタンから[Stop]ボタンをクリックしてデバッガーを終了させます。