Khi tôi bắt một ngoại lệ, làm cách nào để có được loại, tệp và số dòng?


250

Bắt một ngoại lệ sẽ in như thế này:

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

5
Sử dụng được xây dựng trong traceback module.
Ned Deily

Nó cũng có thể hữu ích để in dòng mã, trong trường hợp ngoại lệ xảy ra: xem stackoverflow.com/questions/14519177/
Kẻ

Câu trả lời:


380
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
Bạn nên cẩn thận về việc giải nén sys.exc_info () vào các biến cục bộ, vì nếu bạn có một ngoại lệ trong trình xử lý ngoại trừ, các vars cục bộ có thể được giữ trong một tham chiếu tròn và không phải là GC'd. Thực hành tốt nhất là luôn luôn chỉ sử dụng các lát cắt của sys.exc_info (). Hoặc sử dụng các mô-đun khác như truy nguyên, như các áp phích khác đã đề xuất.
Daniel Pryden

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

4
@Basj: Với sys.exc_info () [0] .__ name__ bạn có được tên đơn giản của loại.
Julian Overmann

5
@DanielPryden Python docs cũng đang sử dụng phương pháp giải nén cùng docs.python.org/2/library/traceback.html#traceback-examples
sử dụng

3
@RobM: Vâng, nó an toàn cho chủ đề. sys.exc_info()đã được giới thiệu để giải quyết các vấn đề an toàn luồng trong API trước đó. Đầu ra của nó là dành riêng cho cả luồng hiện tại và khung stack hiện tại.
user2357112 hỗ trợ Monica

125

Hình thức đơn giản nhất mà làm việc cho tôi.

import traceback

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

Đầu ra

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
trong khi không chính xác định dạng mà op muốn, đây là giải pháp đơn giản và mạnh mẽ nhất
cs_alumnus

5
Điều gì là mạnh mẽ về nó?
jouell

1
@jouell Này, đôi khi tôi cũng thích sử dụng những từ ưa thích :)
Rishav

Sạch & hiệu quả. Cảm ơn đã chia sẻ :)
Himanshu Gautam

49

Nguồn (Py v2.7.3) cho tracBack.format_exception () và các hàm được gọi / liên quan giúp ích rất nhiều. Xấu hổ quá, tôi luôn quên Đọc Nguồn . Tôi chỉ làm như vậy cho việc 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ẽ giúp bất cứ ai tìm kiếm 90 +% cho bất cứ ai 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ể cho 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

1
đổi 'message' : exc_value.messagethành 'message' : str(exc_value)py3
user2682863 24/2/19

34

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

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')
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.