是由於邏輯或語法導致一個程序無法正常運行的問題, 錯誤的特點是有些錯誤是無法預知的
通知上層調用者,有錯誤產生需要處理, 用作信號通知
是程序出錯時的一種狀態, 當異常發生時,程序不會向下繼續執行,而轉去調用此函數的地方,待處理此錯誤
ZeroDivisionError 除(或取模)零
StopIteration 迭代器沒有更多的值
IOError 輸入輸出操作失敗
ImportError 導入模塊失敗
GeneratorExit 生成器發生異常通知退出
IndexError 序列中沒有此索引
IndentationError 縮緊錯誤
ValueError 傳入無效的參數
AssertionError 斷言語句失敗
NameError 未聲明/初始化對象
AttributeError 對象沒有
詳見:>>> help(__builtins__)
捕獲異常,將程序轉為正常流程
try:
可能觸發異常的語句
except 錯誤類型1 [as 變量1]:
異常處理語句1, 根據錯誤類型進行匹配,如果匹配成功,則程序轉入正常狀態,並調用處理語句進行處理
except 錯誤類型2 [as 變量2]:
異常處理語句2
...
except:
如果沒有相應的錯誤類型與之匹配,則執行空類型的except子句(except:),之後程序進入正常狀態; 如果沒有該子句並且沒有匹配到任何錯誤類型,則程序的異常狀態會繼續向上(調用處)傳遞,至到傳入解釋執行器後終止程序執行
else:
未發生異常執行語句
finally:
最終執行語句(一定會被執行)
說明:as 部分可以省略
except 子句可以有一個或多個,但至少要有一個
else 子句最多只能有一個,也可以省略不寫
finally 子句最多只能有一個,也可以省略不寫
try-finally語句不會改變程序的狀態(正常/異常)狀態, 用來做觸發異常時必須處理的事情,無論異常是否發生,finally子句都會被執行; 通常try/finally 語句的finally 子句不可以省略,一定不存在except 子句;
try:
可能觸發異常的語句
finally:
最終語句
def fry_egg():
print("打開天然氣!")
print("開始煎雞蛋!")
try:
n = int(input("請輸入蛋的個數")) # 可觸發異常
print("完成煎蛋!共煎了%d個雞蛋" % n)
finally:
print("關閉天然氣!")
fry_egg()
打開天然氣!
開始煎雞蛋!
請輸入蛋的個數a
關閉天然氣!
--
ValueError Traceback (most recent call last)
<ipython-input-5-426dac8668b5> in <module>
8 print("關閉天然氣!")
9
---> 10 fry_egg()
<ipython-input-5-426dac8668b5> in fry_egg()
3 print("開始煎雞蛋!")
4 try:
----> 5 n = int(input("請輸入蛋的個數")) # 可觸發異常
6 print("完成煎蛋!共煎了%d個雞蛋" % n)
7 finally:
ValueError: invalid literal for int() with base 10: 'a'
觸發一個錯誤,讓程序進入異常狀態
raise 異常類型 或 異常對象
def make_raise():
print("start")
raise ZeroDivisionError("假的零除")
print("end")
try:
make_raise()
except ZeroDivisionError as err: # err綁定錯誤對象
print("出現錯誤")
print("錯誤類型:", err)
start
出現錯誤
錯誤類型:假的零除
當真值表達式為False時, 用錯誤數據創建一個AssertionError類型的錯誤,並進入異常狀態
assert 真值表達式, 錯誤數據(通常是字符串)
等同於:
if 真值表達式 == False:
raise AssertionError(錯誤數據)
def get_age():
a = input("請輸入年齡:")
a = int(a) # ValueError錯誤
assert a < 150, "年齡太大了"
assert a > 0, "還沒出生"
return a
while True: # 循環讀入解決NameValue錯誤
try:
age = get_age() or 0
break
except AssertionError as e:
print("發生年齡值不合法的錯誤,", e)
except ValueError as e:
print("發生輸入值不能轉為整數的錯誤", e)
print("您輸入的年齡是:", age)
請輸入年齡:a
發生輸入值不能轉為整數的錯誤 invalid literal for int() with base 10: 'a'
請輸入年齡:1111
發生年齡值不合法的錯誤, 年齡太大了
請輸入年齡:2
您輸入的年齡是:2
練習: 練習:寫一個函數getscore() 獲取學生輸入的成績(0~100),如果輸入出現異常,則用 try-except語句來處理異常並此函數返回0,如果一切正常則返回輸入的成績
def get_score():
score = int(input("輸入學生成績:"))
if score < 0:
raise ValueError("成績小於零")
if score > 100:
raise ValueError("成績大於零")
return score
while True:
try:
score = get_score()
break
except ValueError as err:
print("有錯誤發生:", err)
print("學生的成績是:", score)
輸入學生成績:-1
有錯誤發生:成績小於零
輸入學生成績:111
有錯誤發生:成績大於零
輸入學生成績:a
有錯誤發生:invalid literal for int() with base 10: 'a'
輸入學生成績:12
學生的成績是:12
pdb是python debugger 調試器. 既可以在命令行執行python時進行調試,也可以作為模塊被調用.
python -m pdb mysqcript.py 則會進入調試模式
(Pdb) # 會自動停在第一行,等待調試
1. 功能
h (help) # 幫助, 列出可用命令, h command 可用查看具體命令
q (quit) # 退出
!statement # 在目前的環境中執行statement (就是執行指定python語句)。
alias name command # 以一個」別名」代替」一群出錯命令」,有點類似c/c++ 的 macro。可在.pdbrc文件內定義..
unalias name # 取消某個 alias定義的別名。cl num (clear) # 刪除第 num 個斷點, num由b列出的Num列決定.如果沒有帶參數,則清除所有斷點。也可指定行號.
condition bpnumber [condition] # 設置斷點條件, 不寫條件則會取消條件設置.disable bpnumber # 取消指定斷點的功能,但仍然保留斷點可以重新激活。不指定 bpnumber會失效暫停所有斷點.
enable bpnumber # 恢復斷點的功能。j lineNo (jump) # 跳到某行執行,可以前跳或後跳。不是所有行都可跳. 只有在 call stack 的最底部才能作用。
unt (until) # 繼續執行直到行號大於當前行. ?? 2.6後新加.import pdb
pdb.set_trace() : 設置斷點, 在運行腳本到此時進入pdb模式, 指令則指到下一行.
pdb.run(statement, globals=None, locals=None): 主要用於調試指定內容語句塊.
statement: 要調試的語句塊,以字符串的形式表示
globals: 可選參數,設置statement運行的全局環境變量
locals: 可選參數,設置statement運行的局部環境變量
pdb.runeval(statement, globals=None, locals=None): 和run類似, 但會對statement字符串先進行運算
pdb.runcall(funcname, *args, **kwds): 調試指定函數.後面可以指定傳遞的函數參數. 多參數要用,隔開.
pdb.post_mortem([traceback]): post-mortem調試模式處理traceback或新近的錯.
pdb.pm(): post-mortem調試模式處理sys.last_traceback 的反饋