Python学習のエラーデバッグとテスト

13719 ワード

Python学習ディレクトリ
  • MacでPython 3を使う
  • Python学習データ型
  • Python学習の関数
  • Python学習の高級特性
  • Python学習の関数式プログラミング
  • Python学習のモジュール
  • Python学習の対象向けプログラミング
  • Python学習の対象向け高度プログラミング
  • Python学習のエラーデバッグとテスト
  • Python学習のIOプログラミング
  • Python学習のプロセスとスレッド
  • Python学習の正則
  • Python学習の常用モジュール
  • Python学習のネットワークプログラミング
  • プログラムの実行中、さまざまなエラーが発生します.Pythonには、エラー処理を支援する異常処理メカニズムが内蔵されています.

    エラー処理


    プログラムの実行中にエラーが発生した場合は、エラーコードを返すことを事前に約束することで、エラーの有無やエラーの原因を知ることができます.オペレーティングシステムが提供する呼び出しでは、エラーコードを返すのが一般的です.たとえばファイルを開く関数open()成功した場合はファイル記述子(整数)を返し、エラーが発生した場合は-1を返します.
    エラーコードでエラーが発生したかどうかを表すのは不便で、関数自体が返すべき正常な結果とエラーコードが混在しているため、呼び出し者は大量のコードでエラーが発生したかどうかを判断しなければならないため、高級言語には通常try...except...finally...のエラー処理メカニズムが内蔵されており、Pythonも例外ではない.

    try

    try:
        print('try...')
        r = 10 / 0
        print('result:', r)
    except ZeroDivisionError as e:
        print('except:', e)
    finally:
        print('finally...')
    print('END')
    

    一部のコードでエラーが発生する可能性があると判断した場合、tryでこのコードを実行することができ、エラーが発生した場合、後続のコードは実行されず、そのままエラー処理コード、すなわちexcept文ブロックにジャンプし、実行が完了except後、finally文ブロックがあれば、finally文ブロックを実行し、これで実行が完了する.
    Pythonのエラーも実はclassで、すべてのエラータイプはBaseExceptionから継承されているので、exceptを使用するときに注意しなければならないのは、そのタイプのエラーをキャプチャするだけでなく、そのサブクラスも「一網打尽」にすることです.

    呼び出しスタック


    エラーがキャプチャされていない場合は、常に上に投げ出され、最後にPython解釈器にキャプチャされ、エラーメッセージが印刷され、プログラムが終了します.見てみるとerr.py:
    # err.py:
    def foo(s):
        return 10 / int(s)
    
    def bar(s):
        return foo(s) * 2
    
    def main():
        bar('0')
    
    main()
    

    実行結果は次のとおりです.
    $ python3 err.py
    Traceback (most recent call last):
      File "err.py", line 11, in 
        main()
      File "err.py", line 9, in main
        bar('0')
      File "err.py", line 6, in bar
        return foo(s) * 2
      File "err.py", line 3, in foo
        return 10 / int(s)
    ZeroDivisionError: division by zero
    

    エラーの呼び出し関数チェーン全体が上から下に表示されます.

    レコードエラー


    エラーをキャプチャしなければ、Python解釈器にエラースタックを印刷させることは自然にできますが、プログラムも終了します.エラーをキャプチャできる以上、エラースタックを印刷し、エラーの原因を分析しながら、プログラムを実行し続けることができます.
    Python内蔵loggingモジュールは非常に簡単にエラーメッセージを記録できる:
    # err_logging.py
    
    import logging
    
    def foo(s):
        return 10 / int(s)
    
    def bar(s):
        return foo(s) * 2
    
    def main():
        try:
            bar('0')
        except Exception as e:
            logging.exception(e)
    
    main()
    print('END')
    

    上記のモジュールを実行します.
    $ python3 err_logging.py
    ERROR:root:division by zero
    Traceback (most recent call last):
      File "err_logging.py", line 13, in main
        bar('0')
      File "err_logging.py", line 9, in bar
        return foo(s) * 2
      File "err_logging.py", line 6, in foo
        return 10 / int(s)
    ZeroDivisionError: division by zero
    END
    

    エラーを投げ出す


    エラーはclassであるため、エラーをキャプチャすることはclassにキャプチャされたインスタンスです.したがって、エラーは空で発生するのではなく、意図的に作成され、投げ出されます.Pythonの内蔵関数は多くのタイプのエラーを投げ出し、私たちが自分で書いた関数もエラーを投げ出すことができます.
    エラーを投げ出す場合は、まず必要に応じて、エラーのclassを定義し、継承関係を選択し、次に、raise文でエラーのインスタンスを投げ出すことができます.
    # err_raise.py
    class FooError(ValueError):
        pass
    
    def foo(s):
        n = int(s)
        if n==0:
            raise FooError('invalid value: %s' % s)
        return 10 / n
    
    foo('0')
    

    実行すると、自分たちが定義したエラーを最後に追跡できます.
    $ python3 err_raise.py 
    Traceback (most recent call last):
      File "err_throw.py", line 11, in 
        foo('0')
      File "err_throw.py", line 8, in foo
        raise FooError('invalid value: %s' % s)
    __main__.FooError: invalid value: 0
    

    最後に、別のエラー処理方法を見てみましょう.
    # err_reraise.py
    
    def foo(s):
        n = int(s)
        if n==0:
            raise ValueError('invalid value: %s' % s)
        return 10 / n
    
    def bar():
        try:
            foo('0')
        except ValueError as e:
            print('ValueError!')
            raise
    
    bar()
    
    bar()関数では、エラーをキャプチャしているのに、1つValueError!を印刷してから、またエラーを通過raise文を投げ出してしまいました.
    実はこのような誤った処理方法は病気ではないだけでなく、かなりよく見られます.エラーをキャプチャする目的は記録するだけで、後続の追跡に便利です.しかし,現在の関数ではこのエラーをどのように処理すべきか分からないため,最上位呼び出し者に処理させ続けるのが最も適切である.例えば、従業員が一つの問題を処理できないときは、問題を彼のボスに投げて、もし彼のボスも処理できないならば、ずっと上に投げて、最終的にCEOに投げて処理します.raise文はパラメータを持たないと現在のエラーをそのまま投げ出す.また、exceptraise1つのErrorは、1つのタイプのエラーを別のタイプに変換することもできます.
    try:
        10 / 0
    except ZeroDivisionError:
        raise ValueError('input error!')
    

    デバッグ


    プログラムが一度に書き終わり、正常に動作する確率は小さく、基本的に1%を超えない.いつもいろいろなバグを修正する必要があります.あるバグは簡単で、エラー情報を見るとわかります.あるバグは複雑で、エラーが発生したとき、どの変数の値が正しいのか、どの変数の値が間違っているのかを知る必要があります.そのため、デバッグプログラム全体の手段でバグを修復する必要があります.

    print()

    print()問題があるかもしれない変数を印刷してみます.

    断言する

    def foo(s):
        n = int(s)
        assert n != 0, 'n is zero!'
        return 10 / n
    
    def main():
        foo('0')
    
    assertという意味で、式n != 0であるべきTrueそうでなければ、プログラムが実行するロジックによって、後のコードが間違いになるに違いない.
    断言に失敗するとassert文自体が投げ出されるAssertionError.

    logging


    loggingでは、記録情報のレベルを指定できます.debuginfowarningerrorなどいくつかのレベルがあります.level=INFOを指定すると、logging.debug機能しません.同様に、level=WARNINGを指定すると、debuginfoが機能しなくなります.これにより、異なるレベルの情報を安心して出力したり、削除したりせずに、どのレベルの情報を出力するかを統一的に制御することができます.loggingもう1つの利点は、簡単な構成により、consoleやファイルなど、1つの文を同時に異なる場所に出力できることです.
    import logging
    logging.basicConfig(level=logging.INFO)
    
    s = '0'
    n = int(s)
    logging.info('n = %d' % n)
    print(10 / n)
    

    pdb


    Pythonのデバッガpdbは、プログラムを単一ステップで実行させ、いつでも実行状態を表示することができます.まずプログラムを用意します.
    # err.py
    s = '0'
    n = int(s)
    print(10 / n)
    

    次の操作を行います.
    $ python -m pdb err.py
    > /Users/michael/Github/learn-python3/samples/debug/err.py(2)()
    -> s = '0'
    

    パラメータ-m pdbで起動後、pdbは次の実行コード-> s = '0'にナビゲートします.コマンドを入力lコードを表示するには:
    (Pdb) l
      1     # err.py
      2  -> s = '0'
      3     n = int(s)
      4     print(10 / n)
    

    入力コマンドnコードはワンステップで実行できます.

    pdb.set_trace()


    この方法もpdbですが、単一ステップで実行する必要はありません.import pdb、そして、エラーが発生する可能性のある場所にpdb.set_trace()を置くだけで、ブレークポイントを設定できます.
    # err.py
    import pdb
    
    s = '0'
    n = int(s)
    pdb.set_trace() #  
    print(10 / n)
    

    コードを実行すると、プログラムは自動的にpdb.set_trace()pdbデバッグ環境に一時停止し、コマンドp変数を表示するか、コマンドcで実行を続行できます.

    IDE


    現在比較的良いPython IDEは以下の通りです.
    isual Studio Code:code.visualstudio.com/、Pythonプラグインをインストールする必要があります.
    PyCharm:www.jetbrains.com/pycharm/
    また、Eclipseにpydevプラグインを追加してPythonプログラムをデバッグすることもできます.

    ユニットテスト


    ユニットテストは、モジュール、関数、またはクラスに対して正確性検査を行うためのテスト作業です.

    ドキュメントテスト


    Pythonの公式ドキュメントをよく読むと、多くのドキュメントにサンプルコードが表示されます.
    これらのサンプルコードはPythonのインタラクティブな環境で入力して実行することができ、結果はドキュメントのサンプルコードの表示と一致します.
    これらのコードは、他の説明とコメントに書くことができ、いくつかのツールによってドキュメントを自動的に生成します.
    上一篇:Python学习のIOプログラミング