Я хотел бы написать функцию на Python (2.6), которая может определить, вызывается ли она из кода обработки исключений где-то вверх по стеку.

Это для специализированного использования ведения журнала. В модуле Python logging вызывающая сторона должна явно указать, что информация об исключении должна быть зарегистрирована (либо путем вызова logger.exception(), либо с помощью ключевого слова exc_info). Я хотел бы, чтобы мой регистратор делал это автоматически, в зависимости от того, вызывается ли он из кода обработки исключений.

Я думал, что ответом может быть проверка sys.exc_info(), но она также возвращает информацию об исключении из уже обработанного исключения. (Из документов: "Эта функция возвращает кортеж из трех значений, которые дают информацию о исключение, которое в данный момент обрабатывается... Если текущий фрейм стека не обрабатывает исключение, информация берется из вызывающего фрейма стека или вызывающего его, и так далее, пока не будет найден фрейм стека, который обрабатывает исключение. Здесь «обработка исключения» определяется как «выполнение или выполнение условия исключения».'")

Кроме того, поскольку я хочу, чтобы это было прозрачно для вызывающей стороны, я не хочу использовать exc_clear() или что-либо еще в предложении except.

Как правильно это сделать?

3
Uncorroborated 27 Июл 2009 в 12:40
Как контекст вызова может быть неоднозначным? Вы определяете функцию, которая будет вызываться из исключения. Он всегда вызывается из исключения. В чем проблема? Пожалуйста, объясните, почему функция, предназначенная для вызова из исключения, не будет вызываться из исключения.
 – 
S.Lott
27 Июл 2009 в 13:55
Я не определял это как функцию, вызываемую из исключения. Это функция, которая может быть вызвана из исключения или может быть вызвана из исключения. Я хочу определить, в чем дело.
 – 
Uncorroborated
27 Июл 2009 в 15:23
1
Эммм... Что не так с определением вашей функции, чтобы она должна вызываться из исключения? Что мешает вам изменить определение функции, чтобы упростить это?
 – 
S.Lott
27 Июл 2009 в 16:00
Или "разветвите" вашу функцию на две: одна вызывается только из обработчика исключений, а другая - во всех остальных случаях (если я правильно понял).
 – 
mlvljr
13 Авг 2009 в 22:35

2 ответа

Если вы очищаете исключение, используя sys.exc_clear в своих обработчиках исключений, тогда sys.exc_info должно работать на вас. Например: если вы запустите следующий скрипт:

import sys

try:
    1 / 0
except:
    print sys.exc_info()
    sys.exc_clear()
print sys.exc_info()

Вы должны увидеть этот вывод:

(, ZeroDivisionError('integer division or modulo by zero',), )
(None, None, None)

Обновление: я не верю, что существует простой ("прозрачный") способ ответить на вопрос "Работает ли обработчик исключений?" без каких-либо проблем, и, на мой взгляд, не стоит заморачиваться только ради регистрации. Конечно, легко ответить на вопрос "Было ли возбуждено исключение (в этом потоке)?", даже для каждого стека-фрейма (см. документацию по объектам фреймов).

2
Vinay Sajip 27 Июл 2009 в 14:23
Спасибо, Винай, но я ищу способ сделать это прозрачным для вызывающего абонента; то есть, это не требует ничего особенного в предложении кроме. Я отредактирую вопрос, чтобы он был более конкретным.
 – 
Uncorroborated
27 Июл 2009 в 13:18

Как и все в Python, исключение — это объект. Следовательно, вы можете сохранить (слабую!) ссылку на последнее обработанное исключение, а затем использовать sys.exc_info(). Примечание: в случае многопоточного кода у вас могут возникнуть проблемы с этим подходом. И могут быть и другие угловые случаи.

Однако явное лучше, чем неявное; Вы действительно уверены, что обработка ведения журнала исключений так же, как и обычная, является хорошей функцией для добавления в вашу систему?
По моему скромному мнению, нет.

0
rob 27 Июл 2009 в 14:29