2013-06-20 2 views
2

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

def do_not_call_on_one(i): 
    if i == 1: 
     raise ValueError("You never listen.") 

    print "Success!" 

do_not_call_on_one(1) 

На excution, вы увидите следующее отслеживающий:

Traceback (most recent call last): 
    File "test.py", line 7, in <module> 
    do_not_call_on_one(1) 
    File "test.py", line 3, in do_not_call_on_one 
    raise ValueError("You never listen.") 
ValueError: You never listen. 

Есть ли какой-нибудь способ манипулировать стек вызовов, так что ошибка вылетает из линия, которая на самом деле вызывает проблему, как и ?:

Traceback (most recent call last): 
    File "test.py", line 7, in <module> 
    do_not_call_on_one(1) 
ValueError: You never listen. 

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

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

Обновления

Есть buitins, которые копируют эту функциональность:

# In test.py: 
int('a') 

# Executing 'python test.py' yields: 
Traceback (most recent call last): 
    File "test.py", line 1, in <module> 
    int('a') 
ValueError: invalid literal for int() with base 10: 'a' 

Примечания: отслеживающие не опускается в функцию int(), чтобы отобразить кучу ненужных областей (особенно бесполезен raise ValueError сам).

+0

Полезно знать, где именно была заброшена ошибка, о которой вы могли бы избавиться. Если бы одна и та же ошибка могла быть сброшена из двух разных точек, вы точно не знаете, где искать. – FastTurtle

+0

Спасибо JAB. Я должен работать над своим поиском-fu: '( – gepoch

+1

Нет, это не дубликат. С одной стороны, связанная статья с точки зрения библиотеки USER, которая не хочет видеть внутренние элементы библиотеки, это с точки зрения из библиотеки AUTHOR, которая не хочет делать SHOW внутренности, а для другого - это QUITE, что нужно сделать: Perl делает это все время в модуле Carp. Не похоже на Python? – Ian

ответ

0

В консоли вывод заключается в следующем:

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 3, in do_not_call_on_one 
ValueError: You never listen. 
1

Я хотел бы предложить отлов исключения в точке вы хотите быть в верхней части стеки вызовов, а затем поднять новое исключение оберточного старый (так что вы можете ссылаться на исходный стек вызовов, чтобы узнать, какое исключение действительно вызвало проблему, ведь что происходит, когда print "Success!" терпит неудачу, потому что, скажем, кто-то установил sys.stdout = int?).


После некоторого просмотра, кажется, что https://stackoverflow.com/a/2615442/138772 является именно такой ответ вы хотите.

+0

OP хочет что-то с другой стороны граница интерфейса библиотеки. – Ian

3

tl; dr: возможно, да, но я не могу себе представить, что это хорошая идея.

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

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

Во-вторых, я не думаю, что вы можете определить «правильную» область применения очень хорошо. Вы можете себе представить, что он всегда должен быть поднят в области вашего звонящего, потому что явно не ошибка вашего. Ну, а что, если это не их ошибка либо? Должны ли каждая функция просто поднять руки и сказать «не моя вина», когда возникает исключение? Довольно скоро наши стоп-кадры ничего не скажут.

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

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

+0

На самом деле очень легко настроить нечитаемые трассировки исключений в Python, как я только что открыл. http://docs.python.org/2/library/sys.html#sys.excepthook «Обработка таких вершин Исключительные исключения могут быть настроены путем назначения другой функции с тремя аргументами 'sys.excepthook'." – JAB