tlndr: как сказать в функции, если она вызвана из блока except
(прямо/косвенно). python2.7/CPython.
Я использую python 2.7 и пытаюсь предоставить что-то похожее на py3 __context__
для моего настраиваемого класса исключений:
class MyErr(Exception):
def __init__(self, *args):
Exception.__init__(self, *args)
self.context = sys.exc_info()[1]
def __str__(self):
return repr(self.args) + ' from ' + repr(self.context)
Это работает нормально:
try:
1/0
except:
raise MyErr('bang!')
#>__main__.MyErr: ('bang!',) from ZeroDivisionError('integer division or modulo by zero',)
Иногда мне нужно MyErr
быть поднятым вне блока исключений. Это тоже хорошо:
raise MyErr('just so')
#>__main__.MyErr: ('just so',) from None
Если, однако, перед этим пунктом было обработано исключение, оно неправильно задано как контекст MyErr
:
try:
print xxx
except Exception as e:
pass
# ...1000 lines of code....
raise MyErr('look out')
#>__main__.MyErr: ('look out',) from NameError("name 'xxx' is not defined",) <-- BAD
Я думаю, причина в том, что sys.exc_info
просто возвращает "последнее", а не "текущее" исключение:
Эта функция возвращает кортеж из трех значений, которые предоставляют информацию об исключении, которое в настоящее время обрабатывается. <... > Здесь "обработка исключения" определяется как "выполнение или с выполнением предложения except".
Итак, мой вопрос: как определить, выполняет ли интерпретатор предложение except
(и не выполнял его в прошлом). Другими словами: существует ли способ узнать в MyErr.__init__
, если в стеке есть except
?
Мое приложение не переносимо, любые специальные хаки Cpython приветствуются.