那些年,我們一起看的例外

20

Click here to load reader

description

 

Transcript of 那些年,我們一起看的例外

Page 1: 那些年,我們一起看的例外

那些年,我們一起看的例外

果凍

Page 2: 那些年,我們一起看的例外

about me● web backend developer● interest in:

○ operator system○ programming language

● http://about.me/ya790206

Page 3: 那些年,我們一起看的例外

先看個例外

Traceback (most recent call last): File "b.py", line 14, in <module> print func(lst, a) File "b.py", line 8, in func raise MyIndexException("list index out of range")__main__.MyIndexException: list index out of range

Page 4: 那些年,我們一起看的例外

那個例外所對應的程式碼import pickleclass Exception(Exception): pass

def func(lst, index): if index < len(lst): return lst[index] raise MyIndexException("list index out of range")

a = input()with open('data.txt', 'r') as ftr: lst = pickle.load(ftr) print func(lst, a)

Page 5: 那些年,我們一起看的例外

例外告訴我們什麼?

1. 在 b.py 第 8 行(在 func)出錯。原因是 list index out of range。

2. 在 b.py 第 14 行(在 func)呼叫3. 例外的類型是 __main__.MyIndexException

Page 6: 那些年,我們一起看的例外

心中疑惑

● lst 元素到底有幾個,還是根本沒有元素?● a 那個數字到底多大?

Page 7: 那些年,我們一起看的例外

方法一import pickleclass Exception(Exception): pass

def func(lst, index): if index < len(lst): return lst[index] raise MyIndexException("list index out of range" +str(locals()))

a = input()with open('data.txt', 'r') as ftr: lst = pickle.load(ftr) print func(lst, a)

Page 8: 那些年,我們一起看的例外

真的吐出區域變數的資訊了

Traceback (most recent call last): File "c.py", line 14, in <module> print func(lst, a) File "c.py", line 8, in func raise MyIndexException("list index out of range. " + str(locals()))__main__.MyIndexException: list index out of range. {'index': 8, 'lst': [1, 2, 3]}

Page 9: 那些年,我們一起看的例外

● 這程式碼看起來很有點蠢● 有沒有更好的辦法?

Page 10: 那些年,我們一起看的例外

在例外建構子做一些手腳,方法二

import pickleimport inspectclass MyIndexException(Exception): def __init__(self, msg): msg += str(inspect.stack()[1][0].f_locals) super(MyIndexException, self).__init__(msg)

下略 ...

Page 11: 那些年,我們一起看的例外

效果等價方法一,更好用了

Traceback (most recent call last): File "c.py", line 14, in <module> print func(lst, a) File "c.py", line 8, in func raise MyIndexException("list index out of range. " + str(locals()))__main__.MyIndexException: list index out of range. {'index': 8, 'lst': [1, 2, 3]}

Page 12: 那些年,我們一起看的例外

● 這一切看起來很美好。也只有看起來。● 如果 ... 程式碼變這樣?

Page 13: 那些年,我們一起看的例外

如果例外是內建的例外 ...

import pickledef func(lst, index): return lst[index]a = input()with open('data.txt', 'r') as ftr: lst = pickle.load(ftr) print func(lst, a)

Page 14: 那些年,我們一起看的例外

如果例外是內建的例外 ...

Traceback (most recent call last): File "a.py", line 11, in <module> print func(lst, a) File "a.py", line 5, in func return lst[index]IndexError: list index out of range

Page 15: 那些年,我們一起看的例外

How to solve it?

● 如果你想修改 IndexError 的建構子的話● 你需要修改 python source code,並自己編譯

他 …● It’s hard for me.

Page 16: 那些年,我們一起看的例外

其他解,方法三

● 利用 trace function 追蹤○ https://github.

com/ya790206/log_exception/blob/master/log_exception.py

○ 無法和 pdb 共存○ 會降低 python 效能,因此不適用於

production。

Page 17: 那些年,我們一起看的例外

其他可能解

● monkey patch 所有內建例外?

Page 18: 那些年,我們一起看的例外

總結

● 方法一:程式碼有點醜陋。每次都要傳參數進去有點麻煩。

● 方法二:只有當錯誤發生時,才自動做紀錄。可避免方法三的效能問題。但要注意上一個的 call stack 未必是你要的資料。如子類別 override 建構子時。又此法只能用在自訂類別。

Page 19: 那些年,我們一起看的例外

總結

● 方法三:可以印出所有例外發生時的 call stack 資訊。缺點為嚴重影響效能。只適合用在開發時期。

Page 20: 那些年,我們一起看的例外

設計緣由

為什麼我會希望把錯誤當時的 run time 資訊顯示出來? bug 可以分成三種:一種是程式錯誤,一種是資料錯誤,一種是前兩者都是錯的。過去維護的一個系統,裡面資料很多都是錯的。因此每當客戶回報系統有問題時,需要花時間去釐清哪種錯誤。如果能夠取得錯誤時的 run time 資訊,可以加速重建錯誤的情形,以利除錯。