Bir istisna yakaladığımda, tür, dosya ve satır numarasını nasıl alabilirim?


252

Aşağıdaki gibi yazdırılacak bir istisna yakalamak:

Traceback (most recent call last):
  File "c:/tmp.py", line 1, in <module>
    4 / 0
ZeroDivisionError: integer division or modulo by zero

Biçimlendirmek istiyorum:

ZeroDivisonError, tmp.py, 1

5
Yerleşik geri izleme modülünü kullanın .
Ned Deily

İstisna olan yerlerde kod satırını yazdırmak da yararlı olabilir: bkz. Stackoverflow.com/questions/14519177/…
Apogentus

Yanıtlar:


381
import sys, os

try:
    raise NotImplementedError("No error")
except Exception as e:
    exc_type, exc_obj, exc_tb = sys.exc_info()
    fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
    print(exc_type, fname, exc_tb.tb_lineno)

51
Sys.exc_info () öğesini yerel değişkenlere açma konusunda dikkatli olmalısınız, çünkü işleyici dışında bir istisna alırsanız, yerel değişkenler GC'd değil dairesel bir referansta tutulabilir. En iyi yöntem, her zaman bunun yerine yalnızca sys.exc_info () 'un dilimlerini kullanmaktır. Veya diğer posterlerin önerdiği gibi geri izleme gibi diğer modülleri kullanın.
Daniel Pryden

1
tb sadece exc_tb mi? ve os.path.split (blabla) [1] os.path.basename (balbal)
sunqiang

4
@Basj: sys.exc_info () [0] .__ name__ ile türün açık adını alırsınız.
Johannes Overmann

5
@DanielPryden Python dokümanları da aynı açma yöntemini kullanıyor docs.python.org/2/library/traceback.html#traceback-examples
kullanıcı

3
@RobM: Evet, iş parçacığı için güvenli. sys.exc_info()önceki API'de iş parçacığı güvenliği sorunları ile başa çıkmak için tanıtıldı. Çıkışı hem mevcut iş parçacığına hem de mevcut yığın çerçevesine özgüdür.
user2357112 Monica

126

Benim için çalışan en basit form.

import traceback

try:
    print(4/0)
except ZeroDivisionError:
    print(traceback.format_exc())

Çıktı

Traceback (most recent call last):
  File "/path/to/file.py", line 51, in <module>
    print(4/0)
ZeroDivisionError: division by zero

Process finished with exit code 0

7
op'un

5
bu konuda ne güçlü?
jouell

1
@jouell Hey, bazen çok süslü kelimeler kullanmayı seviyorum :)
Rishav

Temiz ve etkili.
Paylaştığınız

49

Traceback.format_exception () ve çağrılan / ilgili işlevler için Kaynak (Py v2.7.3) çok yardımcı olur. Utanç verici bir şekilde, her zaman Kaynağı okumayı unuturum . Bunu sadece boşuna benzer ayrıntılar aradıktan sonra yaptım. Basit bir soru, "İstisna için Python ile aynı çıktıyı nasıl yeniden oluşturabilirim?" Bu, aradıklarına% 90 + herhangi bir kişi getirecektir. Hayal kırıklığına uğramış, bu örneği buldum. Umarım başkalarına yardımcı olur. (Kesinlikle bana yardımcı oldu! ;-)

import sys, traceback

traceback_template = '''Traceback (most recent call last):
  File "%(filename)s", line %(lineno)s, in %(name)s
%(type)s: %(message)s\n''' # Skipping the "actual line" item

# Also note: we don't walk all the way through the frame stack in this example
# see hg.python.org/cpython/file/8dffb76faacc/Lib/traceback.py#l280
# (Imagine if the 1/0, below, were replaced by a call to test() which did 1/0.)

try:
    1/0
except:
    # http://docs.python.org/2/library/sys.html#sys.exc_info
    exc_type, exc_value, exc_traceback = sys.exc_info() # most recent (if any) by default

    '''
    Reason this _can_ be bad: If an (unhandled) exception happens AFTER this,
    or if we do not delete the labels on (not much) older versions of Py, the
    reference we created can linger.

    traceback.format_exc/print_exc do this very thing, BUT note this creates a
    temp scope within the function.
    '''

    traceback_details = {
                         'filename': exc_traceback.tb_frame.f_code.co_filename,
                         'lineno'  : exc_traceback.tb_lineno,
                         'name'    : exc_traceback.tb_frame.f_code.co_name,
                         'type'    : exc_type.__name__,
                         'message' : exc_value.message, # or see traceback._some_str()
                        }

    del(exc_type, exc_value, exc_traceback) # So we don't leave our local labels/objects dangling
    # This still isn't "completely safe", though!
    # "Best (recommended) practice: replace all exc_type, exc_value, exc_traceback
    # with sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]

    print
    print traceback.format_exc()
    print
    print traceback_template % traceback_details
    print

Bu sorgunun özel cevabı:

sys.exc_info()[0].__name__, os.path.basename(sys.exc_info()[2].tb_frame.f_code.co_filename), sys.exc_info()[2].tb_lineno

1
değişim 'message' : exc_value.messageiçin 'message' : str(exc_value)PY3 için
user2682863

34

Aşağıda, istisnanın gerçekleştiği satır numarasını gösteren bir örnek bulunmaktadır.

import sys
try:
    print(5/0)
except Exception as e:
    print('Error on line {}'.format(sys.exc_info()[-1].tb_lineno), type(e).__name__, e)

print('And the rest of program continues')
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.