Python Tips 通用的例外處理

今天稍微小結了一下 Python 中的例外處理,想找出一個通用好用的 exception 寫法

(2019.2.1 更新)

sample1.py

最簡單的一種如下

1
2
3
4
5
6
7
#!/usr/bin/python

try:
raise NotImplementedError("Excpetion Testing")
except:
// do something
raise

會列出造成例外的 stack 如下

1
2
3
4
Traceback (most recent call last):
File "sampel1.py", line 4, in <module>
raise NotImplementedError("Exception Testing")
NotImplementedError: Exception Testing

sample2.py

然後是一樣效果,可是可以自訂 exit code 的例子,這也蠻常用的,尤其是跟 Automation 有關的 script

1
2
3
4
5
6
7
8
9
#!/usr/bin/python
import sys, traceback

try:
raise NotImplementedError("Exception Testing")
except:
// do something
traceback.print_exc()
sys.exit(2)

輸出跟上面一樣,然後它的 exit code 是 2

1
2
$ echo $?
2

都 import 了 traceback package ,其實就有很多花招可以玩了,但我個人比較喜歡下面這種

sample3.py

一樣可以自訂 exit code ,但這次我們 format 一下輸出,好處是打印到 log file 的時候,可以一眼看出哪些部分是自己捕捉到的 exception

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/python
import sys, os

try:
raise NotImplementedError("Exception Testing")
except:
// do something
exc_type, exc_value, exc_traceback = sys.exc_info()
exc_file = os.path.split(exc_traceback.tb_frame.f_code.co_filename)[1]
exc_lineno = exc_traceback.tb_lineno
print(
"""
%s
File: %s
Line Number: %d
Error Message: %s
""" % (exc_type.__name__, exc_file, exc_lineno, exc_value))
sys.exit(2)

輸出長這樣,高度客製化

1
2
3
4
5

NotImplementedError
File: customize_exc.py
Line Number: 5
Error Message: Exception Testing

不過每個 Exception 都要寫是麻煩了點,就自行寫另一個 function 來使用吧

結語

  • 我個人習慣 error 和輸出都 print 在 stdout ,如果要寫到 log file 再統一由 stdout redirect ,所以就不討論直接輸出到 file 的寫法
  • 這邊都預設發生 exception 的時候要被 terminated ,所以也不討論 pass 的情況

Reference