第十章:文件和異常


2018年10月25日

10.1 從文件中讀取數(shù)據(jù)

要使用文本文件中的信息,首先需要將信息讀取到內(nèi)存中谁帕。為此可以一次性讀取文件的全部內(nèi)容,也可以以每次一行的方式逐步讀取。

10.1.1 讀取整個(gè)文件

下面的程序打開并讀取存有三行圓周率值的文件淋纲,并打印其內(nèi)容:

with open('pi_digits.txt') as file_object:
    contents = file_object.read()
    print(contents)

要以任何方式使用文件,都得先打開文件院究,這樣才能訪問它洽瞬。在這里,open('pi_digits.txt')返回一個(gè)表示文件pi_digits.txt的對象业汰;Python將這個(gè)對象存儲(chǔ)在我們將在后面使用的變量中片任。
關(guān)鍵字with在不再需要訪問文件后將其關(guān)閉。在這個(gè)程序中蔬胯,注意到我們調(diào)用了open()对供,但沒有調(diào)用close()。如果在程序中過早地調(diào)用close()氛濒,你會(huì)發(fā)現(xiàn)需要使用文件時(shí)它已關(guān)閉产场,這會(huì)導(dǎo)致更多的錯(cuò)誤。并非在任何情況下都能輕松確定變比文件的恰當(dāng)時(shí)機(jī)舞竿,但通過使用前面所示的結(jié)構(gòu)京景,可讓Python去確定:你只管打開文件,并在需要時(shí)使用它骗奖,Python自會(huì)在合適的時(shí)候自動(dòng)將其關(guān)閉确徙。

10.1.2 逐行讀取

讀取文件時(shí)醒串,常常需要檢查其中的每一行,要以每次一行的方式檢查文件鄙皇,可對文件對象使用for循環(huán):

filename = 'pi_digits.txt'

with open(filename) as file_object:
    for line in file_object:
        print(line)

10.1.3 創(chuàng)建一個(gè)包含文件各行內(nèi)容的列表

使用關(guān)鍵字with時(shí)芜赌,open()返回的文件對象只在with代碼塊內(nèi)可用。如果要在with代碼塊外訪問文件內(nèi)容伴逸,可在with代碼塊內(nèi)將文件的各行存儲(chǔ)在一個(gè)列表中缠沈,并在with代碼塊外使用該列表。

filename = 'pi_digits.txt'

with open(filename) as file_object:
    lines = file_object.readlines()

for line in lines:
    print(line.rstrip())

10.1.4 使用文件的內(nèi)容

讀取文本文件時(shí)错蝴,Python將其中所有的文本都解讀為字符串洲愤,因此處理文件內(nèi)容就是處理字符串(或每行字符串作為元素的列表)。處理字符串的函數(shù)(如去除末尾換行符的rstrip()顷锰,替換字符串的replace柬赐,檢查特定字符串是否出現(xiàn)的in運(yùn)算符等)都可以在處理文本文件時(shí)使用。

10.2 寫入文件

要將文本寫入文件官紫,在調(diào)用open()時(shí)需要提供另一個(gè)形參肛宋,告訴Python你要寫入打開的文件。

filename = 'pi_digits.txt'

with open(filename, 'w') as file_object:
    file_object.write("I love programming.")

調(diào)用open()提供的第二個(gè)實(shí)參('w')表示以寫入模式打開這個(gè)文件万矾,另外可指定的有讀取模式('r')悼吱,附加模式('a')或者能夠讀取和寫入文件的模式('r+')。忽略模式實(shí)參時(shí)良狈,Python將以默認(rèn)的只讀模式打開文件后添。
如果要寫入的文件不存在,函數(shù)open()將自動(dòng)創(chuàng)建它薪丁。然而遇西,以寫入('w')模式打開文件時(shí)千萬要小心,因?yàn)槿绻付ǖ奈募呀?jīng)存在严嗜,Python將在返回文件對象前清空該文件粱檀。
函數(shù)write()不會(huì)在你寫入的文本文本末尾添加換行符,因此要寫入多行時(shí)需要在write()語句中包含換行符漫玄。
如果要給文件添加內(nèi)容茄蚯,而不是覆蓋原有的內(nèi)容,可以附加模式打開文件睦优。以附加模式打開文件時(shí)渗常,Python不會(huì)再返回文件對象前清空文件,而寫入到文件的行都將添加到文件末尾汗盘。如果指定文件不存在皱碘,Python將為你創(chuàng)建一個(gè)空文件。

filename = 'pi_digits.txt'

with open(filename, 'a') as file_object:
    file_object.write("I also love finding meaning in large datasets.\n")
    file_object.write("I love creating apps that can run in a browser.\n")

10.3 異常

10.3.1 使用try-except代碼塊

Python使用被稱為異常的特殊對象來管理程序執(zhí)行期間發(fā)生的錯(cuò)誤隐孽。每當(dāng)發(fā)生讓Python不知所措的錯(cuò)誤時(shí)癌椿,它都會(huì)創(chuàng)建一個(gè)異常對象健蕊。如果你編寫了處理該異常的代碼,程序?qū)⒗^續(xù)運(yùn)行踢俄;如果你未對異常進(jìn)行處理缩功,程序?qū)⑼V梗@示一個(gè)traceback褪贵,其中包含有關(guān)異常的報(bào)告掂之。
程序崩潰可不好抗俄,但讓用戶看到traceback也不是好主意脆丁。不懂技術(shù)的用戶會(huì)被它們搞糊涂,而且如果用戶懷有惡意动雹,他會(huì)通過traceback獲悉你不希望他知道的信息槽卫。訓(xùn)練有素的攻擊者可根據(jù)這些信息判斷出可對你的代碼發(fā)起什么樣的攻擊。
異常是使用try-except-else-finally代碼塊處理的胰蝠,其中elsefinally代碼塊是可選的歼培。使用了try-except代碼塊時(shí),即便出現(xiàn)異常茸塞,程序也將繼續(xù)運(yùn)行:顯示你編寫的友好的錯(cuò)誤信息躲庄,而不是令用戶迷惑的traceback。

try:
    print(5/0)
except ZeroDivisionError:
    print("You can't divide by zero!")

上述代碼中钾虐,我們將導(dǎo)致錯(cuò)誤的代碼行print(5/0)放在了一個(gè)try代碼塊中噪窘,ZeroDivisionError是一個(gè)異常對象;如果try代碼塊中的代碼導(dǎo)致了錯(cuò)誤效扫,Python將查找這樣的except代碼塊倔监,并運(yùn)行其中的代碼,即其中指定的錯(cuò)誤與引發(fā)的錯(cuò)誤相同菌仁。
發(fā)生錯(cuò)誤時(shí)浩习,如果程序還有工作沒有完成,妥善地處理錯(cuò)誤就尤其重要济丘。這種情況經(jīng)常會(huì)出現(xiàn)在要求用戶提供輸入的程序中谱秽;如果程序能夠妥善地處理無效輸入,就能再提示用戶提供有效輸入摹迷,而不至于崩潰疟赊。
下面來創(chuàng)建一個(gè)只執(zhí)行除法運(yùn)算的簡單計(jì)算器:

print("Give me two numbers, and I'll divide them.")

while True:
    first_number = input("\nFirst number: ")
    second_number = input("Second number: ")
    try:
        answer = int(first_number) / int(second_number)
        print(answer)
    except ZeroDivisionError:
        print("You can't divide by 0!")
    except ValueError:
        print("Input are not numbers!")
    else:
        break;        

try-except-else-finally代碼塊的工作原理大致如下:Python嘗試執(zhí)行try代碼塊中的代碼;只有可能引發(fā)異常的代碼才需要放在try語句中泪掀。有時(shí)候听绳,有一些僅在try代碼塊成功執(zhí)行時(shí)才需要運(yùn)行的代碼;這些代碼應(yīng)放在·else代碼塊中异赫。except代碼塊告訴Python椅挣,如果它嘗試運(yùn)行try代碼塊中的代碼時(shí)引發(fā)了指定的異常头岔,該怎么辦。
這里需要注意的是鼠证,try塊中可能引發(fā)錯(cuò)誤的是第一行除法運(yùn)算的代碼峡竣,如果這一行代碼中引發(fā)異常,那么程序會(huì)直接跳轉(zhuǎn)到處理相應(yīng)異常的except部分量九,后續(xù)的print語句不會(huì)執(zhí)行适掰,并且循環(huán)會(huì)繼續(xù)下去,只有當(dāng)除法運(yùn)算成功執(zhí)行時(shí)荠列,才會(huì)運(yùn)行后續(xù)的輸出結(jié)果與else代碼塊中的跳出循環(huán)部分类浪。

10.3.2 決定處理異常的方式

并非每次捕獲到異常時(shí)都需要告訴用戶,也可以在發(fā)生異常時(shí)一聲不吭肌似,就像什么都沒有發(fā)生一樣繼續(xù)運(yùn)行费就。要讓程序在失敗時(shí)一聲不吭,可像通常那樣編寫try代碼塊川队,但在except代碼塊中使用pass語句來明確告訴Python什么都不要做力细。pass語句還充當(dāng)了占位符,它提醒在程序的某個(gè)地方什么都沒有做固额,并且以后也許要在這里做些什么眠蚂。
應(yīng)該根據(jù)實(shí)際情況來選擇向用戶報(bào)告錯(cuò)誤或者在失敗時(shí)一聲不吭,Python的錯(cuò)誤處理結(jié)構(gòu)讓能夠細(xì)致地控制與用戶分享錯(cuò)誤信息的程度斗躏。
編寫得很好并且經(jīng)過詳盡測試的代碼不容易出現(xiàn)內(nèi)部錯(cuò)誤逝慧,如語法或邏輯錯(cuò)誤,但只要程序依賴于外部因素瑟捣,如用戶輸入馋艺、存在指定的文件、有網(wǎng)絡(luò)鏈接迈套,就有可能出現(xiàn)異常捐祠。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市桑李,隨后出現(xiàn)的幾起案子踱蛀,更是在濱河造成了極大的恐慌,老刑警劉巖贵白,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件率拒,死亡現(xiàn)場離奇詭異,居然都是意外死亡禁荒,警方通過查閱死者的電腦和手機(jī)猬膨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來呛伴,“玉大人勃痴,你說我怎么就攤上這事谒所。” “怎么了沛申?”我有些...
    開封第一講書人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵劣领,是天一觀的道長。 經(jīng)常有香客問我铁材,道長尖淘,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任著觉,我火速辦了婚禮村生,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘固惯。我一直安慰自己梆造,他們只是感情好缴守,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開白布葬毫。 她就那樣靜靜地躺著,像睡著了一般屡穗。 火紅的嫁衣襯著肌膚如雪贴捡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評(píng)論 1 297
  • 那天村砂,我揣著相機(jī)與錄音烂斋,去河邊找鬼。 笑死础废,一個(gè)胖子當(dāng)著我的面吹牛汛骂,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播评腺,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼帘瞭,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蒿讥?” 一聲冷哼從身側(cè)響起蝶念,我...
    開封第一講書人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎芋绸,沒想到半個(gè)月后媒殉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡摔敛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年廷蓉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片马昙。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡桃犬,死狀恐怖售貌,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情疫萤,我是刑警寧澤颂跨,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站扯饶,受9級(jí)特大地震影響恒削,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜尾序,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一钓丰、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧每币,春花似錦携丁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至揭保,卻和暖如春肥橙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背秸侣。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來泰國打工存筏, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人味榛。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓椭坚,卻偏偏與公主長得像,于是被迫代替她去往敵國和親搏色。 傳聞我的和親對象是個(gè)殘疾皇子善茎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • 學(xué)習(xí)處理文件;學(xué)習(xí)錯(cuò)誤處理;學(xué)習(xí)異常;學(xué)習(xí)模塊json,能夠保存用戶數(shù)據(jù) 10.1 從文件中讀取數(shù)據(jù) 可以一次性讀...
    Shinichi新一君閱讀 310評(píng)論 0 0
  • python提供了兩個(gè)非常重要的功能來處理python程序在運(yùn)行中出現(xiàn)的異常和錯(cuò)誤巾表。你可以使用該功能來調(diào)試pyth...
    _寧采臣閱讀 1,025評(píng)論 0 10
  • 1.住在森林里的公主 王子翻身下馬集币,腳踩長靴穩(wěn)穩(wěn)的落在地上,不遠(yuǎn)處果然有一個(gè)身著白衣如同公主一般的女子朝著她款款走...
    崖柏今天早起了閱讀 339評(píng)論 4 5
  • 它有了当娱,它帶走了黎明前的喧囂吃既, 似乎一切都成了一個(gè)二維世界, 沒有一點(diǎn)兒響動(dòng)跨细。 就連那風(fēng)兒鹦倚,也不見得了。 我佇立在...
    南城微南閱讀 275評(píng)論 0 4
  • 企業(yè)為什么要建站金 截至2015年底全國共有共青團(tuán)員8746.1萬名(圖)現(xiàn)場:福建山體滑坡掩埋工地 發(fā)現(xiàn)3處生命...
    d4f69164ff8e閱讀 267評(píng)論 0 0