2009-08-14 18 views
158

Bắt một ngoại lệ đó sẽ in như thế này:Python Khi tôi bắt một ngoại lệ, làm cách nào để nhận được loại, tệp và số dòng?

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

Tôi muốn để định dạng nó thành:

ZeroDivisonError, tmp.py, 1 
+3

Sử dụng các module tích hợp [traceback] (http://docs.python.org/library/traceback.html). –

+0

Cũng có thể hữu ích khi in dòng mã, nơi xảy ra ngoại lệ: xem http://stackoverflow.com/questions/14519177/python-exception-handling-line-number/20264059#20264059 – Apogentus

Trả lời

239
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) 
+32

Bạn nên cẩn thận khi giải nén sys .exc_info() vào các biến cục bộ, vì nếu bạn có ngoại lệ trong trình xử lý ngoại lệ, các vars cục bộ có thể được giữ trong tham chiếu vòng tròn chứ không phải GC. Thực hành tốt nhất là luôn luôn chỉ sử dụng các slice của sys.exc_info() để thay thế. Hoặc sử dụng các mô-đun khác như traceback, như các áp phích khác đã đề xuất. –

+1

là tb chỉ exc_tb? và os.path.split (blabla) [1] là os.path.basename (balbal) – sunqiang

+14

Chủ đề này có an toàn không? – RobM

34

Source (Py v2.7.3) cho traceback.format_exception() và gọi/chức năng liên quan giúp rất nhiều. Xấu hổ, tôi luôn luôn quên Read the Source. Tôi chỉ làm như vậy cho điều này sau khi tìm kiếm các chi tiết tương tự vô ích. Một câu hỏi đơn giản, "Làm thế nào để tạo lại cùng một đầu ra như Python cho một ngoại lệ, với tất cả các chi tiết giống nhau?" Điều này sẽ nhận được bất cứ ai 90 +% cho bất cứ điều gì họ đang tìm kiếm. Thất vọng, tôi đã đưa ra ví dụ này. Tôi hy vọng nó sẽ giúp người khác. (Nó chắc chắn đã giúp tôi ;-)

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 

Trong câu trả lời cụ thể để truy vấn này:

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

@thatjuan: 43 dòng, không 50. Và đó là bao gồm khoảng cách vô cớ của tôi và ghi chú dồi dào ... trừ khi bạn thực sự hạnh phúc nó là "chỉ 50", trong trường hợp nó có thể được thực hiện để được "ngắn hơn nhiều" ... ? :> – pythonlarry

15

Dưới đây là một ví dụ về hiển thị số dòng về nơi ngoại lệ xảy ra.

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') 
5

Biểu mẫu đơn giản nhất phù hợp với tôi.

import traceback 

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

Output

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 
+1

siêu đơn giản, tôi thích nó. – loneRanger

Các vấn đề liên quan