web-dev-qa-db-ja.com

PythonでAssertionErrorを処理し、どの行またはステートメントが発生したかを調べる方法は?

AssertionErrorsを処理して、スタックトレースの不要な部分をユーザーから隠し、エラーが発生した理由とユーザーが何をすべきかについてのメッセージを出力します。

assertブロック内でexceptが失敗した行またはステートメントを見つける方法はありますか?

try:
    assert True
    assert 7 == 7
    assert 1 == 2
    # many more statements like this
except AssertionError:
    print 'Houston, we have a problem.'
    print
    print 'An error occurred on line ???? in statement ???'
    exit(1)

すべてのassertステートメントにこれを追加する必要はありません。

assert 7 == 7, "7 == 7"

情報を繰り返すからです。

49
devtk

traceback モジュールを使用します。

import sys
import traceback

try:
    assert True
    assert 7 == 7
    assert 1 == 2
    # many more statements like this
except AssertionError:
    _, _, tb = sys.exc_info()
    traceback.print_tb(tb) # Fixed format
    tb_info = traceback.extract_tb(tb)
    filename, line, func, text = tb_info[-1]

    print('An error occurred on line {} in statement {}'.format(line, text))
    exit(1)
62
phihag

トレースバックモジュールとsys.exc_infoは、例外の原因を突き止めるには過剰です。これはすべてデフォルトのトレースバックにあります。そのため、exit(1)を呼び出す代わりに、単に再レイズします。

try:
    assert "birthday cake" == "ice cream cake", "Should've asked for pie"
except AssertionError:
    print 'Houston, we have a problem.'
    raise

これにより、問題のステートメントと行番号を含む次の出力が得られます。

Houston, we have a problem.
Traceback (most recent call last):
  File "/tmp/poop.py", line 2, in <module>
    assert "birthday cake" == "ice cream cake", "Should've asked for pie"
AssertionError: Should've asked for pie

同様に、ロギングモジュールを使用すると、例外(キャッチされて再発生することのない例外を含む)のトレースバックを簡単に記録できます。

import logging

try:
    assert False == True 
except AssertionError:
    logging.error("Nothing is real but I can't quit...", exc_info=True)
18
notpeter