Как я могу гарантировать, что Python формирует исключение с полным обратным отслеживанием? (и почему я получаю частичный?) - PullRequest
0 голосов
/ 22 января 2020

Я получаю странную ситуацию, когда Python выдает исключение с частичным отслеживанием. Или, по крайней мере, мне это кажется странным.

Я хочу знать, почему и как это исправить - я каким-то образом теряю верхние уровни информации стека, если улавливаю исключение.

Вот моя тестовая программа:

# tracebacktest2.py

import sys
import traceback
import bazlib

def bar(i):
    try:
        return bazlib.baz(i, 7, "No sevens!")
    except:
        ty, value, trbk = sys.exc_info()
        print "TR3 traceback=%s" % ''.join(traceback.format_tb(trbk))
        raise

def foo():
    for i in xrange(10):
        bar(i)

if __name__ == '__main__':
    foo()

# bazlib.py

import sys
import traceback

def baz(i, i0, errmsg):
    if i == i0:
        try:
            raise ValueError(errmsg)
        except:
            ty, value, trbk = sys.exc_info()
            print "TR1 traceback=%s" % ''.join(traceback.format_stack())
            print "TR2 traceback=%s" % ''.join(traceback.format_tb(trbk))
            raise
    return i

, которая выполняется:

C:\tmp\python\jyexcept>python tracebacktest2.py
TR1 traceback=  File "tracebacktest2.py", line 20, in <module>
    foo()
  File "tracebacktest2.py", line 17, in foo
    bar(i)
  File "tracebacktest2.py", line 9, in bar
    return bazlib.baz(i, 7, "No sevens!")
  File "C:\tmp\python\jyexcept\bazlib.py", line 12, in baz
    print "TR1 traceback=%s" % ''.join(traceback.format_stack())

TR2 traceback=  File "C:\tmp\python\jyexcept\bazlib.py", line 9, in baz
    raise ValueError(errmsg)

TR3 traceback=  File "tracebacktest2.py", line 9, in bar
    return bazlib.baz(i, 7, "No sevens!")
  File "C:\tmp\python\jyexcept\bazlib.py", line 9, in baz
    raise ValueError(errmsg)

Traceback (most recent call last):
  File "tracebacktest2.py", line 20, in <module>
    foo()
  File "tracebacktest2.py", line 17, in foo
    bar(i)
  File "tracebacktest2.py", line 9, in bar
    return bazlib.baz(i, 7, "No sevens!")
  File "C:\tmp\python\jyexcept\bazlib.py", line 9, in baz
    raise ValueError(errmsg)
ValueError: No sevens!
  • TR1 (traceback.format_stack()) получает полный стек в предложении except , но включает точку выполнения, потому что я не спрашиваю о трассировке конкретного исключения.
  • TR2 получает только самый верхний кадр стека, до текущей функции
  • TR3 получает другой частичный стек trace, вплоть до текущей функции
  • Поскольку я повторно вызываю исключение и не перехватываю его, Python печатает полную трассировку стека исключения.

Можно ли как-нибудь получить доступ к этой полной трассировке стека исключения, но внутри блока except, который находится в кадре промежуточного стека?

(я думал, что это был Jython странно, но Jython 2.5.3 и Python 2.7, похоже, ведут себя одинаково.) * 10 29 *

Я могу получить такое же поведение из одного файла (по какой-то причине я думал, что это не так):

# tracebacktest3.py

import sys
import traceback

def baz(i, i0, errmsg):
    if i == i0:
        try:
            raise ValueError(errmsg)
        except:
            ty, value, trbk = sys.exc_info()
            print "TR1 traceback=%s" % ''.join(traceback.format_stack())
            print "TR2 traceback=%s" % ''.join(traceback.format_tb(trbk))
            raise
    return i

def bar(i):
    try:
        return baz(i, 7, "No sevens!")
    except:
        ty, value, trbk = sys.exc_info()
        print "TR3 traceback=%s" % ''.join(traceback.format_tb(trbk))
        raise

def foo():
    for i in xrange(10):
        bar(i)

if __name__ == '__main__':
    foo()
...