溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Python基礎(chǔ)教程之異常的示例分析

發(fā)布時(shí)間:2021-08-19 14:29:16 來源:億速云 閱讀:146 作者:小新 欄目:開發(fā)技術(shù)

這篇文章給大家分享的是有關(guān)Python基礎(chǔ)教程之異常的示例分析的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過來看看吧。

一、摘要

Python使用被稱為異常 的特殊對(duì)象來管理程序執(zhí)行期間發(fā)生的錯(cuò)誤。每當(dāng)發(fā)生讓Python不知所措的錯(cuò)誤時(shí),它都會(huì)創(chuàng)建一個(gè)異常對(duì)象。如果你編寫了處理該異常的代碼,程序?qū)⒗^續(xù)運(yùn)行;如果你未對(duì)異常進(jìn)行處理,程序?qū)⑼V?,并顯示一個(gè)traceback,其中包含有關(guān)異常的報(bào)告。

異常是使用try-except 代碼塊處理的。try-except 代碼塊讓Python執(zhí)行指定的操作,同時(shí)告訴Python發(fā)生異常時(shí)怎么辦。使用了try-except 代碼塊時(shí),即便出現(xiàn)異常,程序也將繼續(xù)運(yùn)行:顯示你編寫的友好的錯(cuò)誤消息,而不是令用戶迷惑的traceback

二、異常實(shí)操

處理ZeroDivisionError 異常:try-except&try-except-else

Python基礎(chǔ)教程之異常的示例分析

在上述traceback中,指出的錯(cuò)誤ZeroDivisionError 是一個(gè)異常對(duì)象。Python無法按你的要求做時(shí),就會(huì)創(chuàng)建這種對(duì)象。在這種情況下,Python將停止運(yùn)行程序,并指出引發(fā)了哪種異常,而我們可根據(jù)這些信息對(duì)程序進(jìn)行修改。下面我們將使用try-except告訴Python,發(fā)生這種錯(cuò)誤時(shí)怎么辦

Python基礎(chǔ)教程之異常的示例分析

將導(dǎo)致錯(cuò)誤的代碼行print(5/0) 放在了一個(gè)try 代碼塊中。如果try 代碼塊中的代碼運(yùn)行起來沒有問題,Python將跳過except 代碼塊;如果try 代碼塊中的代碼導(dǎo)致了錯(cuò)誤,Python將查找這樣的except 代碼塊,并運(yùn)行其中的代碼,即其中指定的錯(cuò)誤與引發(fā)的錯(cuò)誤相同,在這個(gè)示例中,try 代碼塊中的代碼引發(fā)了ZeroDivisionError 異常,因此Python指出了該如何解決問題的except 代碼塊,并運(yùn)行其中的代碼。這樣,用戶看到的是一條友好的錯(cuò)誤消息,而不是traceback,如果try-except 代碼塊后面還有其他代碼,程序?qū)⒔又\(yùn)行,因?yàn)橐呀?jīng)告訴了Python如何處理這種錯(cuò)誤

使用異常避免崩潰:

發(fā)生錯(cuò)誤時(shí),如果程序還有工作沒有完成,妥善地處理錯(cuò)誤就尤其重要。這種情況經(jīng)常會(huì)出現(xiàn)在要求用戶提供輸入的程序中;如果程序能夠妥善地處理無效輸入,就能再提示用戶提供有效輸入,而不至于崩潰。

print("Give me two numbers, and I'll divide them.")
print("Enter 'q' to quit.")
while True:
 first_number = input("\nFirst number: ")
 if first_number == 'q':
  break
 second_number = input("Second number: ")
 if second_number == 'q':
  break
 answer = int(first_number) / int(second_number)
 print(answer)

這個(gè)程序沒有采取任何處理錯(cuò)誤的措施,因此讓它執(zhí)行除數(shù)為0的除法運(yùn)算時(shí),它將崩潰:

Give me two numbers, and I'll divide them.
Enter 'q' to quit.
First number: 5
Second number: 0
Traceback (most recent call last):
 File "division.py", line 9, in <module>
  answer = int(first_number) / int(second_number)
ZeroDivisionError: division by zero

程序崩潰可不好,但讓用戶看到traceback也不是好主意。不懂技術(shù)的用戶會(huì)被它們搞糊涂,而且如果用戶懷有惡意,他會(huì)通過traceback獲悉你不希望他知道的信息。例如,他將知道你的程序文件的名稱,還將看到部分不能正確運(yùn)行的代碼。有時(shí)候,訓(xùn)練有素的攻擊者可根據(jù)這些信息判斷出可對(duì)你的代碼發(fā)起什么樣的攻擊。

通過將可能引發(fā)錯(cuò)誤的代碼放在try-except 代碼塊中,可提高這個(gè)程序抵御錯(cuò)誤的能力。錯(cuò)誤是執(zhí)行除法運(yùn)算的代碼行導(dǎo)致的,因此我們需要將它放到try-except 代碼塊中。這個(gè)示例還包含一個(gè)else 代碼塊;依賴于try 代碼塊成功執(zhí)行的代碼都應(yīng)放到else 代碼塊中:

print("Give me two numbers, and I'll divide them.")
print("Enter 'q' to quit.")
while True:
 first_number = input("\nFirst number: ")
 if first_number == 'q':
  break
 second_number = input("Second number: ")
 try:
  answer = int(first_number) / int(second_number)
 except ZeroDivisionError:
  print("You can't divide by 0!")
 else:
  print(answer)

讓Python嘗試執(zhí)行try 代碼塊中的除法運(yùn)算,這個(gè)代碼塊只包含可能導(dǎo)致錯(cuò)誤的代碼。依賴于try 代碼塊成功執(zhí)行的代碼都放在else 代碼塊中;在這個(gè)示例中,如果除法運(yùn)算成功,我們就使用else 代碼塊來打印結(jié)果。except 代碼塊告訴Python,出現(xiàn)ZeroDivisionError 異常時(shí)該怎么辦。如果try 代碼塊因除零錯(cuò)誤而失敗,我們就打印一條友好的消息,告訴用戶如何避免這種錯(cuò)誤。程序?qū)⒗^續(xù)運(yùn)行,用戶根本看不到traceback:

Give me two numbers, and I'll divide them.
Enter 'q' to quit.
First number: 5
Second number: 0
You can't divide by 0!
First number: 5
Second number: 2
2.5
First number: q

try-except-else 代碼塊的工作原理大致如下:Python嘗試執(zhí)行try 代碼塊中的代碼;只有可能引發(fā)異常的代碼才需要放在try 語句中。有時(shí)候,有一些僅在try 代碼塊成功執(zhí)行時(shí)才需要運(yùn)行的代碼;這些代碼應(yīng)放在else 代碼塊中。except 代碼塊告訴Python,如果它嘗試運(yùn)行try 代碼塊中的代碼時(shí)引發(fā)了指定的異常,該怎么辦。通過預(yù)測(cè)可能發(fā)生錯(cuò)誤的代碼,可編寫健壯的程序,它們即便面臨無效數(shù)據(jù)或缺少資源,也能繼續(xù)運(yùn)行,從而能夠抵御無意的用戶錯(cuò)誤和惡意的攻擊。

處理FileNotFoundError 異常:

使用文件時(shí),一種常見的問題是找不到文件:你要查找的文件可能在其他地方、文件名可能不正確或者這個(gè)文件根本就不存在。對(duì)于所有這些情形,都可使用try-except 代碼塊以直觀的方式進(jìn)行處理

filename = 'alice.txt'
with open(filename) as f_obj:
 contents = f_obj.read()

當(dāng)我們嘗試打開的文件(alice.txt)不存在時(shí),python會(huì)報(bào)如下異常:

Traceback (most recent call last):
 File "alice.py", line 3, in <module>
  with open(filename) as f_obj:
FileNotFoundError: [Errno 2] No such file or directory: 'alice.txt'

在上述traceback中,最后一行報(bào)告了FileNotFoundError 異常,這是Python找不到要打開的文件時(shí)創(chuàng)建的異常。在這個(gè)示例中,這個(gè)錯(cuò)誤是函數(shù)open() 導(dǎo)致的,因此要處理這個(gè)錯(cuò)誤,必須將try 語句放在包含open() 的代碼行之前:

filename = 'alice.txt'
try:
 with open(filename) as f_obj:
  contents = f_obj.read()
 except FileNotFoundError:
  msg = "Sorry, the file " + filename + " does not exist."
  print(msg)

分析文本:

split()函數(shù),看看下邊的例子,這個(gè)函數(shù)干了什么

>>> title = "Alice in Wonderland"
>>> title.split()
['Alice', 'in', 'Wonderland']

split() 以空格為分隔符將字符串分拆成多個(gè)部分,并將這些部分都存儲(chǔ)到一個(gè)列表中。結(jié)果是一個(gè)包含字符串中所有單詞的列表,雖然有些單詞可能包含標(biāo)點(diǎn)。為計(jì)算Alice in Wonderland 包含多少個(gè)單詞,我們將對(duì)整篇小說調(diào)用split() ,再計(jì)算得到的列表包含多少個(gè)元素,從而確定整篇童話大致包含多少個(gè)單詞

filename = 'alice.txt'
try:
 with open(filename) as f_obj:
  contents = f_obj.read()
 except FileNotFoundError:
  msg = "Sorry, the file " + filename + " does not exist."
  print(msg)
 else:
  # 計(jì)算文件大致包含多少個(gè)單詞
  words = contents.split()
  num_words = len(words)
  print("The file " + filename + " has about " + str(num_words) + " words.")

將文件alice.txt移到了正確的目錄中,讓try 代碼塊能夠成功地執(zhí)行。對(duì)變量contents (它現(xiàn)在是一個(gè)長(zhǎng)長(zhǎng)的字符串,包含童話 Alice in Wonderland 的全部文本)調(diào)用方法split() ,以生成一個(gè)列表,其中包含這部童話中的所有單詞。當(dāng)我們使用len() 來確定這個(gè)列表的長(zhǎng)度時(shí),就知道了原始字符串大致包含多少個(gè)單詞,我們打印一條消息,指出文件包含多少個(gè)單詞,這些代碼都放在else 代碼塊中,因?yàn)閮H當(dāng)try 代碼塊成功執(zhí)行時(shí)才執(zhí)行它們。輸出指出了文件alice.txt包含多少個(gè)單詞

使用多個(gè)文件:

def count_words(filename):
 """計(jì)算一個(gè)文件大致包含多少個(gè)單詞"""
 try:
  with open(filename) as f_obj:
   contents = f_obj.read()
 except FileNotFoundError:
  msg = "Sorry, the file " + filename + " does not exist."
  print(msg)
 else:
  # 計(jì)算文件大致包含多少個(gè)單詞
  words = contents.split()
  num_words = len(words)
  print("The file " + filename + " has about " + str(num_words) +
" words.")

filename = 'alice.txt'
count_words(filename)

然后編寫一個(gè)循環(huán),調(diào)用這個(gè)函數(shù)讓他分析多個(gè)文件:

filenames = ['alice.txt', 'siddhartha.txt', 'moby_dick.txt', 'little_women.txt']
for filename in filenames:
 count_words(filename)

在filenames列表中的siddhartha.txt文件是不存在的,我們的程序也能正常運(yùn)行,使用try-except 代碼塊提供了兩個(gè)重要的優(yōu)點(diǎn):避免讓用戶看到traceback;讓程序能夠繼續(xù)分析能夠找到的其他文件。如果不捕獲因找不到siddhartha.txt而引發(fā)的FileNotFoundError 異常,用戶將看到完整的traceback,而程序?qū)⒃趪L試分析 Siddhartha 后停止運(yùn)行——根本不分析 Moby Dick 和 Little Women

在前一個(gè)示例中,我們告訴用戶有一個(gè)文件找不到。但并非每次捕獲到異常時(shí)都需要告訴用戶,有時(shí)候你希望程序在發(fā)生異常時(shí)一聲不吭,就像什么都沒有發(fā)生一樣繼續(xù)運(yùn)行。要讓程序在失敗時(shí)一聲不吭,可像通常那樣編寫try 代碼塊,但在except 代碼塊中明確地告訴Python什么都不要做。Python有一個(gè)pass 語句,可在代碼塊中使用它來讓Python什么都不要做

def count_words(filename):
"""計(jì)算一個(gè)文件大致包含多少個(gè)單詞"""
 try:
  --snip--
 except FileNotFoundError:
  pass
 else:
  --snip--
filenames = ['alice.txt', 'siddhartha.txt', 'moby_dick.txt', 'little_women.txt']
for filename in filenames:
 count_words(filename)

相比于前一個(gè)程序,這個(gè)程序唯一不同的地方是pass 語句?,F(xiàn)在,出現(xiàn)FileNotFoundError 異常時(shí),將執(zhí)行except 代碼塊中的代碼,但什么都不會(huì)發(fā)生。這種錯(cuò)誤發(fā)生時(shí),不會(huì)出現(xiàn)traceback,也沒有任何輸出。用戶將看到存在的每個(gè)文件包含多少個(gè)單詞,但沒有任何跡象表明有一個(gè)文件未找到

pass 語句還充當(dāng)了占位符,它提醒你在程序的某個(gè)地方什么都沒有做,并且以后也許要在這里做些什么。例如,在這個(gè)程序中,我們可能決定將找不到的文件的名稱寫入到文件missing_files.txt中。用戶看不到這個(gè)文件,但我們可以讀取這個(gè)文件,進(jìn)而處理所有文件找不到的問題

感謝各位的閱讀!關(guān)于“Python基礎(chǔ)教程之異常的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI