Відповідь на це питання залежить від версії 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і спеціальний виняток для зберігання певної інформації. Але я не зовсім впевнений, як це буде працювати.
Правду кажучи, вилов та повернення винятку - це щось незвичне. Це може бути ознакою того, що вам все одно потрібно переробляти.