Saya akan melakukannya seperti ini sehingga mengubah jenisnya foo()tidak perlu juga mengubahnya bar().
def foo():
try:
raise IOError('Stuff')
except:
raise
def bar(arg1):
try:
foo()
except Exception as e:
raise type(e)(e.message + ' happens at %s' % arg1)
bar('arg1')
Traceback (most recent call last):
File "test.py", line 13, in <module>
bar('arg1')
File "test.py", line 11, in bar
raise type(e)(e.message + ' happens at %s' % arg1)
IOError: Stuff happens at arg1
Perbarui 1
Berikut ini sedikit modifikasi yang mempertahankan traceback asli:
...
def bar(arg1):
try:
foo()
except Exception as e:
import sys
raise type(e), type(e)(e.message +
' happens at %s' % arg1), sys.exc_info()[2]
bar('arg1')
Traceback (most recent call last):
File "test.py", line 16, in <module>
bar('arg1')
File "test.py", line 11, in bar
foo()
File "test.py", line 5, in foo
raise IOError('Stuff')
IOError: Stuff happens at arg1
Perbarui 2
Untuk Python 3.x, kode update pertama saya adalah sintaksis benar ditambah gagasan memiliki messageatribut pada BaseExceptionitu ditarik dalam perubahan ke PEP 352 pada 2012/05/16 (update pertama saya telah diposting pada 2012-03-12) . Jadi saat ini, dengan Python 3.5.2, Anda perlu melakukan sesuatu di sepanjang baris ini untuk mempertahankan traceback dan bukan hardcode jenis pengecualian dalam fungsi bar(). Perhatikan juga bahwa akan ada baris:
During handling of the above exception, another exception occurred:
di pesan traceback ditampilkan.
...
def bar(arg1):
try:
foo()
except Exception as e:
import sys
raise type(e)(str(e) +
' happens at %s' % arg1).with_traceback(sys.exc_info()[2])
bar('arg1')
Perbarui 3
Sebuah commenter bertanya apakah ada cara yang akan bekerja di kedua Python 2 dan 3. Meskipun jawabannya mungkin tampaknya menjadi "Tidak" karena perbedaan sintaks, ada adalah cara sekitar bahwa dengan menggunakan fungsi pembantu seperti reraise()di sixadd pada modul. Jadi, jika Anda lebih suka tidak menggunakan pustaka karena alasan tertentu, di bawah ini adalah versi mandiri yang disederhanakan.
Perhatikan juga, bahwa karena pengecualian dijalankan ulang dalam reraise()fungsi, itu akan muncul di traceback apa pun yang dimunculkan, tetapi hasil akhirnya adalah yang Anda inginkan.
import sys
if sys.version_info.major < 3:
exec("""def reraise(exc_type, exc_value, exc_traceback=None):
raise exc_type, exc_value, exc_traceback""")
else:
def reraise(exc_type, exc_value, exc_traceback=None):
if exc_value is None:
exc_value = exc_type()
if exc_value.__traceback__ is not exc_traceback:
raise exc_value.with_traceback(exc_traceback)
raise exc_value
def foo():
try:
raise IOError('Stuff')
except:
raise
def bar(arg1):
try:
foo()
except Exception as e:
reraise(type(e), type(e)(str(e) +
' happens at %s' % arg1), sys.exc_info()[2])
bar('arg1')
messageatribut Exception, saya menemukan pertanyaan SO ini, BaseException.message tidak digunakan lagi di Python 2.6 , yang tampaknya menunjukkan penggunaannya sekarang tidak disarankan (dan mengapa tidak ada di dokumen).