Как скрыть последний звонок от отслеживания?

#python #error-handling #traceback

Вопрос:

У меня есть следующий код

 def _raise_exception(exception):
    raise exception

def require_odd(n):
    if n % 2 == 0:
        _raise_exception(ValueError("n must be odd"))

print(require_odd(2))
 

Когда я запускаю его, он показывает

 Traceback (most recent call last):
  File "main.py", line 31, in <module>
    print(require_odd(2))
  File "main.py", line 29, in require_odd
    _raise_exception(ValueError("n must be odd"))
  File "main.py", line 25, in _raise_exception
    raise exception
ValueError: n must be odd
 

Поскольку последняя строка кода из обратной трассировки избыточна, как мне вызвать исключение, чтобы оно показывало следующее?

 Traceback (most recent call last):
  File "main.py", line 31, in <module>
    print(require_odd(2))
ValueError: n must be odd
 

В настоящее время я занимаюсь этим:

 def _raise_exception(exception):
    try:
        raise exception
    except Exception as e:
        # Remove the last two calls (from this function and from the caller of this function)
        stack_lines = traceback.format_stack()[:-2]

        # Get the exception lines that contains the "Traceback (most recent call last):" in
        # the first line and the "ValueError: n must be odd" in the last line
        exception_lines = traceback.format_exception(e.__class__, e, e.__traceback__)

        # Join the relevant lines, print to stderr and exit
        print(''.join(exception_lines[:1]   stack_lines   exception_lines[-1:]), file=sys.stderr)
        exit(1)

def require_odd(n):
    if n % 2 == 0:
        _raise_exception(ValueError("n must be odd"))

print(require_odd(2))
 

что действительно печатает

 Traceback (most recent call last):
  File "main.py", line 31, in <module>
    print(require_odd(2))
ValueError: n must be odd
 

Но это просто кажется случайным. Есть ли лучший способ?

Комментарии:

1. Я не совсем понимаю, что вы подразумеваете под «избыточным» здесь. Трассировка стека функционирует так, как можно было бы надеяться, — она сбрасывает весь стек вызовов. Это, как правило, считается хорошей вещью , и среда выполнения Python проходит через множество проблем, чтобы предоставить вам эту информацию…

Ответ №1:

Не могли бы вы исключить эту _raise_exception функцию?

Если бы ты просто убежал

 if n % 2 == 0: 
    raise ValueError("n must be odd") 
 

это устранило бы последнюю строку и стало бы ненужным шагом в этом процессе. Это не устранило бы среднюю линию, но, как правило, лучшие практики (о которых я знаю) заключаются в том, чтобы оставить стек в покое. Вам нужно как можно больше данных, когда что-то идет не так.

Дайте мне знать, если я что-то упущу, и я обновлю.

Комментарии:

1. Как вы сказали, это добавило raise ValueError("n must be odd") бы строку, которая , я думаю, является избыточной, так как последняя строка исключения ValueError: n must be odd , но если нет лучшего варианта, я думаю, мне придется с этим разобраться.

2. Просто кажется, что это большая работа, чтобы сделать что-то, что не является «красивым»для пользователя. Это немного избыточно, но, опять же, это дополнительная информация. И если вы ищете ошибку в более длинном стеке, наличие избыточности поможет вам легче привлечь ваше внимание.