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 приветствуются.