Python(Head First)學習筆記:三
3 文件與異常:調試、處理錯誤、迭代、改進、完善
處理錯誤:利用Python的異常處理機制來處理異常情況。
程序外部的數(shù)據(jù):大多程序基本模型:首先輸入數(shù)據(jù),進行處理,然后存儲、顯示、打印或傳輸。
Python從文件讀取數(shù)據(jù):Python的open()BIF就是用來與文件交互的,結合for語句使用,可以非常容易地讀取數(shù)據(jù)。
使用open()流程:讀取文件數(shù)據(jù)時,Python會創(chuàng)建一個迭代器,從文件向代碼輸入數(shù)據(jù)行,一次傳入一行數(shù)據(jù)。
實例:
打開終端,輸入:python3
import os
os.getcwd() #獲取當前工作目錄
os.chdir('包含數(shù)據(jù)文件的文件夾目錄')
data=open('DataFile.txt')
print(data.readline(),end='') #輸出數(shù)據(jù)文件第一行數(shù)據(jù)
print(data.readline(),end='') #輸出數(shù)據(jù)文件第二行數(shù)據(jù)
data.seek(0) #用seek()方法返回文件起始位置
for each_line in data: #使用迭代的方法逐行輸出數(shù)據(jù)文件
print(each_line,end=' ')
data.close() #關閉數(shù)據(jù)文件
進一步查看數(shù)據(jù)
split()方法返回一個字符串列表,然后賦值到一個目標標識符列表,
通過將split()方法關聯(lián)到輸出變量,可以完成對數(shù)據(jù)文件的分割;
如:A:I am a cool boy!
用each_line.split(":")這句話可以分解成A和I am a cool boy!
用(role,line_spoken) = each_line.split(“:”),來獲取分解后的數(shù)據(jù)。
實例:
data = open('DataFile.txt')
for each_line in data:
(role,line_spoken)=each_line.split(':') #需要縮進
print(role,end='') #縮進長度和上面一樣
print(' said: ',end='')
print(line_spoken,end='')
了解數(shù)據(jù)的內容
針對split()方法,上面的實例中,通過(role,line_spoken)=each_line.split(':') 這句代碼,實現(xiàn)了將冒號":"分成兩部分,
然后分別賦值給role和line_spoken,但是當單行中出現(xiàn)多個冒號,就會報錯:too many values to unpack。
為了找到這個錯誤的原因,通過help(each_line.split)來查看:
split()有一個可選參數(shù),用于設置分割的數(shù)量,將其設置為1,則只會分解成兩個部分,
所以,可以將(role,line_spoken)=each_line.split(':') 這行代碼改為(role,line_spoken)=each_line.split(':',1)即可。
更好的了解數(shù)據(jù)內容
仍然針對split()方法,當數(shù)據(jù)行中沒有冒號時,split(':',1)無法查找到,所以就會報錯:need more than 1 value to unpack。
由此引發(fā)了一個思考:如果數(shù)據(jù)文件中存在大量的這種沒有冒號,或符合split()方法的判定,那么一定會報各種錯誤,該如何解決呢?
有兩個方向可以考慮:1 增加額外邏輯,確定是否需要調用split()方法;
2 不斷調試,直到錯誤都解決。
方法一:增加額外邏輯
find()方法的引入,可以通過find()來嘗試找出一個字符串中的子串,如果沒有找到返回值是-1,如果找到了返回該子串在字符串中的索引位置。
實例:>>>each_line = "I tell you, there'no such thing as a flying circus."
>>>each_line.find(':')
返回值為-1,因為字符串中沒有包含冒號;
修改字符串為:>>>each_line = "I tell you: there'no such thing as a flying circus."
>>>each_line.find(':')
返回值為10,正好是字符串的第10個字符,從0開始計下標,空格也算一個字符。
現(xiàn)在可以通過這個find()方法來改進上面的實例,具體如下:
data = open('DataFile.txt')
for each_line in data:
if not each_line.find(':')==-1: #這里增加了一個判斷,即:如果找到了冒號,則繼續(xù)執(zhí)行,用到了not關鍵字。
(role,line_spoken)=each_line.split(':') #需要縮進
print(role,end='') #縮進長度和上面一樣
print(' said: ',end='')
print(line_spoken,end='')
data.close()
注:not關鍵字是對值進行取反的意思。
問:為什么要用取反,而不是if each_line.find(':')>=0?這個有待進一步學習,感覺取反會更快些吧~
方法二:處理異常
當程序運行報錯時,Python解釋器會顯示一個tranceback,后面跟一個錯誤消息,這個錯誤消息就異常(exception)。
先嘗試運行代碼,然后處理可能發(fā)生的錯誤。
try/except機制的引入
基本格式:try:
代碼內容(可能包含未知錯誤)
except:
錯誤回復代碼
找出要保護的代碼
對于上面的實例可以改為:
data = open('DataFile.txt')
for each_line in data:
try: #保護代碼避開運行時的錯誤
(role,line_spoken)=each_line.split(':') #需要縮進
print(role,end='') #縮進長度和上面一樣
print(' said: ',end='')
print(line_spoken,end='')
except:
pass #如果出現(xiàn)一個運行時錯誤,會執(zhí)行這個代碼
data.close()
注:對于列表,用中括號[]擴起來的是可以改變的列表;
用小括號()擴起來的是不可以改變的列表,可以認為是一個常量列表。
增加更多錯誤檢查代碼
當數(shù)據(jù)文件突然丟失或破壞了,那么data=open('DataFile.txt')就會報錯,所以有必要對數(shù)據(jù)文件的存在性進行檢查:
完善后的實例如下:
方法一:
import os
if os.path.exists('DataFile.txt'):
data = open('DataFile.txt')
for each_line in data:
try: #保護代碼避開運行時的錯誤
(role,line_spoken)=each_line.split(':') #需要縮進
print(role,end='') #縮進長度和上面一樣
print(' said: ',end='')
print(line_spoken,end='')
except:
pass #如果出現(xiàn)一個運行時錯誤,會執(zhí)行這個代碼
data.close()
else:
print('The data file is misssing!')
方法二:
try: #保護代碼避開運行時的錯誤
data = open('DataFile.txt')
for each_line in data:
(role,line_spoken)=each_line.split(':') #需要縮進
print(role,end='') #縮進長度和上面一樣
print(' said: ',end='')
print(line_spoken,end='')
data.close()
except:
print(‘The data file is missing!’) #文件丟失
問答:那么經(jīng)過上面兩種方法的實現(xiàn),哪種方法更好一些呢?
隨著越來越多的錯誤和異常,第一種方法:增加額外代碼和邏輯的復雜度也會隨之增加,到后來就會比較亂;
第二種方法:采用異常處理機制,可以將主要注意力集中于代碼的真正功能和實現(xiàn)。
所以,總的來說,采用異常處理機制這種方式更合適。
進一步的完善:特定指定異常
通過對except代碼指定錯誤類型,就可以把一般化的異常處理轉換為具有特定性的處理,如下:
try: #保護代碼避開運行時的錯誤
data = open('DataFile.txt')
for each_line in data:
try:
(role,line_spoken)=each_line.split(':') #需要縮進
print(role,end='') #縮進長度和上面一樣
print(' said: ',end='')
print(line_spoken,end='')
except ValueError:
pass
data.close()
except IOError:
print(‘The data file is missing!’) #文件丟失
注:Python中不可改變的常量列表稱為元組:tuple,一旦列表數(shù)據(jù)賦值到一個元組,就不能再改變,元組的符號是小括號(tuple)。
------------------------------------------The End of Third Chapter---------------------------------------------

浙公網(wǎng)安備 33010602011771號