本博文源於python基礎,主要探討python的錯誤、異常合程序調試。包含:語法錯誤、異常處理、手工拋出異常、assert語句、自定義異常類、pdb調式程序、測試程序。
語法錯誤
拼寫錯誤
比如print硬生生拼成printtt
腳本程序不符合python的語法規範
比如少括號、冒號等符號
縮進錯誤
沒有按照標準的四個空格縮進。一般很難會產生這種錯誤。
異常的處理
異常處理的基本語法
完整格式
try:
<語句塊>
except <異常名1>:
<語句塊>
except <異常名2>:
<語句塊>
....
else:
<語句塊>
finally:
<語句塊>
這塊代碼格式的語句是這樣子的分爲有無異常,
- 如果有異常,執行異常所在的except語句,不執行else,然後執行finally
- 如果無異常,執行else,執行finally
其他形式的捕獲異常格式
try:
<語句塊>
except <異常名1>:
<語句塊>
try:
<語句塊>
except <異常名1>:
<語句塊>
finally:
<語句塊>
例子:捕獲獲取列表索引是否存在的異常,觀察有什麼發現
def testTry(index, flag=False):
stulst = ["John", "Jenny", "Tom"]
if flag:
try:
astu = stulst[index]
except IndexError:
print("IndexError")
return "Try Test Finished!"
else:
astu = stulst[index]
return "No Try Test Finished!"
print("Right parmas teting start....")
# 執行成功的代碼
print(testTry(1, True))
# 不越界的代碼
print(testTry(1, False))
# 索引不存在檢測異常代碼
print(testTry(4, True))
# 索引不存在不檢測異常
print(testTry(4, False))
通過上面的代碼執行會發現捕獲異常的時候,如果捕獲到那就程序處理異常,然後正確往下面走。如果沒捕獲到異常那就陷入奔潰的程序,這也是保證程序的健壯性。
python主要內置及其處理
常用的異常函數
異常名 | 描述 |
---|---|
AttributeError | 調用不存在的方法引發異常 |
EOFError | 遇到文件末尾引發的異常 |
ImportError | 導入模塊出錯引發的異常 |
IndexError | 列表越界引起的異常 |
IOError | I/O操作中的引發異常 |
KeyError | 使用字典不存在的關鍵字引發的異常 |
NameError | 使用不存在的變量名引發的異常 |
TabError | 語句塊縮進不正確引發的異常 |
ValueError | 搜索列表中不存在的值引發的異常 |
ZeroDivisionError | 除數爲0引發的異常 |
except語句主要有以下幾種用法。
- except: 捕獲所有異常
- except <異常名>:捕獲指定異常
- except(異常名1,異常名2):捕獲異常名1或者異常名2
- except<異常名> as <數據>:捕獲指定異常及其附加得數據
- except(異常名1,異常名2) as <數據>:捕獲異常名1或者異常名2及異常的附加數據
手工拋出異常
用raise手工拋出異常
raise 異常名
raise 異常名,附加數據
raise 類名
例子:代碼執行遇到2拋出NameError異常
def testRaise():
for i in range(5):
if i==2:
raise NameError
print(i)
print('end...')
testRaise()
效果
例子:捕獲異常,繼續運行
def testRaise():
for i in range(5):
try:
if i==2:
raise NameError
except NameError:
print('Raise a NameError')
print(i)
print('end...')
testRaise()
assert語句
語句格式
assert <條件測試>,<異常附加的數據>
assert語句是簡化的raise語句,它引發異常的前提是其後面的條件測試爲假
assert使用場景
assert語句一般用於在程序開發時測試代碼的有效性。比如某個變量的值必須在一定範圍內,而運行時得到的值不符號要求,則引發該異常,對開發者予以提示。所以一般在程序中不去捕獲這個異常,而是讓它中斷程序。因爲程序中已經出現問題,沒有必要繼續運行下去。
例子:拋出程序執行到2的assert異常
def testAssert():
for i in range(3):
try:
assert i<2
except AssertionError:
print('Raise a AssertionError!')
print(i)
print('end...')
testAssert()
自定義異常類
在python中定義異常類不用從基礎完全自己定義,只要通過繼承Exception類來創建自己的異常類。異常類的定義和其他類沒有區別,最簡單的自定義異常類甚至可以只繼承Exception類,類體爲pass:
例子:程序自定義異常類,並用代碼將其引發
class RangeError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return self.value
raise RangeError('Range Error!')
用pdb調試程序
調試語句塊函數
格式
run(statement[, globals[, locals]])
- statement 要調試的語句塊,以字符串的形式表示
- global 可選參數,設置statement運行的全局環境變量
- locals 可選參數,設置statement運行的局部環境變量
pdb交互命令表
完整命令 | 簡寫命令 | 描 述 |
---|---|---|
args | a | 打印當前函數的參數 |
clear | cl | 清除斷點 |
break | b | 設置斷點 |
condition | 無 | 設置條件斷點 |
continue | c或者cont | 繼續運行,直到遇到斷點或者程序結束 |
disable | 無 | 禁用斷點 |
enable | 無 | 啓用斷點 |
help | 無 | 查看pdb幫助 |
ignore | 無 | 忽略斷點 |
jump | j | 跳轉到指定行數運行 |
list | l | 列出程序清單 |
next | n | 執行下條語句,遇到函數不進入其內部 |
p | p | 打印變量值,也可以用print |
quit | q | 退出pdb |
return | r | 一直運行到函數返回 |
tbreak | 無 | 設置臨時斷點,斷點只中斷一次 |
step | s | 執行下一條語句,遇到函數進入其內部 |
where | w | 查看所在的位置 |
! | 無 | 在pdb中執行語句 |
調試函數
pdb模塊中的調試函數應當調用模塊中的runcall函數,其參數原型爲:
runcall(function [,argument,...])
- function 函數名
- argument 函數的參數
例子:用pdb測試執行0,1,2
import pdb
pdb.run("""
for i in range(3):
print(i)
""")
例子:使用pdb進行測試函數逐條執行
import pdb
def sumn(maxint):
s = 0
for i in range(maxint):
s+= i
return s
pdb.runcall(sumn,10)
print(sumn(10))
測試程序
用testmod函數
用testmod函數進行單元測試,就要將測試用例寫入程序的docstring中
例子:自寫if判斷,用testmod進行測試
import pdb
def grade(sum):
"""
>>> grade(100)
'優秀'
>>> grade(80)
'良'
>>> grade(65)
'合格'
>>> grade(10)
'不合格'
"""
if sum>90:
return '優秀'
if sum>80:
return '良好'
if sum>60:
return '合格'
if sum<60:
return '不合格'
if __name__ == '__main':
import dectest
doctest.testmod()
同testfile測試
例子:自寫if判斷,用testfile進行測試
在myt.txt中輸入
>>> from test import grade
>>> grade(20)
'不合格'
>>> grade(100)
'優秀'
>>> grade(65)
'合格'
在test.py中輸入
import pdb
def grade(score):
if score > 90:
return '優秀'
if score > 80:
return '良好'
if score > 60:
return '合格'
if score < 60:
return '不合格'
if __name__ == '__main__':
import doctest
doctest.testfile('myt.txt')
測試效果
無異常