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_traceback
metode pengecualian:
raise Exception("foo occurred").with_traceback(tracebackobj)
Fitur-fitur ini secara minimal dijelaskan sebagai bagian dari raise
dokumentasi.
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 except
klausa, 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 except
klausa, Anda dapat menggunakan output sys.exc_info()
bersama traceback
modul 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_info
kembali (None, None, None)
jika tidak ada pengecualian yang ditangani. sys
Atribut terkait lainnya juga tidak membantu. sys.exc_traceback
tidak berlaku lagi dan tidak ditentukan saat tidak ada pengecualian yang ditangani; sys.last_traceback
tampak sempurna, tetapi tampaknya hanya ditentukan selama sesi interaktif.
Jika Anda dapat mengontrol bagaimana pengecualian dimunculkan, Anda mungkin dapat menggunakan inspect
dan 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.