# 28.10. `traceback` --- スタックトレースの表示または取得

このモジュールは Python プログラムのスタックトレースを抽出し、書式を整え、表示するための標準インターフェースを提供します。モジュールがスタックトレースを表示するとき、Python インタープリタの動作を正確に模倣します。インタープリタの"ラッパー"の場合のように、プログラムの制御の元でスタックトレースを表示したいと思ったときに役に立ちます。

モジュールは traceback オブジェクトを使います --- これは変数 `sys.exc_traceback` (非推奨)と `sys.last_traceback` に保存され、 `sys.exc_info()` から三番目の項目として返されるオブジェクト型です。

このモジュールでは以下の関数を定義しています:

`traceback.``print_tb`(tb[, limit[, file]])

  トレースバックオブジェクト tb から limit までのスタックトレース項目を出力します。 limit が省略されるか `None` の場合は、すべての項目が表示されます。 file が省略されるか `None` の場合は、 `sys.stderr` へ出力されます。それ以外の場合は、出力を受けるためのオープンされたファイルまたはファイル風 (file-like) オブジェクトでなければなりません。

`traceback.``print_exception`(etype, value, tb[, limit[, file]])

  例外情報とトレースバック tb から limit までのスタックトレース項目を file へ出力します。これは以下のような点で `print_tb()` とは異なります: (1) tb が `None` でない場合は、ヘッダ `Traceback (most recent call last):` を出力します。 (2) スタックトレースの後に例外 etype と value を出力します。 (3) etype が `SyntaxError` であり、 value が適切な形式の場合は、エラーのおおよその位置を示すカレットを付けて構文エラーが起きた行を出力します。

`traceback.``print_exc`([limit[, file]])

  これは `print_exception(sys.exc_type, sys.exc_value, sys.exc_traceback, limit, file)` の省略表現です。 (非推奨の変数を使う代わりにスレッドセーフな方法で同じ情報を引き出すために、実際には `sys.exc_info()` を使います。)

`traceback.``format_exc`([limit])

  これは、`print_exc(limit)` に似ていますが、ファイルに出力する代わりに文字列を返します。

  バージョン 2.4 で追加.

`traceback.``print_last`([limit[, file]])

  `print_exception(sys.last_type, sys.last_value, sys.last_traceback, limit, file)` の省略表現です。一般に、例外が対話的なプロンプトに達した後にだけ機能します (`sys.last_type` 参照)。

`traceback.``print_stack`([f[, limit[, file]]])

  This function prints a stack trace from its invocation point. The optional f argument can be used to specify an alternate stack frame to start. The optional limit and file arguments have the same meaning as for `print_exception()`.

`traceback.``extract_tb`(tb[, limit])

  トレースバックオブジェクト tb から limit まで取り出された"前処理済み"スタックトレース項目のリストを返します。スタックトレースの代わりの書式設定を行うために役に立ちます。limit が省略されるか `None` の場合は、すべての項目が取り出されます。"前処理済み"スタックトレース項目とは4要素のタプル (filename, line number, function name, text) で、スタックトレースに対して通常出力される情報を表しています。text は前後の空白を取り除いた文字列です。ソースが利用できない場合は `None` です。

`traceback.``extract_stack`([f[, limit]])

  現在のスタックフレームから生のトレースバックを取り出します。戻り値は `extract_tb()` と同じ形式です。オプションの f と limit 引数は `print_stack()` と同じ意味を持ちます。

`traceback.``format_list`(extracted_list)

  `extract_tb()` または `extract_stack()` が返すタプルのリストが与えられると、出力の準備を整えた文字列のリストを返します。結果として生じるリストの中の各文字列は、引数リストの中の同じインデックスの要素に対応します。各文字列は末尾に改行が付いています。さらに、ソーステキスト行が `None` でないそれらの要素に対しては、文字列は内部に改行を含んでいるかもしれません。

`traceback.``format_exception_only`(etype, value)

  トレースバックの例外部分をフォーマットします。 引数は `sys.last_type` と `sys.last_value` で与えられるような、例外の型 etype と値 value です。 戻り値はそれぞれが改行で終わっている文字列のリストです。 通常、リストは一つの文字列を含んでいます。 しかし、 `SyntaxError` 例外に対しては、 (出力されるときに) 構文エラーが起きた場所についての詳細な情報を示す行をいくつか含んでいます。 どの例外が起きたのかを示すメッセージは、常にリストの最後の文字列です。

`traceback.``format_exception`(etype, value, tb[, limit])

  スタックトレースと例外情報を書式化します。引数は `print_exception()` の対応する引数と同じ意味を持ちます。戻り値は文字列のリストで、それぞれの文字列は改行で終わり、そのいくつかは内部に改行を含みます。これらの行が連結されて出力される場合は、厳密に `print_exception()` と同じテキストが出力されます。

`traceback.``format_tb`(tb[, limit])

  `format_list(extract_tb(tb, limit))` の省略表現です。

`traceback.``format_stack`([f[, limit]])

  `format_list(extract_stack(f, limit))` の省略表現です。

`traceback.``tb_lineno`(tb)

  トレースバックオブジェクトに設定された現在の行番号を返します。 Python 2.3より前のバージョンでは、 `-O` フラグが渡されたときに `tb.tb_lineno` が正しく更新されなかったため、この関数は必要でした。 2.3以降のバージョンでは不要です。

## 28.10.1. トレースバックの例

この簡単な例では基本的な read-eval-print ループを実装しています。標準的な Python の対話インタープリタループに似ていますが、 Python のものより便利ではありません。インタープリタループのより完全な実装については、 `code` モジュールを参照してください。

    import sys, traceback

    def run_user_code(envdir):
        source = raw_input(">>> ")
        try:
            exec source in envdir
        except:
            print "Exception in user code:"
            print '-'*60
            traceback.print_exc(file=sys.stdout)
            print '-'*60

    envdir = {}
    while 1:
        run_user_code(envdir)

次の例は例外とトレースバックの出力並びに形式が異なることを示します:

    import sys, traceback

    def lumberjack():
        bright_side_of_death()

    def bright_side_of_death():
        return tuple()[0]

    try:
        lumberjack()
    except IndexError:
        exc_type, exc_value, exc_traceback = sys.exc_info()
        print "*** print_tb:"
        traceback.print_tb(exc_traceback, limit=1, file=sys.stdout)
        print "*** print_exception:"
        traceback.print_exception(exc_type, exc_value, exc_traceback,
                                  limit=2, file=sys.stdout)
        print "*** print_exc:"
        traceback.print_exc()
        print "*** format_exc, first and last line:"
        formatted_lines = traceback.format_exc().splitlines()
        print formatted_lines[0]
        print formatted_lines[-1]
        print "*** format_exception:"
        print repr(traceback.format_exception(exc_type, exc_value,
                                              exc_traceback))
        print "*** extract_tb:"
        print repr(traceback.extract_tb(exc_traceback))
        print "*** format_tb:"
        print repr(traceback.format_tb(exc_traceback))
        print "*** tb_lineno:", exc_traceback.tb_lineno

この例の出力は次のようになります:

    *** print_tb:
      File "<doctest...>", line 10, in <module>
        lumberjack()
    *** print_exception:
    Traceback (most recent call last):
      File "<doctest...>", line 10, in <module>
        lumberjack()
      File "<doctest...>", line 4, in lumberjack
        bright_side_of_death()
    IndexError: tuple index out of range
    *** print_exc:
    Traceback (most recent call last):
      File "<doctest...>", line 10, in <module>
        lumberjack()
      File "<doctest...>", line 4, in lumberjack
        bright_side_of_death()
    IndexError: tuple index out of range
    *** format_exc, first and last line:
    Traceback (most recent call last):
    IndexError: tuple index out of range
    *** format_exception:
    ['Traceback (most recent call last):\n',
     '  File "<doctest...>", line 10, in <module>\n    lumberjack()\n',
     '  File "<doctest...>", line 4, in lumberjack\n    bright_side_of_death()\n',
     '  File "<doctest...>", line 7, in bright_side_of_death\n    return tuple()[0]\n',
     'IndexError: tuple index out of range\n']
    *** extract_tb:
    [('<doctest...>', 10, '<module>', 'lumberjack()'),
     ('<doctest...>', 4, 'lumberjack', 'bright_side_of_death()'),
     ('<doctest...>', 7, 'bright_side_of_death', 'return tuple()[0]')]
    *** format_tb:
    ['  File "<doctest...>", line 10, in <module>\n    lumberjack()\n',
     '  File "<doctest...>", line 4, in lumberjack\n    bright_side_of_death()\n',
     '  File "<doctest...>", line 7, in bright_side_of_death\n    return tuple()[0]\n']
    *** tb_lineno: 10

次の例は、スタックの print と format の違いを示しています:

    >>> import traceback
    >>> def another_function():
    ...     lumberstack()
    ...
    >>> def lumberstack():
    ...     traceback.print_stack()
    ...     print repr(traceback.extract_stack())
    ...     print repr(traceback.format_stack())
    ...
    >>> another_function()
      File "<doctest>", line 10, in <module>
        another_function()
      File "<doctest>", line 3, in another_function
        lumberstack()
      File "<doctest>", line 6, in lumberstack
        traceback.print_stack()
    [('<doctest>', 10, '<module>', 'another_function()'),
     ('<doctest>', 3, 'another_function', 'lumberstack()'),
     ('<doctest>', 7, 'lumberstack', 'print repr(traceback.extract_stack())')]
    ['  File "<doctest>", line 10, in <module>\n    another_function()\n',
     '  File "<doctest>", line 3, in another_function\n    lumberstack()\n',
     '  File "<doctest>", line 8, in lumberstack\n    print repr(traceback.format_stack())\n']

最後の例は、残りの幾つかの関数のデモをします:

    >>> import traceback
    >>> traceback.format_list([('spam.py', 3, '<module>', 'spam.eggs()'),
    ...                        ('eggs.py', 42, 'eggs', 'return "bacon"')])
    ['  File "spam.py", line 3, in <module>\n    spam.eggs()\n',
     '  File "eggs.py", line 42, in eggs\n    return "bacon"\n']
    >>> an_error = IndexError('tuple index out of range')
    >>> traceback.format_exception_only(type(an_error), an_error)
    ['IndexError: tuple index out of range\n']