Конструкция try except удаляет мою переменную. Зачем?

Вот код

ex_value = ''
try:
    2/0
except ValueError as ex_value:
    print(ex_value)
except ZeroDivisionError as ex_value:
    print(ex_value)
finally:
    print(ex_value)

Вот печать в терминале

division by zero
Traceback (most recent call last):

  File "C:\Users\Vasil\anaconda3\envs\AMZ\lib\site-packages\spyder_kernels\py3compat.py", line 356, in compat_exec
    exec(code, globals, locals)

  File "d:\onedrive\projects\chud_amaz\soft_in_dev\moduled_way_oop\code_questions\try_except_var_in_finally.py", line 15, in <module>
    print(ex_value)

NameError: name 'ex_value' is not defined

Как распечатать в finally сообщение и зачем try удаляет мою переменную ex_value.


Ответы (3 шт):

Автор решения: Leonid

Так вы назвали ошибку именем переменной, смените обзывание ошибки другим именем:

ex_value = ''
try:
    2/0
except ValueError as ve:
    print(ex_value)
except ZeroDivisionError as zde:
    print(ex_value)
finally:
    print(ex_value)
→ Ссылка
Автор решения: Danis

Из документации:

Exceptions are cleared because with the traceback attached to them, they form a reference cycle with the stack frame, keeping all locals in that frame alive until the next garbage collection occurs.

→ Ссылка
Автор решения: Павел

Зачем try удаляет мою переменную ex_value

Как уже ответил @Danis, это происходит, потому что все объекты исключений, созданные внутри блока try-except (и также сохраненные в переменные оператором as), очищаются при завершении блоков.

Как распечатать в finally сообщение

Не совсем понимаю зачем это может быть нужно, но в принципе достаточно сохранять объект исключения в другой переменной, из которой потом его и выводить.

try:
    2/0
except ValueError as z:
    print(ex_value := z)
except ZeroDivisionError as z:
    print(ex_value := z)
finally:
    print(ex_value)

Вывод:

division by zero
division by zero
→ Ссылка