python except用法和作用_python上手--异常处理与文件
本專欄python屬于上手系列,因?yàn)榫W(wǎng)絡(luò)資源眾多,有從零基礎(chǔ)開始介紹的,也有各種進(jìn)階應(yīng)用,我在這個(gè)專欄里就從上手來介紹python,零基礎(chǔ)也許不一定合適。但實(shí)踐永遠(yuǎn)是獲得認(rèn)知的手段,因此上手實(shí)踐操作對于學(xué)習(xí)編程還是來的容易一些。
莫愁前路無知己,天下誰人不識君!
前面介紹了python的安裝、編譯器選擇、基礎(chǔ)語法和數(shù)據(jù)類型、程序控制結(jié)構(gòu)、函數(shù)、模塊和類,完成基本的python編程已經(jīng)沒有問題了,本篇從程序的異常處理和文件輸出進(jìn)一步完善上手系列。
(1)異常處理
在開發(fā)程序過程中,總會(huì)遇到各種問題,有一些是語法錯(cuò)誤,如python使用時(shí)將字符串與數(shù)字類型放在一起加減乘除、引號錯(cuò)誤,或者拼寫錯(cuò)誤;有一些是邏輯問題,如for循環(huán)遍歷不止(死循環(huán)),或者函數(shù)調(diào)用順序不對等。出了問題肯定要解決才行,可以根據(jù)控制臺錯(cuò)誤提示來糾正自己的代碼;同時(shí)出問題時(shí)如果不仔細(xì)找不到錯(cuò)誤的地方是一件很頭疼的事情。而如果開發(fā)了大段Python程序時(shí),python解釋器在執(zhí)行程序時(shí)當(dāng)檢測到一個(gè)錯(cuò)誤時(shí)就會(huì)觸發(fā)異常,如果沒有加入異常處理代碼,程序會(huì)在異常處直接崩潰而不會(huì)繼續(xù)執(zhí)行后續(xù)的代碼。試想誰會(huì)去用一個(gè)運(yùn)行著突然就崩潰的軟件。所以必須提供一種異常處理機(jī)制來增強(qiáng)程序的健壯性與容錯(cuò)性。良好的容錯(cuò)能力,能夠有效的提高用戶體驗(yàn),維持業(yè)務(wù)的穩(wěn)定性。注意的是:語法錯(cuò)誤跟異常處理無關(guān),所以我們在處理異常之前,必須避免語法上的錯(cuò)誤。
寫過java代碼的同學(xué)肯定對這個(gè)異常處理有印象;在python中,異常處理基本構(gòu)造也是這種:
try這種結(jié)構(gòu)中try-except或者try-finally通常匹配出現(xiàn),也就是說else是可選的。結(jié)構(gòu)中except可以有多個(gè),但else或者finally只能有一個(gè)。
在程序執(zhí)行的時(shí)候如果是try-except-else-finally結(jié)構(gòu),會(huì)首先執(zhí)行try里面的Python語句,如果存在錯(cuò)誤就執(zhí)行except里的異常提示和finally里的異常處理;如果執(zhí)行成功且沒有錯(cuò)誤提示就執(zhí)行else中另一個(gè)代碼塊,else代碼塊執(zhí)行后finally語句也會(huì)執(zhí)行。但實(shí)際開發(fā)中很少加入else代碼塊,一般就使用try-expect,或者try-finally結(jié)構(gòu)即可。
如下面一個(gè)完整結(jié)構(gòu)的實(shí)際例子:
Created on Thu Oct 31 20:17:57 2019@author: Caojianhua """ try: #try代碼塊for i in range(10):print(i) except: #觸發(fā)異常處理塊:except,如果try代碼塊中有異常,執(zhí)行這里print("error") else: #如果try代碼塊中正常運(yùn)行無異常,執(zhí)行else代碼塊 for j in range(2):print(i*j) finally: #觸發(fā)異常總結(jié)塊,finally,這個(gè)異常處理塊不管前面是否有異常都會(huì)執(zhí)行print("no way!")如果try語句里沒有錯(cuò)誤,就會(huì)執(zhí)行else代碼塊和finally語句。這么寫太費(fèi)事,所以一般不會(huì)加入else代碼塊,直接使用try-except結(jié)構(gòu)即可。
try:for i in range(10):print(i) except:print("error")再來列舉一個(gè)錯(cuò)誤的例子:
try: for i in range(a):print(i) except:print("有錯(cuò)誤") #提示有錯(cuò)誤很明顯上述try代碼中a沒有定義,使用try-except結(jié)構(gòu)后,執(zhí)行時(shí)如果try代碼塊中有錯(cuò)誤系統(tǒng)會(huì)直接執(zhí)行except中的語句,而不會(huì)在終端提示a沒有定義。很顯然這種我們自己定義的提示錯(cuò)誤還不夠完美或者考慮不周到,幸好python已經(jīng)做的足夠好。python將常出現(xiàn)的異常類型都進(jìn)行了內(nèi)置集成,在使用的時(shí)候直接在except后增加相應(yīng)的異常類型關(guān)鍵詞即可。
常用的異常類型對象如下:
AttributeError 試圖訪問一個(gè)對象沒有的樹形,比如foo.x,但是foo沒有屬性x IOError 輸入/輸出異常;基本上是無法打開文件 ImportError 無法引入模塊或包;基本上是路徑問題或名稱錯(cuò)誤 IndentationError 語法錯(cuò)誤(的子類) ;代碼沒有正確對齊 IndexError 下標(biāo)索引超出序列邊界,比如當(dāng)x只有三個(gè)元素,卻試圖訪問x[5] KeyError 試圖訪問字典里不存在的鍵 KeyboardInterrupt Ctrl+C被按下 NameError 使用一個(gè)還未被賦予對象的變量 SyntaxError Python代碼非法,代碼不能編譯(個(gè)人認(rèn)為這是語法錯(cuò)誤,寫錯(cuò)了) TypeError 傳入對象類型與要求的不符合 UnboundLocalError 試圖訪問一個(gè)還未被設(shè)置的局部變量,基本上是由于另有一個(gè)同名的全局變量, 導(dǎo)致你以為正在訪問它 ValueError 傳入一個(gè)調(diào)用者不期望的值,即使值的類型是正確的其余類型名可參考:
Python 異常處理 | 菜鳥教程?www.runoob.com上述語法錯(cuò)誤的例子如果使用我們自己的錯(cuò)誤提示,終端會(huì)打印"有錯(cuò)誤"而不會(huì)提示a沒有定義。為了改善代碼,我們加入python的異常類型:
try: for i in range(a):print(i) except ValueError as e: #使用python的ValueError類型,這是一個(gè)異常類,as用法是實(shí)例化print(e.args) #調(diào)用實(shí)例error對象的args屬性,提示參數(shù)錯(cuò)誤這樣再執(zhí)行的時(shí)候系統(tǒng)終端就會(huì)提示:NameError: name 'a' is not defined
再修改一下上述代碼,將a修改為10,range(10)默認(rèn)表示從0到10,:
try: for i in range(10):print(10/i) #使用10除以i,這里i肯定會(huì)取0值 except ValueError as error:print(err.args)執(zhí)行時(shí)系統(tǒng)終端提示:ZeroDivisionError: division by zero
同時(shí)在開發(fā)過程中還可以在程序代碼中使用raise語句來自定義觸發(fā)異常,例如:
def getRemains(i):if i==0:raise ValueError('分母不能為0')return 10%itry: for i in range(10):print(getRemains(i)) except ValueError as error:print(error.args)代碼執(zhí)行的時(shí)候就會(huì)直接拋出異常:('分母不能為0',)
這個(gè)異常處理在項(xiàng)目開發(fā)過程中每一個(gè)業(yè)務(wù)處理的時(shí)候都需要構(gòu)建,使得程序更為安全和健壯,也有利于程序員快速定位錯(cuò)誤,及時(shí)完善代碼。對于初學(xué)者而言,也得學(xué)著開始逐步添加這類異常處理,為后續(xù)的進(jìn)階打下基礎(chǔ)。
(2)文件
文件的讀取應(yīng)該是非常常見的,因?yàn)槲覀儾豢赡芤恢睆逆I盤輸入相應(yīng)的數(shù)據(jù),許多圖形圖像、大篇幅的文字都是以文件形式存在的,所以有必要學(xué)會(huì)使用python來讀取和存儲文件。
這里首先引入常用的with方式:在處理文件時(shí)使用python的上下文管理器,可以保證文件在使用后被關(guān)閉、占用的內(nèi)存資源被釋放,使用方式就是with語句:
with open(filename,mode)as context: #mode就是讀、寫等模式,conText可以自定義process file here #處理文件代碼代碼中對于文件file的操作使用python內(nèi)置的open函數(shù):
file object = open(file_name,mode)因此上述的contextName也就是一個(gè)file對象,可以自定義命名。open函數(shù)中filename就是要操作的文件名,mode為模式,常用模式包括:
t 文本模式 (默認(rèn))。 x 寫模式,新建一個(gè)文件,如果該文件已存在則會(huì)報(bào)錯(cuò)。 b 二進(jìn)制模式。 + 打開一個(gè)文件進(jìn)行更新(可讀可寫)。 U 通用換行模式(不推薦)。 r 以只讀方式打開文件。文件的指針將會(huì)放在文件的開頭。這是默認(rèn)模式。 rb 以二進(jìn)制格式打開一個(gè)文件用于只讀。文件指針將會(huì)放在文件的開頭。這是默認(rèn)模式。一般用于非文本文件如圖片等。 r+ 打開一個(gè)文件用于讀寫。文件指針將會(huì)放在文件的開頭。 rb+ 以二進(jìn)制格式打開一個(gè)文件用于讀寫。文件指針將會(huì)放在文件的開頭。一般用于非文本文件如圖片等。 w 打開一個(gè)文件只用于寫入。如果該文件已存在則打開文件,并從開頭開始編輯,即原有內(nèi)容會(huì)被刪除。如果該文件不存在,創(chuàng)建新文件。 wb 以二進(jìn)制格式打開一個(gè)文件只用于寫入。如果該文件已存在則打開文件,并從開頭開始編輯,即原有內(nèi)容會(huì)被刪除。如果該文件不存在,創(chuàng)建新文件。一般用于非文本文件如圖片等。 w+ 打開一個(gè)文件用于讀寫。如果該文件已存在則打開文件,并從開頭開始編輯,即原有內(nèi)容會(huì)被刪除。如果該文件不存在,創(chuàng)建新文件。 wb+ 以二進(jìn)制格式打開一個(gè)文件用于讀寫。如果該文件已存在則打開文件,并從開頭開始編輯,即原有內(nèi)容會(huì)被刪除。如果該文件不存在,創(chuàng)建新文件。一般用于非文本文件如圖片等。 a 打開一個(gè)文件用于追加。如果該文件已存在,文件指針將會(huì)放在文件的結(jié)尾。也就是說,新的內(nèi)容將會(huì)被寫入到已有內(nèi)容之后。如果該文件不存在,創(chuàng)建新文件進(jìn)行寫入。 ab 以二進(jìn)制格式打開一個(gè)文件用于追加。如果該文件已存在,文件指針將會(huì)放在文件的結(jié)尾。也就是說,新的內(nèi)容將會(huì)被寫入到已有內(nèi)容之后。如果該文件不存在,創(chuàng)建新文件進(jìn)行寫入。 a+ 打開一個(gè)文件用于讀寫。如果該文件已存在,文件指針將會(huì)放在文件的結(jié)尾。文件打開時(shí)會(huì)是追加模式。如果該文件不存在,創(chuàng)建新文件用于讀寫。 ab+ 以二進(jìn)制格式打開一個(gè)文件用于追加。如果該文件已存在,文件指針將會(huì)放在文件的結(jié)尾。如果該文件不存在,創(chuàng)建新文件用于讀寫。在處理代碼部分,如果是讀操作,就使用read()、readline()或readlines()等方法。具體對比如下:
read() : 讀取整個(gè)文件內(nèi)容到一個(gè)字符串中,以一個(gè)換行符結(jié)束 readline() : 把文件一行一行地讀入一個(gè)列表中,并且保留每一行的換行符 readlines(): 讀取文件中的下一行,也保留換行符,結(jié)果為列表如果是寫操作,就是write()或者writelines方法,與類似名稱的讀方法格式類似。
推薦使用下述格式代碼來實(shí)現(xiàn)讀取文件操作:
with open(filename, mode) as f:for line in f:#讀或?qū)懛椒ùa下面首先來看文本文件的讀寫,如txt文件、csv文件、prn文件等。文本文件是一種特殊的二進(jìn)制文件。在文本文件中其內(nèi)容都是字符串類型,同時(shí)也需要注意的是在文本文件中段落的換行或者縮進(jìn)等都有轉(zhuǎn)義字符。
讀文本文件:with open(filename,mode='r') as f: f.read()
例如將如下文字保存到本地磁盤E盤的week8目錄下,命名為test.txt文本文件:
馬上進(jìn)入冬天了,溫度還維持在15度左右,看來又是一個(gè)暖冬了! 很想念老家那些好吃的東西,真是好久沒有吃到了。 你在那邊還好嗎,有一點(diǎn)想你。如果要讀取該文件并將內(nèi)容打印到終端,代碼如下:
filename='E:/week8/test.txt' with open(filename,'r') as f:for line in f:print(line)終端打印出來的效果如前述完全一致。由于是讀文本文件,默認(rèn)模式就是r,所以也可以不寫mode,直接使用with open(filename) as f。
如果使用read或者readline,代碼如下:
filename='E:/test.txt' #read函數(shù)直接讀取所有內(nèi)容,保持原有的換行 with open(filename,'rb') as f:print(f.read())#readline()函數(shù)讀取,括號里可以給字節(jié)數(shù)參數(shù),默認(rèn)讀取第一行所有字符, #f.readline(10),表示從文件頭開始讀取到第10個(gè)字符 with open(filename) as f: print(f.readline(10))寫文本文件:with open(filename,mode='w') as f: f.write("內(nèi)容")
接下來看寫入文本文件或者保存為文本文件的方法。此時(shí)就使用write或者writeline方法,修改open函數(shù)的mode模式為w,w為寫入,這種模式會(huì)將原有內(nèi)容清空,直接寫入新的內(nèi)容。如下代碼:
filename='nn.txt' with open(filename,'w') as f: f.write("晴朗的天氣n")f.write("沒有一絲微風(fēng)")如果想在這個(gè)nn.txt里追加一些內(nèi)容,則將open函數(shù)的模式修改為a,如下:
filename='nn.txt' with open(filename,'a') as f: f.write("明朗的月亮n")f.write("照亮著大地")對于圖形圖像、音頻、視頻等多媒體文件等非文本文件,采用上述方式就不行了,需要采用其他的工具,使用第三方庫。
讀取圖形文件
有許多類都提供了圖形讀取和處理的方法,在實(shí)踐時(shí)選用的是anaconda平臺的spyder開發(fā)模塊,許多庫都內(nèi)置了,也就是在安裝時(shí)就安裝好了。這里選取幾種加以介紹:
使用PIL庫,使用代碼示例吐下:
from PIL import Image #從PIL包里導(dǎo)入Image類 import numpy as np #導(dǎo)入numpy包 def readImage(image): #構(gòu)建一個(gè)讀取圖形文件的函數(shù)img=Image.open(image) #調(diào)用image類的open函數(shù),打開給定的圖形文件,返回一個(gè)對象img.show() #調(diào)用返回對象的show函數(shù),顯示圖形img_rgb_array=np.array(img) #使用numpy包的數(shù)組函數(shù)讀取圖形對象print(img_rgb_array.shape) #打印圖形對象大小image="e:/55.png" readImage(image)執(zhí)行效果如下:
同時(shí)在終端上顯示圖形大小為(147, 117, 4)。
如果使用skimage庫,示例代碼可修改為:
from skimage import io #導(dǎo)入skimage庫的io類 def readImage(image): #構(gòu)建readImage函數(shù)img=io.imread(image) #調(diào)用io類的imread函數(shù),返回一個(gè)img對象io.imshow(img) #調(diào)用io類的imshow函數(shù),傳遞img對象,執(zhí)行顯示image="e:/55.png" readImage(image)執(zhí)行后,在終端直接顯示當(dāng)前圖片:
同時(shí)還可以使用機(jī)器學(xué)習(xí)里的scipy和matplotlib庫,如下代碼:
import matplotlib.pyplot as plt #導(dǎo)入機(jī)器學(xué)習(xí)類里的繪圖包 from scipy import misc #導(dǎo)入機(jī)器學(xué)習(xí)包里的misc類def readImage(image):img=misc.imread(image) #調(diào)用misc類的imread函數(shù),傳遞image文件,返回一個(gè)對象plt.imshow(img) #調(diào)用plt類的imshow函數(shù),傳入img對象plt.show() #調(diào)用plt類的顯示函數(shù)image="e:/55.png" readImage(image)其結(jié)果與上述一致。
對于圖形文件的存取,也都是使用這些庫的對象函數(shù),如imsave函數(shù)等來實(shí)現(xiàn)。這里受限于主題與篇幅不在贅述。
總結(jié)
以上是生活随笔為你收集整理的python except用法和作用_python上手--异常处理与文件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: openlayers 添加点线面 De
- 下一篇: python获取系统当前时间并转utc时