版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
匯報(bào)人:WPSPython程序設(shè)計(jì)基礎(chǔ)第七章訪問文件目錄01文件的使用流程02文件的讀寫操作03Python生態(tài)系統(tǒng)之os庫(kù)04小試牛刀目錄05拓展實(shí)踐:根據(jù)訂單數(shù)據(jù)生成銷售報(bào)告06本章小結(jié)理解文件的作用。掌握文件使用的流程。掌握文本文件的讀取與寫入方法。了解
os庫(kù)的使用。前面雖然介紹了很多數(shù)據(jù)結(jié)構(gòu)來保存數(shù)據(jù),但都是在內(nèi)存中,因此無法實(shí)現(xiàn)長(zhǎng)期持久的保存數(shù)
據(jù)。要達(dá)到這一目標(biāo),就需要使用文件。本章介紹使用文件的基本流程,以及如何讀寫文本文件。學(xué)習(xí)目標(biāo)PART17.1文件的使用流程相信讀者已經(jīng)習(xí)慣了程序要有變量,有各種類型的容器來保存數(shù)據(jù)。簡(jiǎn)單如整型、浮點(diǎn)型、字
符串,復(fù)雜點(diǎn)的如列表、元組和字典等。但所有這些變量容器都是在內(nèi)存中的,內(nèi)存的弱點(diǎn)是一旦
意外關(guān)機(jī)、斷電,保存其中的數(shù)據(jù)就都沒有了。因此如果程序想要持久保存數(shù)據(jù)就需要使用文件。
文件一般位于磁盤上,磁盤是永久性保存數(shù)據(jù)的媒介,即使斷電也不會(huì)丟失數(shù)據(jù)。因此現(xiàn)實(shí)世界的
程序都需要有訪問磁盤文件的能力。7.1.1使用文件的原因Python
內(nèi)置的
open()函數(shù)可以打開磁盤上的文件,打開方式可以是讀取、寫入或二者均可。對(duì)
于文本文件,open()函數(shù)還可以指定使用何種編碼方式打開目標(biāo)文件。按照面向?qū)ο蟮睦砟?,文件?/p>
開后open()函數(shù)會(huì)返回一個(gè)代表該文件的對(duì)象,這個(gè)文件對(duì)象具有很多操作文件的方法,調(diào)用文件
對(duì)象的這些方法就可以方便地操作文件了。例如,
假設(shè)文件對(duì)象叫
file_obj,則關(guān)閉這個(gè)文件的操作
可以通過
file_obj.close()方法來完成。文件使用完畢后一定要記得關(guān)閉,這是每次使用完文件必做的收尾工作。因?yàn)楫?dāng)文件被
open()
函數(shù)打開時(shí),這個(gè)文件就被程序獨(dú)享占用,操作系統(tǒng)會(huì)保證其他的程序無法使用這個(gè)文件。如果
程序用完文件但不關(guān)閉,則程序?qū)ξ募莫?dú)享占用就仍然持續(xù)著,導(dǎo)致其他程序無法正常使用該
文件。使用文件的基本流程如下。第一步,使用
open()函數(shù)打開文件,得到一個(gè)文件對(duì)象。第二步,調(diào)用文件對(duì)象的方法對(duì)文件進(jìn)行讀寫操作。第三步,關(guān)閉文件。7.1.2使用文件的方法內(nèi)置的open()函數(shù)擁有多個(gè)參數(shù),但常用的只有幾個(gè)。下面通過打開一個(gè)文本文件的例子演示
open()函數(shù)的使用細(xì)節(jié)。代碼
7.1
要求磁盤上和代碼文件相同目錄下有
file
文件夾,file
文件夾下有“長(zhǎng)信宮燈.txt”文件。代碼
7.1
使用
open
函數(shù)打開文件7.1.3open()函數(shù)的使用#file_obj=open("file/長(zhǎng)信宮燈.txt","r",encoding="utf-8")#亦可file_obj=open("file\\長(zhǎng)信宮燈.txt","r",encoding="utf-8")forline
in
file_obj:print(line)file_obj.close()這段代碼打開指定的文本文件并將其中的內(nèi)容輸出,之后關(guān)閉文件。代碼
7.1
的運(yùn)行結(jié)果如下。長(zhǎng)信宮燈一改以往青銅器皿的神秘厚重,整個(gè)造型及裝飾風(fēng)格都顯得舒展自如、輕巧華麗,是一件既實(shí)用、又美觀的燈
具珍品。宮女銅像體內(nèi)中空,其中空的右臂與衣袖形成銅燈燈罩,可以自由開合,燃燒產(chǎn)生的灰塵可以通過宮女的右臂沉積
于宮女體內(nèi),不會(huì)大量飄散到周圍環(huán)境中,其環(huán)保理念體現(xiàn)了古代中國(guó)人民的智慧,長(zhǎng)信宮燈被譽(yù)為“中華第一燈”。美國(guó)前國(guó)務(wù)卿基辛格來華訪問時(shí)曾參觀過長(zhǎng)信宮燈,并感慨道:“2000
多年前中國(guó)人就懂得了環(huán)保,真了不起?!遍L(zhǎng)信宮燈一直被認(rèn)為是中國(guó)工藝美術(shù)品中的巔峰之作和民族工藝的重要代表而廣受贊譽(yù)。這不僅在于其獨(dú)一無二、稀有
珍貴,更在于它精美絕倫的制作工藝和巧妙獨(dú)特的藝術(shù)構(gòu)思。采取分別鑄造,然后合成一整體的方法。考古學(xué)和冶金史的研
究專家一致公認(rèn),此燈設(shè)計(jì)之精巧,制作工藝水平之高,在漢代宮燈中首屈一指。1993
年被鑒定為國(guó)寶級(jí)文物。摘自《百度百科》代碼中的
open()函數(shù)用到了
3個(gè)參數(shù),分別如下。(
1)參數(shù)
file:待打開的文件名。open()函數(shù)的第一個(gè)參數(shù)是要打開的文件名,如果文件不在當(dāng)前路徑還要有路徑名。其中的路徑
分隔符在
Windows平臺(tái)下使用的是“\”,與
Python
的字符串轉(zhuǎn)義符號(hào)沖突了。因此如果想要使用
“\”作為路徑分隔符,則每個(gè)分隔路徑的斜杠要寫兩遍。如果覺得麻煩,也可以使用“/”斜杠作為
路徑分隔符,就像代碼中被注釋掉的那行一樣。(2)參數(shù)mode:文件的打開模式。打開模式通常有讀、寫、追加等幾種,表7.1
是文件的常見打開模式。其中,寫入模式和追加
模式的區(qū)別在于,如果打開的文件原來有內(nèi)容,則寫入模式會(huì)完全覆蓋掉原來的內(nèi)容,而追加模式
會(huì)在原內(nèi)容的后邊追加新的內(nèi)容。如果沒有指定打開模式,則默認(rèn)為“r”模式也就是讀模式。使用“r”模式打開文件時(shí),要求目
標(biāo)文件一定要事先存在,否則會(huì)報(bào)錯(cuò)。而使用“w”模式打開文件時(shí),如果文件名指定的文件不存
在,則
open()函數(shù)會(huì)創(chuàng)建這個(gè)文件。7.1.3open()函數(shù)的使用(3)參數(shù)
encoding:針對(duì)文本文件的編碼、解碼方案。打開文件時(shí)常用到的第三個(gè)參數(shù)就是
encoding。注意,這里只是說
encoding是常用到的第三個(gè)
參數(shù),不是說
encoding是
open()函數(shù)的第三個(gè)參數(shù)。實(shí)際上
encoding是
open()函數(shù)的第四個(gè)參數(shù)。這意味著為
encoding
參數(shù)傳值時(shí),一般要明確寫出參數(shù)名,即像
encoding="utf-8"
這樣書寫,這和前兩個(gè)參數(shù)不同。文件名和打開模式這兩個(gè)參數(shù)在傳值時(shí)寫不寫參數(shù)名都沒問題,因?yàn)樗鼈兙褪?/p>
open()函數(shù)的第一、第二個(gè)參數(shù),按照位置對(duì)應(yīng)也是沒問題的。但
encoding是
open()函數(shù)的第四個(gè)參數(shù),如果代碼
7.1傳值時(shí)只寫"utf-8",實(shí)際上是傳給了
open()函數(shù)的第三個(gè)參數(shù)。代碼
7.1如果去掉
encoding參數(shù)的設(shè)置就會(huì)報(bào)錯(cuò),錯(cuò)誤原因是解碼方案不對(duì),無法正確解碼。
當(dāng)打開的文本文件遇到編碼錯(cuò)誤時(shí),就要了解該文件使用的是何種編碼,通過
encoding參數(shù)設(shè)置正
確的解碼方案。7.1.3open()函數(shù)的使用打開模式說明r以只讀方式打開文件,默認(rèn)模式w以寫入模式打開文件a以追加模式打開文件表
7.1文件的常見打開模式PART27.2文件的讀寫操作open()函數(shù)得到的文件對(duì)象有
3個(gè)常用的讀取文件內(nèi)容的方法,分別是
read()方法、readline()方
法和
readlines()方法。下面以文本文件為例介紹這
3個(gè)方法的用法。1.read()方法這個(gè)方法可讀入指定長(zhǎng)度的內(nèi)容,如果沒有指定長(zhǎng)度,則默認(rèn)將文本文件的內(nèi)容全部讀入。該
方法返回的是一個(gè)字符串。代碼
7.2演示了
read()方法的使用。代碼
7.2
文件對(duì)象的
read()方法代碼
7.2
的運(yùn)行結(jié)果如下,只有原文的前一小部分內(nèi)容。讀者可將
read()方法括號(hào)中的
35去掉,
看一下返回的結(jié)果。7.2.1讀取文本文件file_obj=open("file/長(zhǎng)信宮燈.txt","r",encoding="utf-8")text=file_obj.read(35)#讀取前
35個(gè)字符print(text)file_obj.close()長(zhǎng)信宮燈一改以往青銅器皿的神秘厚重,整個(gè)造型及裝飾風(fēng)格都顯得舒展自如、2.readline()方法顧名思義,readline()方法一次可以讀入文本文件的一行,如代碼
7.3所示。這段代碼要打開的文
本文件內(nèi)含納蘭性德的一首《浣溪沙》詞,整個(gè)文本內(nèi)容從標(biāo)題、作者到正文被分成了幾行書寫。
每次調(diào)用readline()方法都會(huì)讀入一行文本,直到文件尾部。代碼
7.3
文件對(duì)象的
readline()方法代碼
7.3
的運(yùn)行結(jié)果如下。這里有一個(gè)細(xì)節(jié)需要說明,代碼中的
print()函數(shù)通過
end
參數(shù)關(guān)閉了自帶的換行效果。這是因
為文本文件中每一行的結(jié)尾都有一個(gè)看不見的換行符,如果不對(duì)
end
參數(shù)進(jìn)行設(shè)置,則每輸出一行文本會(huì)換兩次行。7.2.1讀取文本文件file_obj=open("file/浣溪沙.txt","r",encoding="utf-8")text=file_obj.readline()whiletext
!=
"":print(text,end="")text=file_obj.readline()file_obj.close()浣溪沙【清】納蘭性德誰(shuí)念西風(fēng)獨(dú)自涼,蕭蕭黃葉閉疏窗。沉思往事立殘陽(yáng)。被酒莫驚春睡重,賭書消得潑茶香。當(dāng)時(shí)只道是尋常。3.readlines()方法與
readline()方法不同,readlines()方法將文本文件的內(nèi)容以列表形式返回,文件的每一行是列表
的一個(gè)元素,如代碼
7.4所示。代碼
7.4
文件對(duì)象的
readlines()方法readlines()方法會(huì)將文件中的所有行都讀取出來,每一行文本作為一個(gè)元素保存在列表lines_lst
中,所以代碼
7.4
的運(yùn)行結(jié)果如下,注意每行行尾的換行符。7.2.1讀取文本文件file_obj=open("file/浣溪沙.txt","r",encoding="utf-8")lines_lst=file_obj.readlines()print(lines_lst)file_obj.close()['浣溪沙\n','【清】納蘭性德\n','誰(shuí)念西風(fēng)獨(dú)自涼,蕭蕭黃葉閉疏窗。沉思往事立殘陽(yáng)。\n','被酒莫驚春睡重,
賭書消得潑茶香。當(dāng)時(shí)只道是尋常。\n']如果讀入文本內(nèi)容后不是簡(jiǎn)單地從頭到尾輸出,而是有其他處理需求,則可以根據(jù)需要組合使
用多個(gè)讀入文本的方法。例如,代碼
7.5使用了
readline()和
readlines()兩個(gè)方法,將詞的標(biāo)題、作者與正文分開處理。代碼
7.5
組合使用文件對(duì)象的方法7.2.1讀取文本文件file_obj.close()forline
in
lines_lst:print(line,end="")author=author[:-1]#去掉行尾的換行符title=title[:-1]msg="——{a}
·《{t}》".format(a=author,t=title)
print(msg)title=file_obj.readline()author=file_obj.readline()lines_lst=file_obj.readlines()file_obj=open("file/浣溪沙.txt","r",encoding="utf-8")#讀取詞標(biāo)題
#讀取詞作者
#讀取詞正文代碼沒有按照原始書寫順序輸出,而是希望將標(biāo)題與作者放到正文的后邊,并為詞的標(biāo)題添加了書名號(hào),最終的運(yùn)行結(jié)果如下。誰(shuí)念西風(fēng)獨(dú)自涼,蕭蕭黃葉閉疏窗。沉思往事立殘陽(yáng)。被酒莫驚春睡重,賭書消得潑茶香。當(dāng)時(shí)只道是尋常。——【清】納蘭性德
·《浣溪沙》向文本文件寫入內(nèi)容的操作可以通過文件對(duì)象的write()方法來完成,該方法只是將指定的字符
串寫入文件,如果需要換行,則換行符也需要調(diào)用者提供。代碼
7.6
使用
write()方法向文本文件寫入
3
個(gè)“不要回答!”,因?yàn)闆]有提供換行符,所以雖
然代碼分
3行調(diào)用了
3次
write()方法,但是寫入的
3個(gè)“不要回答!”會(huì)出現(xiàn)在同一行。如果希望文件中分
3行書寫,那么應(yīng)該改為“不要回答!\n”。代碼
7.6使用文件對(duì)象的write()方法另外需要注意的是,上述代碼使用了“w”模式打開文件,如果使用“r”模式打開文件,那么
是無法寫入內(nèi)容的。但“w”模式意味著每次寫入內(nèi)容時(shí)都會(huì)覆蓋原來的內(nèi)容,如果想要在原來內(nèi)容的基礎(chǔ)上追加內(nèi)容,那么就要使用“a”模式打開文件。7.2.2寫入文本文件#文本文件如果事先不存在,則
w模式下
open()函數(shù)會(huì)自動(dòng)創(chuàng)建該文件myfile=open("file/三體.txt","w")myfile.write("不要回答!")myfile.write("不要回答!")myfile.write("不要回答!")myfile.close()無論是讀取內(nèi)容還是寫入內(nèi)容,每次打開文件時(shí)都要記著使用完畢后關(guān)閉文件。可要是遺忘了
怎么辦呢?為了確保文件用完之后關(guān)閉,也省去每次都要調(diào)用
close()方法的麻煩,Python提供了with
語(yǔ)句,這個(gè)語(yǔ)句可以進(jìn)行某種情景管理。當(dāng)使用open()函數(shù)打開文件得到文件對(duì)象后,把文件對(duì)象交給with
語(yǔ)句,with
語(yǔ)句會(huì)維護(hù)著使用該文件的情景,一旦程序完成了對(duì)該文件的使用,要離開
with情景時(shí),with語(yǔ)句負(fù)責(zé)關(guān)閉文件,無須程序員手動(dòng)書寫
close()方法了。在代碼
7.7
中,使用
open()函數(shù)打開文件后將文件對(duì)象交給
with語(yǔ)句,之后對(duì)文件的操作代碼
都從屬于with情景,因此會(huì)有縮進(jìn)。當(dāng)程序的執(zhí)行離開with語(yǔ)句時(shí)就意味著對(duì)該文件的操作結(jié)束了,
with語(yǔ)句會(huì)自動(dòng)關(guān)閉該文件。代碼
7.7
使用
with語(yǔ)句自動(dòng)關(guān)閉文件7.2.3with語(yǔ)句withopen("file/陶行知名言.txt","a",encoding="utf-8")asmyfile:myfile.write("人生天地間,各自有稟賦;為一大事來,做一大事去。\n")withopen("file/陶行知名言.txt","r",encoding="utf-8")asmyfile:text_lst=myfile.readlines()forline
in
text_lst:print(line[:-1])左側(cè)代碼中,open()函數(shù)返回的文件對(duì)象通過
as關(guān)鍵字起名為
myfile,在
with語(yǔ)句塊內(nèi)可以使
用
myfile
指代這個(gè)文件,對(duì)其進(jìn)行各種操作。從下面的輸出結(jié)果可知,該文本文件在追加內(nèi)容之前,原本有一行陶先生的名言。千教萬(wàn)教,教人求真;千學(xué)萬(wàn)學(xué),學(xué)做真人。人生天地間,各自有稟賦;為一大事來,做一大事去。PART37.3Python生態(tài)系統(tǒng)之os庫(kù)標(biāo)準(zhǔn)庫(kù)
os
的名稱來自
Operating
System(操作系統(tǒng))的縮寫,它是
Python和操作系統(tǒng)打交道的
一個(gè)重要的庫(kù)。平時(shí)交互式操作計(jì)算機(jī)時(shí),免不了要頻繁和文件系統(tǒng)打交道,如創(chuàng)建新的文件夾、
在文件夾路徑中移動(dòng)位置、刪除已有的文件夾、給文件夾和文件改名等操作都是十分常見的。這些操作平時(shí)可以通過鍵盤、鼠標(biāo)交互式完成,但要是在程序代碼中需要做這些操作該怎么辦呢?這時(shí)就該
os庫(kù)出馬了。os庫(kù)中有一個(gè)rename()函數(shù)可以為文件或文件夾修改名稱,如代碼
7.8所示。
代碼
7.8使用
rename()函數(shù)修改文件名7.3.1修改文件名import
oswithopen("file/test.txt","w")asmyfile:myfile.write("仕而優(yōu)則學(xué),學(xué)而優(yōu)則仕\n")myfile.write("意思是工作后還有余力的就應(yīng)該去學(xué)習(xí)進(jìn)修,不斷提高自己;")myfile.write("學(xué)習(xí)、研究之余要多參與具體的工作與實(shí)踐。\n")os.rename("file/test.txt","file/論語(yǔ)摘錄.txt")print("改名成功")這段代碼要求
file文件夾事先存在,test.txt文件存在與否均可,因?yàn)榇a以“w”模式打開test.txt
文件,如果
file
文件夾下沒有該文件則
open()函數(shù)會(huì)創(chuàng)建這個(gè)文件。之后代碼向文件內(nèi)寫入從《論
語(yǔ)
·子張》中摘錄的片段及現(xiàn)代文解釋。當(dāng)with語(yǔ)句結(jié)束時(shí)打開的文件會(huì)被關(guān)閉,對(duì)test.txt文件的占
用將被釋放,從而可以使用os庫(kù)中的rename()函數(shù)對(duì)其進(jìn)行重命名,將“test.txt”改名為“論語(yǔ)摘錄.txt”。可以使用
os庫(kù)中的
remove()函數(shù)刪除文件。例如,代碼
7.9
中如果在詢問是否刪除文件時(shí)回答
“Y”,論語(yǔ)摘錄.txt文件將會(huì)被刪除。代碼7.9
使用
remove()函數(shù)刪除文件remove()函數(shù)在刪除文件時(shí)是直接刪除的,因此使用該函數(shù)時(shí)要謹(jǐn)慎,確保不會(huì)誤操作。7.3.2刪除文件import
oswithopen("file/論語(yǔ)摘錄.txt","w")asmyfile:myfile.write("日知其所亡,月無忘其所能,可謂好學(xué)也已矣。\n")answer=input("要?jiǎng)h除該文件嗎?
(Y/N)")ifanswer.upper()==
"Y":os.remove("file/論語(yǔ)摘錄.txt")print("文件刪除成功。")os
庫(kù)中也有多個(gè)完成文件夾操作的函數(shù),如新建文件夾的mkdir()函數(shù)、切換當(dāng)前文件夾的chdir()
函數(shù)及顯示當(dāng)前路徑下文件清單的
listdir()函數(shù)等。代碼
7.10演示了這幾個(gè)函數(shù)的使用。代碼
7.10os庫(kù)中文件夾相關(guān)的函數(shù)使用示例7.3.3文件夾相關(guān)操作import
osos.mkdir("./mydir")#新建mydir
文件夾,該文件夾不能已經(jīng)存在withopen("中國(guó)小說.txt","w")as
f:f.write("《芙蓉鎮(zhèn)》《平凡的世界》《張居正》《額爾古納河右岸》《蛙》")withopen("外國(guó)小說.txt","w")as
f:f.write("《約翰·克利斯朵夫》《長(zhǎng)日將盡》《亂世佳人》《鼠疫》")print(f"文件夾{current_path}下的文件:")forfile_name
inos.listdir():print(file_name)answer=input("os庫(kù)試驗(yàn)結(jié)束,是否刪除以上文件夾與文件?
(Y/N)")
ifanswer.upper()==
"Y":forfile_name
inos.listdir():os.remove(file_name)
os.chdir("..")os.rmdir("./mydir")print("刪除完畢。")os.chdir("./mydir")current_path=os.getcwd()#刪除每一個(gè)文件
#向上一層#刪除mydir
文件夾#切換當(dāng)前路徑到新建的文件夾
#獲取當(dāng)前路徑代碼
7.10
的運(yùn)行結(jié)果如下。文件夾
D:\代碼示例\mydir下的文件:中國(guó)小說.txt外國(guó)小說.txtos庫(kù)試驗(yàn)結(jié)束,是否刪除以上文件夾與文件?
(Y/N)y刪除完畢。這段代碼首先使用
mkdir()函數(shù)在當(dāng)前文件夾下新建一個(gè)mydir文件夾,“./mydir”
中的點(diǎn)代表
當(dāng)前文件夾。然后使用
chdir()函數(shù)將當(dāng)前路徑切換到新建的
mydir文件夾。而
getcwd()函數(shù)則可以獲
取當(dāng)前的路徑。接下來使用
open()函數(shù)的“w”模式新建兩個(gè)文件,并各自寫入一行文本。代碼最后
通過
listdir()函數(shù)獲取當(dāng)前路徑下即
mydir文件夾下的文件名清單并輸出。讀者可去磁盤上檢驗(yàn)這一
切操作的結(jié)果,確認(rèn)完畢后再來回答是否要?jiǎng)h除這些試驗(yàn)中創(chuàng)建的文件。如果回答“Y”,則接下
來的代碼會(huì)將文件及文件夾都刪除。最后,為了便于記憶,表
7.2給出以上各函數(shù)名稱的含義。7.3.3文件夾相關(guān)操作函數(shù)名含義mkdir()make
directory(創(chuàng)建目錄)chdir()change
directory(修改目錄)rmdir()remove
directory
(刪除目錄)getcwd()get
current
work
directory
(獲取當(dāng)前工作目錄)listdir()list
directory
(列表目錄)表
7.2os庫(kù)的常用函數(shù)PART47.4小試牛刀在掌握了文件的基本使用流程后,本章的小試牛刀環(huán)節(jié)演練幾個(gè)需要訪問文本文件的案例,感受有了文件的加持后程序功能的提升。7.4.1
保存比薩定價(jià)第
6章的小試牛刀練習(xí)了一個(gè)計(jì)算比薩價(jià)格的案例,比薩店提供
2
種尺寸的比薩(12寸、16
寸),
還有
3種調(diào)料
greenpeppers、mushrooms、extracheese。它們的定價(jià)都直接寫在了當(dāng)時(shí)的代碼
中,這意味著如果老板想要調(diào)整價(jià)格就需要修改代碼,這顯然是不現(xiàn)實(shí)的。比較可行的做法是將比薩的基礎(chǔ)價(jià)格及各種調(diào)料的價(jià)格保存在一個(gè)文本文件中,店員可根據(jù)行情修改文本文件中的價(jià)格,程序每次要讀入文本文件中的最新價(jià)格才能正確計(jì)算訂單的最終價(jià)格。小試牛刀7.4.2去掉重復(fù)姓名數(shù)據(jù)分析是
Python非常重要的應(yīng)用領(lǐng)域,很多數(shù)據(jù)在進(jìn)行正式分析之前往往需要進(jìn)行一些預(yù)處
理,這個(gè)過程被稱為“數(shù)據(jù)清洗”。例如,數(shù)據(jù)中的缺失、錯(cuò)漏、冗余重復(fù)、格式不符等問題,都需要進(jìn)行預(yù)處理。這個(gè)例子假設(shè)要分析保存在文件中的一批姓名,由于某種原因,文件中的姓名會(huì)出現(xiàn)重復(fù),而正式的分析過程要求姓名不能重復(fù),因此任務(wù)的目標(biāo)即去掉文件姓名數(shù)據(jù)中的重復(fù)值。7.4.3文件批量重命名很多時(shí)候從網(wǎng)上下載的文件名稱很長(zhǎng),帶有很多前綴或后綴。例如,從
B站下載的視頻文件名
往往帶有“嗶哩嗶哩”“【1080P】”等字樣。這種過長(zhǎng)的文件名在手機(jī)或其他屏幕空間有限的情形
下使用起來并不方便,文件名核心的文字內(nèi)容反而不易瀏覽。這個(gè)例子就是要通過程序代碼能
自動(dòng)對(duì)大量這類文件進(jìn)行重命名,去掉文件名中無關(guān)緊要的文字,使文件名簡(jiǎn)短、醒目。小試牛刀PART57.5拓展訓(xùn)練本案例嘗試模擬訂單的處理過程,其中會(huì)用到一種常見的文本文件——CSV(Comma-Separated
Values)文件,即內(nèi)部數(shù)據(jù)分行,每行的多個(gè)數(shù)據(jù)項(xiàng)之間使用逗號(hào)分隔。這種文件會(huì)被經(jīng)常使用,以至于
Python生態(tài)系統(tǒng)中專門有處理
CSV文件的庫(kù)。不過這個(gè)例子中仍然使用基本的
open()函數(shù)就可以了,畢竟
CSV文件的本質(zhì)還是文本文件。假設(shè)某圖書銷售系統(tǒng)中使用
BookList.csv
文件保存書籍的“名稱”和“單價(jià)”等有關(guān)書籍本身
的基礎(chǔ)信息,另一個(gè)
BookOrder.csv文件記錄著銷售訂單的情況。現(xiàn)在希望根據(jù)以上兩個(gè)
CSV文件打造一個(gè)日銷售報(bào)告系統(tǒng),可以報(bào)告指定日期的銷售詳情,包
括該日共有幾個(gè)訂單,每個(gè)訂單的訂貨書店、所訂書籍名稱、單價(jià)、數(shù)量及每個(gè)訂單的銷售額,最后給出該日的總銷售額。報(bào)告詳情不僅要在屏幕上輸出,還要以類似
OrderReport_日期.csv
的文件形式保存。根據(jù)訂單數(shù)據(jù)生成銷售報(bào)告PART67.6本章小結(jié)本章介紹了使用文件的基本流程,重點(diǎn)講解了文本文件的讀取、寫入操作;介紹了
os庫(kù)中有關(guān)文件系統(tǒng)的相關(guān)函數(shù)。通過幾個(gè)案例演示了文件在程序中的運(yùn)用,并進(jìn)一步實(shí)踐了使用自定義函數(shù)
組織程序代碼。小結(jié)匯報(bào)人:WPSPython程序設(shè)計(jì)基礎(chǔ)第八章處理異常目錄01異常的基礎(chǔ)知識(shí)02異常的種類03主動(dòng)拋出異常04Python生態(tài)系統(tǒng)之shutil庫(kù)目錄06拓展實(shí)踐:給程序做個(gè)彩超07本章小結(jié)05小試牛刀理解異常。掌握異常處理的相關(guān)語(yǔ)句。了解異常的分類。了解匿名函數(shù)的使用方法。掌握
enumerate()函數(shù)的使用方法。在日常生活中每個(gè)人都希望從不生病,然而生病卻是不可避免的。在程序編寫的過程中人們也
希望不要出現(xiàn)任何異常,但異常也是不可避免的。正如生病了要治病,出現(xiàn)異常就需要處理異常。
本章將介紹什么是異常及處理異常的相關(guān)語(yǔ)句。學(xué)習(xí)目標(biāo)PART18.1異常的基礎(chǔ)知識(shí)異常是程序在運(yùn)行過程中由于各種硬件故障(如網(wǎng)絡(luò)中斷,文件不存在等)、軟件設(shè)計(jì)錯(cuò)誤(如
引用不存在的索引)等原因?qū)е碌某绦蝈e(cuò)誤,這些錯(cuò)誤通常會(huì)終止程序的運(yùn)行,使程序崩潰。程序員在編寫程序時(shí)當(dāng)然希望避開所有的異常,但由于程序的運(yùn)行環(huán)境、用戶的操作行為等因
素都不是程序員可以控制的,所以異常也是不可避免的。例如,代碼8.1
接收用戶輸入的兩個(gè)數(shù)并
輸出相除結(jié)果,但即便如此簡(jiǎn)單的一段程序,也有可能出現(xiàn)意外情形而導(dǎo)致異常。代碼
8.1
認(rèn)識(shí)異常在用戶完全按要求輸入時(shí),程序可以正常執(zhí)行并輸出結(jié)果。但如果用戶輸入的不是數(shù)字而是字
母如
a,則會(huì)出現(xiàn)
ValueError異常,錯(cuò)誤信息如下。如果用戶輸入的是數(shù)字,但在輸入除數(shù)時(shí)輸入了
0,則會(huì)出現(xiàn)
ZeroDivisionError異常,錯(cuò)誤信
息如下。如果程序在用戶的輸入不合預(yù)期時(shí)就直接崩潰,這樣的程序太脆弱,缺乏穩(wěn)健性和可用性。為了提高程序的穩(wěn)健性,需要某種機(jī)制來對(duì)異常進(jìn)行妥善的處理,使程序不會(huì)輕易崩潰。8.1.1異常的概念a=float(input('請(qǐng)輸入被除數(shù):'))b=float(input('請(qǐng)輸入除數(shù)(非
0):'))print("二者的商為",a/b)ValueError:couldnotconvert
stringto
float:
'a'ZeroDivisionError:floatdivisionby
zeroPython針對(duì)異常處理的基本策略是使用
try、except等關(guān)鍵字,形成如下的一個(gè)結(jié)構(gòu)。
處理異常的基本語(yǔ)法形式try-except結(jié)構(gòu)的工作原理如下:將有可能產(chǎn)生異常的代碼書寫在
try語(yǔ)句塊中,如果這段代碼執(zhí)行時(shí)一切順利,則后面的各
except語(yǔ)句塊就像不存在一樣。如果
try
語(yǔ)句塊的代碼執(zhí)行時(shí)出現(xiàn)了某種異常,則根據(jù)異常的類型會(huì)激發(fā)相應(yīng)的
except分支下的代碼,或者說異常被相應(yīng)的except分支捕獲。這里“捕獲”的含義是指不要將異常報(bào)告給最終用戶,從而導(dǎo)致程序崩潰,而是在出現(xiàn)某種異常時(shí),
執(zhí)行對(duì)應(yīng)的
except下的異常處理代碼,這段異常處理代碼負(fù)責(zé)對(duì)該類型的異常進(jìn)行妥善的處理。因此
一個(gè)try
語(yǔ)句后可以有多個(gè)
except
語(yǔ)句,用來捕獲可能產(chǎn)生的多種類型的異常,如代碼
8.2所示。代碼
8.2
使用
try-except進(jìn)行異常處理8.1.2異常處理的語(yǔ)法結(jié)構(gòu)try:可能引發(fā)異常的代碼except
異常類型名稱
1:異常處理代碼
1except
異常類型名稱
2:異常處理代碼
2try:a=float(input('請(qǐng)輸入被除數(shù):'))b=float(input('請(qǐng)輸入除數(shù)(非
0):'))print("二者的商為",a/b)exceptZeroDivisionError:print("除數(shù)不能為
0")exceptValueError:print("請(qǐng)輸入數(shù)字")經(jīng)過
try-except結(jié)構(gòu)的改造后,這段代碼在用戶輸入不合要求的數(shù)據(jù)時(shí)就不會(huì)輕易崩潰了。如果
用戶輸入字母等無法轉(zhuǎn)換為數(shù)值型的內(nèi)容,則程序會(huì)提示用戶“請(qǐng)輸入數(shù)字”。如果除數(shù)輸入了
0,
則程序會(huì)提示“除數(shù)不能為0”。無論哪一種情形,程序都會(huì)給出合理的交互信息而不是粗暴地崩潰,這極大地增強(qiáng)了程序的穩(wěn)健性。代碼
8.2
的運(yùn)行結(jié)果如下所示。處理異常的
try、except語(yǔ)句還可以搭配
as、finally等關(guān)鍵字,形成更完備的異常處理結(jié)構(gòu)。下
面看代碼
8.3,這段代碼假設(shè)在指定位置有一個(gè)number_div.txt文件,該文件的每一行都是以冒號(hào)分隔的兩個(gè)數(shù)值,程序的目的是計(jì)算得出每一行兩個(gè)數(shù)值相除的結(jié)果。代碼在
try語(yǔ)句塊后面預(yù)備了
4
個(gè)
except
語(yǔ)句塊,并且最后還有一個(gè)
finally
語(yǔ)句塊。無論
try
語(yǔ)句塊的代碼是否出現(xiàn)異常,finally
語(yǔ)句塊的代碼都是要執(zhí)行的。因此
finally語(yǔ)句塊的代碼經(jīng)常用來做一些必需的善后工作,如代碼
8.3
中關(guān)閉已打開的文件。8.1.2異常處理的語(yǔ)法結(jié)構(gòu)請(qǐng)輸入被除數(shù):46請(qǐng)輸入除數(shù)(非
0):0除數(shù)不能為
0請(qǐng)輸入被除數(shù):45ada請(qǐng)輸入數(shù)字代碼
8.3使用
try-except-finally結(jié)構(gòu)處理異常8.1.2異常處理的語(yǔ)法結(jié)構(gòu)f_obj=Nonetry:f_obj=open("file/number_div.txt","r")content=f_obj.readlines()forline
in
content:numbers=line.split(":")print(float(numbers[0])/float(numbers[1]))print("計(jì)算完畢。")exceptZeroDivisionError:print("除數(shù)不能為
0")exceptValueErrorase:err_msg=
str(e)loc=err_msg.find(":")print("文件中出現(xiàn)非數(shù)值內(nèi)容:",err_msg[loc+1:])exceptFileNotFoundErrorase:err_msg=
str(e)loc=err_msg.find(":")print(f"指定的文件
{err_msg[loc+1:]}
不存在")except:print("出現(xiàn)未知錯(cuò)誤")finally:if
f_obj
!=None:f_obj.close()print("謝謝使用,再見")仔細(xì)觀察這段代碼中出現(xiàn)的
4個(gè)
except語(yǔ)句塊,會(huì)發(fā)現(xiàn)最后一個(gè)
except沒有指明要捕獲的異常
類型,這意味著除前
3個(gè)
except語(yǔ)句塊所處理的異常類型外,程序出現(xiàn)的所有其他類型異常都由最
后的
except語(yǔ)句塊處理。因此這樣的
except必須位于眾多
except語(yǔ)句塊的最后。另外,第
2和第
3個(gè)
except語(yǔ)句使用
as關(guān)鍵字為捕獲的異常對(duì)象命名為
e,這樣做的優(yōu)點(diǎn)是可
以通過名稱訪問捕獲的異常對(duì)象,從而進(jìn)行更多的處理操作。例如,代碼
8.3就將捕獲的名稱為e
的異常對(duì)象通過str()函數(shù)轉(zhuǎn)換為字符串,這個(gè)字符串描述了錯(cuò)誤的信息,其中會(huì)出現(xiàn)一個(gè)冒號(hào),冒
號(hào)后的文本往往是引起異常的源頭。因此程序找到這部分文本將其輸出,以便給用戶更多、更有價(jià)
值的錯(cuò)誤信息。最后的
finally語(yǔ)句塊是無論發(fā)不發(fā)生異常或發(fā)生何種異常都要執(zhí)行的代碼段。這里用來關(guān)閉打
開的文件,防止在處理文件內(nèi)部數(shù)據(jù)的過程中出現(xiàn)異常,程序終止運(yùn)行來不及關(guān)閉文件的情形發(fā)生。
但如果是由于文件路徑等問題導(dǎo)致
open()函數(shù)的執(zhí)行出現(xiàn)異常,文件并沒有成功打開,代碼中
f_obj
變量的值會(huì)是None,此時(shí)就無須關(guān)閉文件了。代碼
8.3
的運(yùn)行結(jié)果取決于實(shí)際情形。如果指定的文件不存在,則運(yùn)行效果如下。如果文件打開沒有問題,但內(nèi)部數(shù)據(jù)有非數(shù)值內(nèi)容,則運(yùn)行結(jié)果如下。其中的“ad”就是文件
中引起異常的文本內(nèi)容。如果文件中的數(shù)據(jù)符合要求,一切順利,則運(yùn)行結(jié)果如下。可見無論何種情形,finally的代碼都被執(zhí)行了,“謝謝使用,再見”的字樣總會(huì)出現(xiàn)在運(yùn)行結(jié)
果中。如果將
try語(yǔ)句塊中進(jìn)行類型轉(zhuǎn)換的
float()函數(shù)去掉,則會(huì)出現(xiàn)前
3個(gè)
except語(yǔ)句塊都無法捕獲的異常,此時(shí)就可以看到第
4個(gè)
except語(yǔ)句塊的效力了。8.1.2異常處理的語(yǔ)法結(jié)構(gòu)指定的文件'file/number_div.txt'
不存在謝謝使用,再見文件中出現(xiàn)非數(shù)值內(nèi)容:
'ad'謝謝使用,再見7.65計(jì)算完畢。謝謝使用,再見PART28.2異常的種類前面的例子涉及了幾種Python
常見的異常類型,
如ZeroDivisionError
、ValueError
及
FileNotFoundError等。它們都是
Python
內(nèi)置的異常類型,此外,Python
內(nèi)置的異常種類還有很多,
下面簡(jiǎn)單介紹幾個(gè)。(
1
)NameError:當(dāng)程序嘗試訪問一個(gè)未定義的變量時(shí)會(huì)引發(fā)NameError異常。例如,如果將
代碼
8.3
中第
1行的
f_obj定義改為注釋,當(dāng)
open()函數(shù)要打開的文件不存在時(shí),最后的
finally語(yǔ)句
塊中的
f_obj變量就會(huì)觸發(fā)NameError異常。(2)IndexError:當(dāng)引用序列中不存在的索引時(shí),會(huì)引發(fā)
IndexError異常。例如,在一個(gè)只有
5
個(gè)元素的列表中要訪問
5或更大的索引序號(hào)時(shí)就會(huì)觸發(fā)這種異常。(3)KeyError:當(dāng)使用映射中不存在的鍵時(shí),會(huì)引發(fā)Keyerror異常。例如,訪問字典中不存在
的鍵時(shí),就會(huì)帶來這種問題。(4)AttributeError:當(dāng)嘗試訪問未知的對(duì)象屬性時(shí),會(huì)引發(fā)AttributeError
異常。例如,變量a
的類型是整型,在沒有將其轉(zhuǎn)換為字符串的情形下卻要調(diào)用a.find()方法,就會(huì)出現(xiàn)“AttributeError:'int'
objecthasnoattribute'find'”的錯(cuò)誤信息。8.2.1內(nèi)置的常見異常種類(5)SyntaxError:當(dāng)
Python解釋器發(fā)現(xiàn)語(yǔ)法錯(cuò)誤時(shí),會(huì)引發(fā)
SyntaxError異常。(6)FileNotFoundError:當(dāng)使用
open()函數(shù)試圖打開不存在的文件時(shí),會(huì)引發(fā)
FileNotFoundError
異常。這個(gè)異常在代碼8.3中已經(jīng)涉及了。找不到文件的原因可能是提供了錯(cuò)誤的文件名,如將
readme.txt錯(cuò)誤地拼寫為readwe.txt;也可能是路徑分隔符與
Python字符串的轉(zhuǎn)義符相沖突造成的。
無論是什么原因?qū)е碌模灰獙?/p>
open()函數(shù)放在
try語(yǔ)句塊中,再配合捕獲
FileNotFoundError類型的
except語(yǔ)句塊即可妥善處理這類異常。Python
內(nèi)置的異常種類很多,這里無法一一講解,但它們都有共同的特征,是更廣泛意義上的
同一類對(duì)象。實(shí)際上
Python
中所有的異常都是對(duì)象,因此
except分支中可以使用
as關(guān)鍵字為捕獲
的異常對(duì)象命名。每一個(gè)異常對(duì)象都有其從屬的類別,這個(gè)類別又有大與小之分,如除數(shù)為
0
激發(fā)
的異常對(duì)象屬于
ZeroDivisionError類,也屬于更大范圍的
ArithmeticError類,當(dāng)然還屬于Exception
類。這就好比一只貓是一個(gè)具體的動(dòng)物,它屬于貓科,也可以說它屬于哺乳動(dòng)物類,還可以說它屬于動(dòng)物類。由此可見,Exception類在
Python異常的類別組成中占有重要地位。8.2.1內(nèi)置的常見異常種類實(shí)際上
Python
中“至高無上”的異常類是
BaseException類,它是所有異常的基類。它又包括
4
個(gè)子類:SystemExit、KeyboardInterrupt、GeneratorExit、Exception。其中,
最重要的是
Exception類,
它是所有常規(guī)異常的基類,之前講到的常見的異常類型都是
Exception類的子類。程序員如果要自定
義異常,則也需要以
Exception類為父類(類是面向?qū)ο缶幊痰幕靖拍?,有關(guān)父類、子類的含義可參閱第
10章)。雖然使用
Exception類可以捕獲所有常規(guī)異常,但是對(duì)于所有異常都使用同一段代碼處理的話,
會(huì)使對(duì)異常的處理過于粗糙。通常情況下,應(yīng)該盡可能使異常處理的粒度細(xì)化,以保證每種異常有
合適的處理方式。因此在except分支中使用Exception
類捕獲異常應(yīng)該作為一種后備的異常處理方式。
換句話說,在
except分支中使用
Exception類的效果類似于在
except分支中不指明異常分類。當(dāng)然,
嚴(yán)格說來二者還是有區(qū)別的,畢竟不是所有的異常都屬于
Exception類。8.2.2Exception異常類盡管
Python提供了相當(dāng)豐富的異常類型,但有時(shí)為了處理特定的業(yè)務(wù)邏輯,如某個(gè)軟件應(yīng)用所
特有的運(yùn)行錯(cuò)誤,需要根據(jù)程序的邏輯在程序中自行定義需要的異常類和異常對(duì)象。Python要求程序自行定義的異常類必須繼承
Exception
類或其他某個(gè)
Exception類的子類。換句
話說,自定義異常類必須以Exception
類為基類。通常的做法是先為自己的程序創(chuàng)建一個(gè)派生自
Exception類的自定義異常類,然后從此自定義異常類派生其他異常類。這樣不但清晰明了,也方便
管理,如代碼
8.4所示。有關(guān)類的定義與繼承的語(yǔ)法會(huì)在第
10章中進(jìn)行介紹。代碼
8.4自定義異常類示意由于大多數(shù)
Python
內(nèi)置異常的名稱都以“Error”結(jié)尾,所以自定義異常類并對(duì)類進(jìn)行命名時(shí)要
遵循同樣的風(fēng)格。8.2.3自定義異常類classMyError(Exception):#MyError類是
Exception類的子類passclassAError(MyError):#AError類是MyError類的子類passclassBError(MyError):#BError類是MyError類的子類passPART38.3主動(dòng)拋出異常某些情形下,程序運(yùn)行時(shí)也可以主動(dòng)拋出異常。這種異常一般不是指發(fā)生了內(nèi)存溢出、列表索
引越界等系統(tǒng)級(jí)異常,而是程序在執(zhí)行過程中發(fā)生了不符合業(yè)務(wù)邏輯的情形,主要使用的多是用戶自定義異常。主動(dòng)拋出異常一般可以使用raise語(yǔ)句和
assert語(yǔ)句。代碼
8.3從指定的文件number_div.txt
中讀取數(shù)據(jù),然后進(jìn)行相應(yīng)的處理。代碼考慮了很多異常
情形,如文件不存在、除數(shù)為0、文本無法轉(zhuǎn)換為數(shù)值等。這些錯(cuò)誤一旦發(fā)生,如果不加處理的話
程序就都會(huì)崩潰。如果指定文件內(nèi)部沒有任何數(shù)據(jù)呢?這時(shí)在業(yè)務(wù)邏輯上已經(jīng)與預(yù)期不一致了,但程序運(yùn)行時(shí)并
不會(huì)報(bào)錯(cuò)、崩潰。如果不進(jìn)行顯式的處理,則很有可能會(huì)忽略這種不正常的情形。因此可以將這種
情形定義為一種異常,遇到后主動(dòng)拋出異常,引起外界注意并進(jìn)行后期處理。代碼8.5
演示了自定義異常類型并使用
raise語(yǔ)句拋出該異常,注意其中粗體顯示的代碼。8.3.1使用raise語(yǔ)句上報(bào)異常代碼
8.5
使用
raise語(yǔ)句拋出異常8.3.1寫入文本文件classNoDataError(Exception):#自定義的異常類型,當(dāng)文件中沒有數(shù)據(jù)時(shí)觸發(fā)passf_obj=Nonetry:f_obj=open("file/number_div.txt","r")content=f_obj.readlines()iflen(content)==0:raiseNoDataError("文件沒有數(shù)據(jù)!")forline
in
content:numbers=line.split(":")print(float(numbers[0])/float(numbers[1]))print("計(jì)算完畢。")exceptNoDataErrorase:
#捕獲
raise語(yǔ)句拋出的異常print(e)exceptZeroDivisionError:print("除數(shù)不能為
0")exceptValueErrorase:err_msg=
str(e)loc=err_msg.find(":")print("文件中出現(xiàn)非數(shù)值內(nèi)容:",err_msg[loc+1:])exceptFileNotFoundErrorase:err_msg=
str(e)loc=err_msg.find(":")print(f"指定的文件
{err_msg[loc+1:]}
不存在")except:print("出現(xiàn)未知錯(cuò)誤")finally:if
f_obj
!=None:f_obj.close()print("謝謝使用,再見")當(dāng)指定文件為空文件時(shí),代碼
8.5
的運(yùn)行結(jié)果如下。文件沒有數(shù)據(jù)!謝謝使用,再見程序編寫完成后都要經(jīng)過大量的調(diào)試,去除各種潛藏的“bug”,這個(gè)過程被稱為
debug。在調(diào)
試過程中,如果程序運(yùn)行狀態(tài)已經(jīng)與某種預(yù)期不符,則程序應(yīng)該及時(shí)匯報(bào)出現(xiàn)的問題。這可以通過
assert語(yǔ)句實(shí)現(xiàn)。assert語(yǔ)句也稱為斷言語(yǔ)句,它可以指明程序邏輯預(yù)期應(yīng)該滿足的條件,當(dāng)程序?qū)?/p>
際運(yùn)行沒有滿足該條件時(shí)會(huì)觸發(fā)
AssertionError異常。assert語(yǔ)句的用法如下。當(dāng)程序應(yīng)滿足的條件表達(dá)式結(jié)果為真時(shí),不會(huì)拋出異常。當(dāng)程序運(yùn)行不滿足條件表達(dá)式時(shí),會(huì)
引發(fā)
AssertionError異常。其中第
2項(xiàng)的描述信息是可選的,一般是一個(gè)字符串,用于描述異常信息。8.3.2使用assert語(yǔ)句調(diào)試程序assert
應(yīng)滿足的條件表達(dá)式,不滿足時(shí)的描述信息通過設(shè)置異常信息,就可以及時(shí)發(fā)現(xiàn)程序運(yùn)行與預(yù)期不符之處,從而查找原因、改進(jìn)代碼。下面看代碼
8.6
的演示。代碼
8.6
使用
assert語(yǔ)句調(diào)試程序8.3.2使用assert語(yǔ)句調(diào)試程序f_obj=open("file/number_div.txt","r")content=f_obj.readlines()try:forline
in
content:numbers=line.split(":")
#中文冒號(hào),與文件使用的英文冒號(hào)不符assertlen(numbers)==2,"數(shù)據(jù)行拆分不正確!"print(float(numbers[0])/float(numbers[1]))print("計(jì)算完畢。")exceptAssertionErrorase:print(e)f_obj.close()print("謝謝使用,再見")這段代碼在進(jìn)行數(shù)據(jù)行以冒號(hào)為標(biāo)志拆分時(shí),誤將文件使用的英文冒號(hào)書寫為中文冒號(hào),因此
會(huì)導(dǎo)致拆分失敗。這個(gè)小錯(cuò)誤不仔細(xì)看不容易發(fā)現(xiàn)。但如果在拆分后添加assert
斷言,判斷拆分得到的
numbers列表長(zhǎng)度是否為
2。如果不是預(yù)期的
2,就會(huì)激發(fā)
AssertionError異常,該異常的描述信息是由
assert語(yǔ)句的第
2個(gè)參數(shù)指定的。異常被
except語(yǔ)句捕獲后,異常處理語(yǔ)句輸出“數(shù)據(jù)行
拆分不正確!”,這樣就知道程序運(yùn)行的故障在哪里,有的放矢地去改進(jìn)代碼。程序最后調(diào)試完成后,這些
assert語(yǔ)句都應(yīng)該從最終版本的程序代碼中去除。當(dāng)然,即使有assert
語(yǔ)句,有其他各種調(diào)試功能的幫助,程序員也無法保證代碼執(zhí)行時(shí)不出現(xiàn)異常,沒有bug。用平和的心態(tài)對(duì)待異常,盡可能地預(yù)備好
except分支的代碼,設(shè)置好各種預(yù)案,異常就沒有那么可怕了。PART48.4Python生態(tài)系統(tǒng)之shutil庫(kù)為了完成下面的演示,假設(shè)代碼文件存在于子文件夾
test1和
test2
中,而
test1文件夾下有一個(gè)
read_me.txt文件。代碼
8.7演示了各種情形下
copy()函數(shù)的工作結(jié)果。其中,Windows路徑分隔符“\”
每一個(gè)都要書寫兩遍。代碼
8.7
使用
copy()函數(shù)復(fù)制文件代碼中的路徑使用的是相對(duì)路徑,點(diǎn)代表當(dāng)前路徑。其實(shí)換成以盤符開頭的絕對(duì)路徑道理是一
樣的。關(guān)鍵在于目標(biāo)位置的文件夾要事先存在,否則就會(huì)像代碼中最后一行的情形,這是因?yàn)槟繕?biāo)
路徑的
read文件夾不存在而無法完成文件的復(fù)制。8.4.1使用copy()函數(shù)復(fù)制文件import
shutil#指明原文件,目標(biāo)文件名shutil.copy('.\\test1\\read_me.txt','.\\test1\\read.txt')#目標(biāo)文件名未指定,就使用原文件名shutil.copy('.\\test1\\read_me.txt','.\\test2\\')#test2
文件夾存在,但
test2
文件夾復(fù)制下沒有me
文件夾#此時(shí)me
為目標(biāo)文件名,原文件被復(fù)制到
test2
文件夾下,名為me,沒有擴(kuò)展名shutil.copy('.\\test1\\read_me.txt','.\\test2\\me')#目標(biāo)路徑的
read
文件夾不存在,報(bào)錯(cuò)shutil.copy('.\\test1\\read_me.txt','.\\read\\me')
#errorcopy()函數(shù)雖然可以將文件復(fù)制到指定的目標(biāo)位置,但原文件的一些元數(shù)據(jù)(如原文件的訪問時(shí)
間、修改時(shí)間等信息)會(huì)丟失。如果不僅需要將文件中的數(shù)據(jù)復(fù)制一份,而且原文件的有關(guān)元數(shù)據(jù)
也要保留,則可以使用
copy2()函數(shù)復(fù)制文件。下面的代碼
8.8使用
copy()與
copy2()函數(shù)復(fù)制同一個(gè)文件,之后使用
os庫(kù)中的
getmtime()函數(shù)
獲取原文件與兩個(gè)復(fù)制文件的修改時(shí)間(modify
time)。其實(shí)每個(gè)文件都有創(chuàng)建時(shí)間、修改時(shí)間、
最近訪問時(shí)間等
3個(gè)常用的時(shí)間信息。考慮到文件在復(fù)制到新位置后,創(chuàng)建時(shí)間就變成了復(fù)制動(dòng)作
發(fā)生的時(shí)刻,但修改時(shí)間保持不變,因此代碼中獲取的是文件的修改時(shí)間。類似的,os庫(kù)中還有g(shù)etctime()
和
getatime()函數(shù)用于分別獲取創(chuàng)建時(shí)間和最后訪問時(shí)間。8.4.2使用copy()函數(shù)復(fù)制文件的元數(shù)據(jù)從代碼
8.8
的運(yùn)行結(jié)果中顯然可見,copy2()函數(shù)復(fù)制的文件保留了原文件的修改時(shí)間,而
copy()
函數(shù)則丟掉了這項(xiàng)信息。代碼
8.8使用
copy2()
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 農(nóng)村土地開發(fā)工程竣工管理辦法
- 娛樂場(chǎng)所安全管理與審計(jì)辦法
- 醫(yī)療衛(wèi)生項(xiàng)目招標(biāo)操作
- 醫(yī)學(xué)學(xué)校租賃教學(xué)醫(yī)院合同
- 新能源工程招投標(biāo)異議樣本
- 旅游區(qū)給水系統(tǒng)施工合同
- 保稅區(qū)消防維保項(xiàng)目招投標(biāo)文件
- 農(nóng)貿(mào)交易誠(chéng)信守則
- 2024年住宅區(qū)開發(fā)土方工程承包合同
- 數(shù)碼產(chǎn)品退換貨標(biāo)準(zhǔn)
- 推拉門安裝技術(shù)交底
- 中班健康《身體上的洞洞》課件
- 2023年04月山東濟(jì)南市槐蔭區(qū)殘聯(lián)公開招聘殘疾人工作“一專兩員”公開招聘筆試參考題庫(kù)+答案解析
- 2023石景山區(qū)高三一模數(shù)學(xué)答案
- 第8講《人無精神則不立 國(guó)無精神則不強(qiáng)》課件
- 神奇飛書課件
- 旅游消費(fèi)者行為智慧樹知到答案章節(jié)測(cè)試2023年山東女子學(xué)院
- 船體強(qiáng)度與結(jié)構(gòu)設(shè)計(jì)課程設(shè)計(jì)
- 概率論與數(shù)理統(tǒng)計(jì)(第五版)習(xí)題答案
- 網(wǎng)簽授權(quán)書(學(xué)生就業(yè)平臺(tái))
- GB/T 14480.1-2015無損檢測(cè)儀器渦流檢測(cè)設(shè)備第1部分:儀器性能和檢驗(yàn)
評(píng)論
0/150
提交評(píng)論