2010-04-10 18 views
7

Khi tôi nhận được một ngoại lệ thời gian chạy từ thư viện chuẩn, nó hầu như luôn luôn là một vấn đề trong mã của tôi và không phải trong mã thư viện. Có cách nào để cắt bớt các dấu vết ngăn xếp ngoại lệ để nó không hiển thị ruột của gói thư viện?Python: loại bỏ dấu vết ngăn xếp thành mã thư viện?

Ví dụ, tôi muốn có được điều này:

Traceback (most recent call last): 
    File "./lmd3-mkhead.py", line 71, in <module> 
    main() 
    File "./lmd3-mkhead.py", line 66, in main 
    create() 
    File "./lmd3-mkhead.py", line 41, in create 
    headver1[depotFile]=rev 
TypeError: Data values must be of type string or None. 

và không này:

Traceback (most recent call last): 
    File "./lmd3-mkhead.py", line 71, in <module> 
    main() 
    File "./lmd3-mkhead.py", line 66, in main 
    create() 
    File "./lmd3-mkhead.py", line 41, in create 
    headver1[depotFile]=rev 
    File "/usr/anim/modsquad/oses/fc11/lib/python2.6/bsddb/__init__.py", line 276, in __setitem__ 
    _DeadlockWrap(wrapF) # self.db[key] = value 
    File "/usr/anim/modsquad/oses/fc11/lib/python2.6/bsddb/dbutils.py", line 68, in DeadlockWrap 
    return function(*_args, **_kwargs) 
    File "/usr/anim/modsquad/oses/fc11/lib/python2.6/bsddb/__init__.py", line 275, in wrapF 
    self.db[key] = value 
TypeError: Data values must be of type string or None. 

update: thêm một answer với mã, nhờ con trỏ từ Alex.

Trả lời

2

Nhờ con trỏ từ Alex, đây là teh codez:

def trimmedexceptions(type, value, tb, pylibdir=None, lev=None): 
    """trim system packages from the exception printout""" 
    if pylibdir is None: 
     import traceback, distutils.sysconfig 
     pylibdir = distutils.sysconfig.get_python_lib(1,1) 
     nlev = trimmedexceptions(type, value, tb, pylibdir, 0) 
     traceback.print_exception(type, value, tb, nlev) 
    else: 
     fn = tb.tb_frame.f_code.co_filename 
     if tb.tb_next is None or fn.startswith(pylibdir): 
      return lev 
     else: 
      return trimmedexceptions(type, value, tb.tb_next, pylibdir, lev+1) 

import sys 
sys.excepthook=trimmedexceptions 

# --- test code --- 

def f1(): f2() 
def f2(): f3() 
def f3(): 
    import xmlrpclib 
    proxy = xmlrpclib.ServerProxy('http://nosuchserver') 
    proxy.f() 

f1() 

nào mang lại đống này dấu vết:

Traceback (most recent call last): 
    File "./tsttraceback.py", line 47, in <module> 
    f1() 
    File "./tsttraceback.py", line 40, in f1 
    def f1(): f2() 
    File "./tsttraceback.py", line 41, in f2 
    def f2(): f3() 
    File "./tsttraceback.py", line 45, in f3 
    proxy.f() 
gaierror: [Errno -2] Name or service not known 
0

Đặt thử không đủ tiêu chuẩn ... ngoại trừ ở đầu mã của bạn (ví dụ: trong "chính") của bạn hoặc đặt sys.excepthook. Sau đó, bạn có thể định dạng theo dõi ngăn xếp theo ý muốn.

1

Traceback library có lẽ là những gì bạn muốn. Dưới đây là một ví dụ có thể giúp:

import traceback 

try: 
    your_main() 
except: 
    lines = traceback.format_exc() 
    print lines[:lines.find('File "/usr')] 

(Điều này rõ ràng sẽ không làm việc nếu có một ngoại lệ bên ngoài thư viện, và có thể không chính xác phù hợp với nhu cầu của bạn, nhưng đó là một cách để sử dụng thư viện traceback)

10

Mô-đun traceback trong thư viện chuẩn của Python cho phép bạn phát ra các dấu vết lỗi theo cách phù hợp với ý thích của bạn, trong khi ngoại lệ đang lan truyền. Bạn có thể sử dụng quyền này ở chân except của tuyên bố try/except hoặc trong một chức năng bạn đã cài đặt là sys.excepthook, được gọi nếu và khi một ngoại lệ lan truyền tất cả; trích dẫn tài liệu:

Trong phiên tương tác, điều này xảy ra ngay trước khi điều khiển được trả về lời nhắc ; trong một chương trình Python này xảy ra ngay trước khi thoát khỏi chương trình. Việc xử lý các trường hợp cấp cao nhất như vậy có thể được tùy chỉnh bằng cách gán ba đối số khác cho sys.excepthook.

Dưới đây là một đơn giản, ví dụ nhân tạo:

>>> import sys 
>>> import traceback 
>>> def f(n): 
... if n<=0: raise ZeroDivisionError 
... f(n-1) 
... 
>>> def excepthook(type, value, tb): 
... traceback.print_exception(type, value, tb, 3) 
... 
>>> sys.excepthook = excepthook 
>>> f(8) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 3, in f 
    File "<stdin>", line 3, in f 
ZeroDivisionError 

như bạn thấy, mà không cần một try/except, bạn có thể dễ dàng hạn chế traceback đến (ví dụ) ba cấp độ đầu tiên - dù chúng ta biết bằng cách thiết kế rằng có 9 mức lồng nhau khi ngoại lệ được nâng lên.

Bạn muốn điều gì đó tinh vi hơn giới hạn đơn giản về mức, vì vậy bạn cần gọi số traceback.format_exception, cung cấp cho bạn danh sách các dòng thay vì in, sau đó "tỉa" từ danh sách đó bạn không bao giờ muốn nhìn thấy trong tracebacks của bạn, và cuối cùng phát ra các dòng còn lại (thường là sys.stderr, nhưng, bất cứ điều gì! -).

+0

tinh khiết khôn ngoan cất, trộn với một chút phong cách ... nhờ Alex! –

+0

@Mark, bạn được chào đón - cảm ơn vì các kudo! –

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