Відповідь на це питання залежить від версії Python, яку ви використовуєте.
У Python 3
Це просто: винятки оснащені __traceback__
атрибутом, який містить прослідкування. Цей атрибут також можна записати, і його можна зручно встановити, використовуючи with_traceback
метод винятків:
raise Exception("foo occurred").with_traceback(tracebackobj)
Ці функції мінімально описані як частина raise
документації.
Вся заслуга за цю частину відповіді повинна мати Виктор, який першим опублікував цю інформацію . Я включаю його сюди лише тому, що ця відповідь застрягла вгорі, а Python 3 стає все більш поширеним.
У Python 2
Це прикро складно. Проблема із зворотними зворотами полягає в тому, що вони мають посилання на фрейми стеків, а фрейми стеків мають посилання на зворотні сигнали, які мають посилання на фрейми стеків, на які є посилання на ... Ви отримуєте ідею. Це спричиняє проблеми зі збирачем сміття. (Дякую Екатмуру, що вперше вказав на це.)
Хорошим способом вирішити це було б хірургічним шляхом розірвати цикл після відмови від цього except
пункту, що і робить Python 3. Рішення Python 2 набагато потворніше: вам надається спеціальна функція sys.exc_info()
, яка працює лише всередині except
пункту . Він повертає кортеж, що містить виняток, тип винятку та зворотний зворотний бік будь-якого винятку в даний час обробляється.
Отже, якщо ви перебуваєте всередині except
пункту, ви можете використовувати результат sys.exc_info()
разом із traceback
модулем, щоб робити різні корисні речі:
>>> import sys, traceback
>>> def raise_exception():
... try:
... raise Exception
... except Exception:
... ex_type, ex, tb = sys.exc_info()
... traceback.print_tb(tb)
... finally:
... del tb
...
>>> raise_exception()
File "<stdin>", line 3, in raise_exception
Але як вказує ваша редакція, ви намагаєтеся отримати зворотний слід, який був би надрукований, якби не було оброблено ваше виключення, після того, як воно вже було оброблене. Це набагато складніше питання. На жаль, sys.exc_info
повертається, (None, None, None)
коли не обробляється жоден виняток. Інші пов'язані sys
атрибути також не допомагають. sys.exc_traceback
є застарілим та невизначеним, коли не обробляються винятки; sys.last_traceback
здається ідеальним, але він, як видається, визначається лише під час інтерактивних сесій.
Якщо ви можете керувати тим, як збільшується виняток, ви можете використовувати inspect
і спеціальний виняток для зберігання певної інформації. Але я не зовсім впевнений, як це буде працювати.
Правду кажучи, вилов та повернення винятку - це щось незвичне. Це може бути ознакою того, що вам все одно потрібно переробляти.