Jawaban atas pertanyaan ini bergantung pada versi Python yang Anda gunakan.
Dengan Python 3
Sederhana: pengecualian dilengkapi dengan __traceback__atribut yang berisi traceback. Atribut ini juga bisa ditulis, dan bisa diatur dengan mudah menggunakan with_tracebackmetode pengecualian:
raise Exception("foo occurred").with_traceback(tracebackobj)
Fitur-fitur ini secara minimal dijelaskan sebagai bagian dari raisedokumentasi.
Semua kredit untuk bagian jawaban ini harus diberikan kepada Vyctor, yang pertama kali memposting informasi ini . Saya memasukkannya di sini hanya karena jawaban ini tertahan di atas, dan Python 3 menjadi lebih umum.
Dengan Python 2
Ini sangat rumit. Masalah dengan tracebacks adalah bahwa mereka memiliki referensi ke frame stack, dan frame stack memiliki referensi ke traceback yang memiliki referensi ke frame stack yang memiliki referensi ke ... Anda mendapatkan idenya. Ini menyebabkan masalah bagi pengumpul sampah. (Terima kasih kepada ecatmur untuk pertama kali menunjukkan ini.)
Cara yang bagus untuk menyelesaikan ini adalah dengan memutus siklus setelah meninggalkan exceptklausa, yang dilakukan Python 3. Solusi Python 2 jauh lebih buruk: Anda diberikan fungsi ad-hoc sys.exc_info(), yang hanya bekerja di dalam except klausa . Ini mengembalikan tupel yang berisi pengecualian, jenis pengecualian, dan traceback untuk pengecualian apa pun yang saat ini ditangani.
Jadi jika Anda berada di dalam exceptklausa, Anda dapat menggunakan output sys.exc_info()bersama tracebackmodul untuk melakukan berbagai hal berguna:
>>> 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
Tapi seperti mengedit Anda menunjukkan, Anda mencoba untuk mendapatkan traceback yang akan telah dicetak jika pengecualian Anda belum ditangani, setelah itu telah sudah ditangani. Itu pertanyaan yang jauh lebih sulit. Sayangnya, sys.exc_infokembali (None, None, None)jika tidak ada pengecualian yang ditangani. sysAtribut terkait lainnya juga tidak membantu. sys.exc_tracebacktidak berlaku lagi dan tidak ditentukan saat tidak ada pengecualian yang ditangani; sys.last_tracebacktampak sempurna, tetapi tampaknya hanya ditentukan selama sesi interaktif.
Jika Anda dapat mengontrol bagaimana pengecualian dimunculkan, Anda mungkin dapat menggunakan inspectdan pengecualian khusus untuk menyimpan beberapa informasi. Tapi saya tidak sepenuhnya yakin bagaimana itu akan berhasil.
Sejujurnya, menangkap dan mengembalikan pengecualian adalah hal yang tidak biasa untuk dilakukan. Ini mungkin pertanda bahwa Anda perlu melakukan refactor.