初心者でも理解可能!Pythonデバッグの手順とテクニック7つ

Pythonデバッグの流れと詳細な使い方を解説するイラストPython
この記事は約13分で読めます。

 

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればカスタムコードを使って機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

プログラミングにおいて、エラーを見つけて修正するデバッグは重要なスキルの一つです。

Pythonは初心者にも使いやすい言語であるため、デバッグ手法も比較的シンプルですが、それでも知っておくべきテクニックは存在します。

この記事では、Pythonのデバッグの基本から具体的な手順、注意点やカスタマイズ方法まで、初心者にも理解しやすいように詳しく解説します。

●Pythonデバッグの基本とは

Pythonのデバッグについて学ぶ前に、まずデバッグの目的と重要性を理解することが重要です。

○デバッグの目的

デバッグの主な目的は、コードに存在するエラーや不具合を見つけて修正することです。

また、不具合の原因を特定し、それが再発しないように対策を立てることも目的の一つです。

○デバッグの重要性

デバッグはプログラムが正常に動作するために不可欠なプロセスです。

また、エラーの解決を通じて自分のコード理解が深まり、スキル向上にも繋がります。

特にPythonのような動的型付け言語では、エラーが実行時まで現れないケースが多いため、デバッグスキルは必須といえます。

●Pythonデバッグの具体的な手順

それでは、Pythonのデバッグの具体的な手順を見ていきましょう。

○デバッグ前の準備

Pythonのデバッグを行う前に、まずは基本的な準備を整えることが重要です。

□Pythonの組み込みデバッガpdb

Pythonにはpdbという組み込みのデバッガがあります。

このpdbを使うことで、コードの任意の位置で実行を一時停止し、その時点での変数の値を確認することができます。

□ブレークポイントの設定方法

ブレークポイントとは、プログラムの実行を一時停止する指定した地点のことを言います。

pdbでは、次のようにコード内に ‘import pdb; pdb.set_trace()’ を挿入することでブレークポイントを設定できます。

def debug_sample():
    x = 10
    import pdb; pdb.set_trace()  # ここがブレークポイント
    y = x * 5
    return y

上記のコードでは、xの値が10に設定された後でプログラムの実行が一時停止します。

この状態でpdbのコマンドを使って変数の値を調べたり、ステップ実行を行ったりすることができます。

○エラーの読み方

次に、Pythonのエラーの種類とそれぞれの読み方を説明します。

□構文エラー(Syntax Errors)

Pythonの構文エラーは、コードの書き方がPythonの文法に適合していないときに発生します。

例えば、下記のコードは括弧が閉じられていないため構文エラーとなります。

print("Hello, World!

上記のコードを実行すると、次のようなエラーメッセージが表示されます。

  File "<stdin>", line 1
    print("Hello, World!
                         ^
SyntaxError: EOL while scanning string literal

このメッセージによれば、エラーの種類は ‘SyntaxError’ で、具体的な原因は ‘EOL while scanning string literal’ となっています。

つまり、文字列の途中で行が終わってしまった、つまり括弧が閉じられていないということを表しています。

□実行エラー(Runtime Errors)

実行エラーは、コードの構文自体には問題ないが、実行中に何らかの問題が生じたときに発生します。

例えば、存在しない変数を参照した場合などです。次のコードは実行エラーを引き起こします。

print(x)

上記のコードを実行すると、次のようなエラーメッセージが表示されます。

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined

このメッセージによれば、エラーの種類は ‘NameError’ で、具体的な原因は ‘name ‘x’ is not defined’ となっています。

つまり、定義されていない変数 ‘x’ を参照しようとしたということを示しています。

□論理エラー(Logical Errors)

論理エラーは、コードの構文も実行も問題なく、しかし結果が期待したものと異なるときに発生します。

つまり、プログラムのロジックが間違っているということです。例えば、以下のコードは論理エラーです。

def add(x, y):
    return x - y  # 加算ではなく減算を行っている

result = add(5, 3)
print(result)  # 期待値は8だが、実際の出力は2

上記のコードを実行すると、エラーは発生しませんが、期待した結果と異なる出力が得られます。

論理エラーは明確なエラーメッセージが表示されないため、デバッグが難しいケースもあります。

そのため、こうしたエラーを発見するためには、コードの理解と、適切なテストケースの作成が重要となります。

○デバッグ手法の選択

Pythonのデバッグ手法には主に2つあります。

1つはprint関数を用いたデバッグ、もう1つはデバッガを用いたデバッグです。

□print関数を用いたデバッグ

最も基本的なデバッグ手法は、print関数を用いて変数の値を確認する方法です。

下記のようなコードで、変数xとyの値を確認できます。

x = 10
y = 20
print(f"x: {x}, y: {y}")  # f-stringを使って変数の値を表示

この方法はシンプルで使いやすいですが、大規模なプログラムや複雑なエラーの場合、効率的にデバッグするのが難しい場合もあります。

□デバッガを用いたデバッグ

デバッガを用いると、コードの任意の位置で実行を一時停止したり、1行ずつ実行したりしながら変数の値を確認することができます。

これにより、エラーの原因をより効率的に特定することができます。

Pythonには組み込みのデバッガpdbのほか、高機能なデバッガIPythonなどがあります。

それでは具体的なデバッグの実施例とサンプルコードを見ていきましょう。

○デバッグの実施例とサンプルコード

それでは、3つのサンプルコードを用いて具体的なデバッグの手順を説明します。

□サンプルコード1:シンプルな計算コードのデバッグ

下記のコードは、2つの数値を足し合わせる非常にシンプルなコードです。

しかし、このコードには論理エラーがあります。

def add(x, y):
    return x - y  # 加算ではなく減算を行っている

result = add(5, 3)
print(result)  # 期待値は8だが、実際の出力は2

実行結果は ‘2’ となり、期待値の ‘8’ とは異なります。

これは ‘add’ 関数が足し算ではなく引き算を行ってしまっているためです。

この問題を解決するためには、関数内の ‘-‘ を ‘+’ に修正すれば良いです。

def add(x, y):
    return x + y  # '+'に修正

result = add(5, 3)
print(result)  # 正しく8が出力される

□サンプルコード2:ループ処理のデバッグ

次のコードは、リスト内の各要素を2倍にして新しいリストを作るコードです。

しかし、このコードにはエラーが存在します。

def double_elements(list):
    new_list = []
    for i in list:
        new_element = i * 2
    new_list.append(new_element)
    return new_list

numbers = [1, 2, 3, 4, 5]
print(double_elements(numbers))  # 期待値は[2, 4, 6, 8, 10]だが、実際の出力は[10]

このコードを実行すると、出力は ‘[10]’ となります。

これはループ内で新しい要素をリストに追加する処理がループの外にあるためです。

これを解決するためには、 ‘new_list.append(new_element)’ をループ内に移動すれば良いです。

def double_elements(list):
    new_list = []
    for i in list:
        new_element = i * 2
        new_list.append(new_element)  # ここに移動
    return new_list

numbers = [1, 2, 3, 4, 5]
print(double_elements(numbers))  # 正しく[2, 4, 6, 8, 10]が出力される

□サンプルコード3:関数のデバッグ

最後のサンプルは、ある関数が正しく動作しているかをチェックするコードです。

下記のコードは、数値を2で割る関数 ‘divide_by_two’ と、この関数をテストする関数 ‘test_divide_by_two’ が含まれています。

def divide_by_two(x):
    return x // 2  # 整数除算を行っている

def test_divide_by_two():
    assert divide_by_two(10) == 5, "Failed on 10"
    assert divide_by_two(0) == 0, "Failed on 0"
    assert divide_by_two(-10) == -5, "Failed on -10"

test_divide_by_two()  # テストを実行

しかし、このテストを実行すると、’assert divide_by_two(10) == 5′ の行で AssertionError が発生します。

これは、’divide_by_two’ 関数が整数除算を行ってしまっているためです。

この問題を解決するためには、’//’ を ‘/’ に変更すれば良いです。

def divide_by_two(x):
    return x / 2  # '/'に修正

def test_divide_by_two():
    assert divide_by_two(10) == 5, "Failed on 10"
    assert divide_by_two(0) == 0, "Failed on 0"
    assert divide_by_two(-10) == -5, "Failed on -10"

test_divide_by_two()  # 正しくテストが通る

以上の例からわかるように、デバッグはプログラムの不具合を修正するための重要な手続きであり、効果的なデバッグを行うためには適切な手法の選択と、その手法を適用するための理解が必要となります。

●Pythonデバッグの注意点と対処法

デバッグを行う上で注意すべき点とその対処法について解説します。

一つ目の注意点は、エラーメッセージを適切に理解することです。

Pythonのエラーメッセージは非常に詳細で、エラーの種類や発生源を特定する手がかりを提供します。

したがって、エラーメッセージを正しく読み取り、それを基に問題を解決することが重要です。

二つ目の注意点は、テストケースの選択です。

適切なテストケースを作成することで、予期しないエラーや論理エラーを発見することが可能となります。

特に、境界条件をテストすることで、多くのエラーを捉えることができます。

三つ目の注意点は、デバッグの作業を焦らないことです。

コードのエラーを修正する作業はしばしば困難であり、それによって焦ってしまうことがあります。

しかし、焦りはさらなるエラーを生む可能性がありますので、一息つき、必要なら他の人の意見を求めることも重要です。

●Pythonデバッグのカスタマイズ方法

Pythonのデバッグ作業を更に効果的に行うためのカスタマイズ方法について解説します。

Pythonには、デバッグ作業を助けるためのツールやライブラリがいくつかあります。

それぞれのツールやライブラリには、特定の目的や状況に対応するためのカスタマイズオプションがあります。

●デバッグを助けるPythonのツールとライブラリ

デバッグ作業を助けるPythonのツールとライブラリについて紹介します。

○pdbの詳細な使い方とカスタマイズ

Pythonに組み込まれているデバッガであるpdbは、コードの実行を一時停止し、変数の値を確認したり、一行ずつコードを実行したりすることができます。

pdbを使ってデバッグを行う例を紹介します。

import pdb

def add(x, y):
    pdb.set_trace()  # ここで実行を一時停止
    return x + y

print(add(10, 20))

このコードを実行すると、 ‘pdb.set_trace()’ の行で実行が一時停止し、対話式のデバッガセッションが開始します。

ここで ‘x’ や ‘y’ と入力することで変数の値を確認したり、 ‘next’ や ‘continue’ と入力することでコードの実行を制御したりできます。

○高機能デバッガIPythonとその使い方

IPythonは、対話型のPythonシェルで、デバッグ機能やコードの補完、色付け等、多くの機能を提供しています。

IPythonのデバッガであるipdbを使うと、pdbよりも高度なデバッグが可能です。

ipdbを使ってデバッグを行う例を紹介します。

from IPython.core.debugger import set_trace

def add(x, y):
    set_trace()  # ここで実行を一時停止
    return x + y

print(add(10, 20))

このコードを実行すると、 ‘set_trace()’ の行で実行が一時停止し、対話式のデバッガセッションが開始します。

ここでも ‘x’ や ‘y’ と入力することで変数の値を確認したり、 ‘next’ や ‘continue’ と入力することでコードの実行を制御したりできますが、より進んだ機能が利用可能です。

○静的解析ツールとその活用法

静的解析ツールの一つに、Pythonの標準ライブラリであるpylintがあります。

pylintはコードに潜む潜在的なエラーやスタイル違反を見つけるためのツールであり、デバッグを支援するための有力なツールです。

pylintを使ってPythonコードを静的解析する方法を紹介します。

まず、Python環境にpylintをインストールします。

!pip install pylint

次に、チェックを行いたいPythonコードを書きます。

ここでは例として、一つの関数の定義が未完了のコードを示します。

def add(x, y):
    return x +

このコードでは、add関数が2つの数を足す処理を行うはずですが、足すべきyが漏れています。

このようなコードをpylintで静的解析を行うことで、未完成の部分や潜在的なバグを発見することができます。

そして、コマンドラインでpylintを実行します。

引数にはチェックを行いたいPythonファイル名を指定します。

!pylint test.py

このコードを実行すると、pylintは解析結果を出力します。

解析結果には、エラーメッセージや警告、そして最後には評価スコアが表示されます。

エラーメッセージには、エラーの種類や発生源、そしてエラーの詳細説明が含まれています。

この情報を利用することで、コードの問題点を具体的に理解し、修正することが可能となります。

なお、pylintでは、PythonのPEP 8というスタイルガイドに従っていないコードに対しても警告を出します。

これにより、Pythonの慣例に従ったコーディングスタイルを守ることが可能となります。

以上のように、静的解析ツールを活用することで、Pythonコードのデバッグ作業を助け、より効率的なプログラミングを可能にします。

まとめ

Pythonデバッグの手順とテクニックを7つ紹介しました。

これらを活用することで、Pythonプログラミングがよりスムーズになります。

また、これらの手法は初心者でも簡単に理解し、活用することが可能です。

特に、静的解析ツールを活用することで、プログラムの問題点を早期に発見し、効率的に修正することが可能となります。

プログラミングにおいてデバッグ技術は欠かせないスキルですので、ぜひこの記事を参考にしてみてください。