Python 基礎(chǔ)總結(jié)(十)(文件和異常處理)

原文鏈接

文件處理


1.打開文件

使用如下語法:
fileVariable = open(filename, mode)
filename指定一個文件兽埃,mode指定打開文件的方式,具體方式可選擇下表中某一個:

模式 描述
r 為讀取打開一個文件
w 為寫入打開一個文件道宅,如果文件已經(jīng)存在就會覆蓋其內(nèi)容,如果不存在就會創(chuàng)建文件
a 打開一個文件從文件末尾追加數(shù)據(jù)
rb 為讀取二進制數(shù)據(jù)打開文件
wb 為寫入二進制數(shù)據(jù)打開文件

例如:

input = open(r"/home/usr/test.txt", "r")

2.寫入數(shù)據(jù)

  • 2.1 當使用open函數(shù)成功后就會創(chuàng)建一個文件對象(_io.TextIOWrapper類的實例),它包含了讀寫數(shù)據(jù)和關(guān)閉文件的方法,如下表:
_io.TextIOWrapper
read([number.int]): str 返回自定個數(shù)個字符忱反,如果參數(shù)被忽略渤弛,那么讀取文件中全部剩余的內(nèi)容
readline(): str 以字符串格式返回文件下一行
readlines(): list 返回文件剩余行的列表
write(s: str): None 向文件寫入字符串
close(): None 關(guān)閉文件

提示:我們知道當使用print()函數(shù)的時候祝拯,函數(shù)會在顯示字符串后面自動添加一個換行符\n,但是這里的write函數(shù)不會自動添加換行符進來她肯,所以當我么希望換行的時候佳头,必須主動的給文件寫入一個換行字符。

  • 2.2 檢測文件存在性

    為了防止在當前目錄下已經(jīng)存在的文件被意外消除晴氨,在打開一個文件進行寫操作前應該檢測該文件是否已經(jīng)存在康嘉。可以使用os.path模塊中的isfile函數(shù)判斷籽前,當文件存在就會返回true, 例:

import os.path

if os.path.isfile("presidents.txt"):
    print("文件已經(jīng)存在")
  • 2.3 從文件中讀取所有數(shù)據(jù)

可以使用read()(返回字符串)或readlines()(返回字符串列表)讀取文件的所有行亭珍,但是這比較適用于小文件,當文件過大的時候枝哄,無法全部存在存儲器中肄梨。那么可以使用循環(huán)一次讀取一行來進行讀取。Python中允許使用for循環(huán)來讀取文件所有行:

for line in infield:

例:將文件f1中的數(shù)據(jù)寫入到f2中:

import os.path
import sys


def main():
    
    f1 = input("請輸入原文件:").strip()
    f2 = input("請輸入目標文件:").strip()
    
    if os.path.isfile(f2):
        print(f2 + "已經(jīng)存在了")
        sys.exit()
        
    infile = open(f1, "r")
    outfile = open(f2, "w")
    
    countLines = countChars = 0
    for line in infile:
        countLines += 1
        countChars += len(line)
        outfile.write(line)
    print(countLines, "lines and", countChars, "chars copied")
    
    infile.close()
    outfile.close()

main()

處理文件后記得關(guān)閉挠锥。

  • 2.4 將數(shù)字寫入文件
    將數(shù)字寫入文件需要先轉(zhuǎn)換成字符串众羡,然后使用write方法將它們寫入文件。

3.文件對話框

關(guān)鍵點:tinter.filedialog模塊中提供了askopenfilename和filesaveasfilename函數(shù)來顯文件打開和保存為對話框蓖租。

例如:

from tkinter.filedialog import askopenfilename
from tkinter.filedialog import asksaveasfilename

filenameforReading = askopenfilename()

print("you can read from" + filenameforReading)

filenameforWriting = asksaveasfilename()

print("you can write data to " + filenameforWriting)

運行這段代碼粱侣,askopenfilename()函數(shù)會顯示選擇文件的對話框:

Snip20161108_1.png

asksaveasfilename()函數(shù)將顯示保存為的對話框:

Snip20161108_2.png

例子:
簡單的文本編輯器:

from tkinter import *
from  tkinter.filedialog import askopenfilename
from tkinter.filedialog import asksaveasfilename

class FileEditor:
    def __init__(self):
        window = Tk()
        window.title("簡單的編輯器")

        menubar = Menu(window)
        window.config(menu = menubar)

        operationMenu = Menu(menubar, tearoff = 0)
        menubar.add_cascade(label = "文件", menu = operationMenu)
        operationMenu.add_command(label = "打開", command = self.openFile)
        operationMenu.add_command(label = "保存", command = self.saveFile)

        frame = Frame(window)
        frame.grid(row = 1, column = 1)

        scrollbar = Scrollbar(frame)
        scrollbar.pack(side = RIGHT, fill = Y)
        self.text = Text(frame, width = 40, height = 20, wrap = WORD, yscrollcommand = scrollbar.set)
        self.text.pack()
        scrollbar.config(command = self.text.yview)

        window.mainloop()

    def openFile(self):
        filenameforfeading = askopenfilename()
        infile = open(filenameforfeading, "r")
        self.text.insert(END, infile.read())
        infile.close()

    def saveFile(self):
        filenameforwriting = asksaveasfilename()
        outfile = open(filenameforwriting, "w")
        outfile.write(self.text.get(1.0, END))
        outfile.close()
FileEditor()

當點擊文件-打開的時候會讓選擇本地的文件,例子中是選擇了test.py文件菜秦,然后可以選擇文件-保存講文件保存下來甜害。如圖:

Snip20161109_3.png

從網(wǎng)站上獲取數(shù)據(jù)

可以使用urllib.request模塊中的urlopen函數(shù)打開一個統(tǒng)一資源定位器(URL)從網(wǎng)站上讀取數(shù)據(jù)。然后使用decode函數(shù)將讀取的比特形式的數(shù)據(jù)轉(zhuǎn)換成字符串球昨。這里的一個例子是計算一個網(wǎng)址的每個字母出現(xiàn)的次數(shù):

import urllib.request

def main():
    url = input("輸入網(wǎng)址: ").strip()  #例如https://www.baidu.com 
    infile = urllib.request.urlopen(url)

    s = infile.read().decode()
    counts = countLetters(s.lower())
    for i in range(len(counts)):
        if counts[i] != 0:
            print(chr(ord('a') + i) + "出現(xiàn)" + str(counts[i]) + (" time" if counts[i] == 1 else " times"))

def countLetters(s):
    counts = 26 * [0]
    for ch in s:
        if ch.isalpha():
            counts[ord(ch) - ord('a')] += 1
    return counts

main()

在例子中我們?yōu)榱耸箄rlopen識別一個有效的url尔店,url地址需要有http://或https://前綴。如果沒有就會出現(xiàn)異常。

異常處理


異常處理使程序能夠處理異常然后繼續(xù)它的正常執(zhí)行嚣州。

上例中加入我們輸入一個不存在的網(wǎng)址鲫售,就會拋出錯誤:

輸入網(wǎng)址: www.baidu.com
Traceback (most recent call last):
  File "/Users/sl/Desktop/StillClock.py", line 20, in <module>
    main()
  File "/Users/sl/Desktop/StillClock.py", line 5, in main
    infile = urllib.request.urlopen(url)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/urllib/request.py", line 163, in urlopen
    return opener.open(url, data, timeout)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/urllib/request.py", line 451, in open
    req = Request(fullurl, data)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/urllib/request.py", line 269, in __init__
    self.full_url = url
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/urllib/request.py", line 295, in full_url
    self._parse()
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/urllib/request.py", line 324, in _parse
    raise ValueError("unknown url type: %r" % self.full_url)
ValueError: unknown url type: 'www.baidu.com'

這個錯誤信息被稱為堆棧回溯或回溯该肴∏橹瘢回溯到導致這條語句錯誤的地方,錯誤信息會顯示行號匀哄。如果發(fā)生錯誤秦效,我們可以使用Python的異常處理語法來捕獲這個錯誤并提示用戶下一步操作。

try:
    <body>
except <ExceptionType>:
    <handler>

<body>包含可能包含異常的代碼涎嚼,當一個異常出現(xiàn)的時候阱州,<body>中剩余的代碼被跳過,如果該異常匹配一個異常類型法梯,那么該類型下的處理代碼會被執(zhí)行苔货。<handler>是處理異常的代碼。

一個try語法可以有多個except子句來處理不同的異常立哑。這個語句也可以選擇else或finally語句夜惭,語法如下:

try:
    <body>
except <ExceptionType1>:
    <handler1>
    ...
except <ExceptionTypeN>:
    <handlerN>
else:
    <process_else>
finally:
    <process_finally>
  • 當出現(xiàn)異常的時候,按順序檢查是否匹配except子句后面的異常铛绰,如果找到一個匹配诈茧,就處理匹配的異常處理,其他的except子句部分就會被忽略至耻。

  • 如果出現(xiàn)異常若皱,所列的異常類型都不匹配,就會執(zhí)行最后一個except子句的處理尘颓。

  • 如果沒有出現(xiàn)異常就會執(zhí)行else子句走触。

  • finally子句定義收尾動作,無論怎樣都會執(zhí)行疤苹。

使用異常對象處理異常
在except子句中互广,我們可以訪問到這個異常的對象,可以使用如下語法將exception對象賦給一個變量:

try:
    <body>
except <ExceptionType> as ex:
    print("Exception:", ex)

拋出異常

一個異常的拋出是通過異常類實現(xiàn)的卧土。首先創(chuàng)建一個異常對象惫皱,然后通過raise關(guān)鍵字將它拋出。
在程序中當我們希望拋出異常的地方(例如檢測到數(shù)據(jù)不符合我們的需求時候)尤莺,可以使用下面語法從一個正確的異常類創(chuàng)建一個對象并拋給函數(shù)調(diào)用者:

raise ExceptionClass("Something is wrong")
例如一個運行時的錯誤:
raise RuntimeError("錯誤請求")

自定義異常類

BaseException類是所有異常類的父類旅敷,所有的Python異常類都直接或間接地繼承自BaseException類。所以我們可以直接或間接繼承自BaseException類來自定義一個異常類颤霎。

例如:


class InvalidRadiusException(RuntimeError):
    def __init__(self, radius):
        super().__init__()
        self.radius = radius

class Circle():
    def __init__(self, radius):
        self.setRadius(radius)

    def getRadius(self):
        return self.__radius

    def setRadius(self, radius):
        if radius >= 0:
            self.__radius = radius
        else:
            raise InvalidRadiusException(radius)

def main():

    try:
        c1 = Circle(-5)
    except InvalidRadiusException as ex:
        print("半徑是", ex.radius,"不合法")
    except Exception:
        print("一些異常")
    else:
        print("半徑是", c1.getRadius())

main()
#結(jié)果:半徑是 -5 不合法

使用Pickling進行二進制IO

加入往文件中寫入像列表這樣的任何一個對象媳谁,就需要使用二進制IO涂滴。這時候可以使用pickle模塊中的dump和load函數(shù)進行二進制IO操作。
Python的pickle模塊使用強大且有效的算法來序列化和反序列化對象晴音。序列化是指將對象轉(zhuǎn)換為一個能夠存儲一個文件中或網(wǎng)絡上傳輸?shù)淖止?jié)流過程柔纵。反序列化指相反的過程,是從字節(jié)流中提取對象的過程锤躁。
如果不知道文件中有多少對象搁料,可以使用load函數(shù)重復讀取一個文件對象知道函數(shù)拋出一個EOFError異常(文件末尾)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末系羞,一起剝皮案震驚了整個濱河市郭计,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌觉啊,老刑警劉巖拣宏,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沈贝,死亡現(xiàn)場離奇詭異杠人,居然都是意外死亡,警方通過查閱死者的電腦和手機宋下,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門嗡善,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人学歧,你說我怎么就攤上這事罩引。” “怎么了枝笨?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵袁铐,是天一觀的道長。 經(jīng)常有香客問我横浑,道長剔桨,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任徙融,我火速辦了婚禮洒缀,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘欺冀。我一直安慰自己树绩,他們只是感情好,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布隐轩。 她就那樣靜靜地躺著饺饭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪职车。 梳的紋絲不亂的頭發(fā)上瘫俊,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天蛛芥,我揣著相機與錄音,去河邊找鬼军援。 笑死仅淑,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的胸哥。 我是一名探鬼主播涯竟,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼空厌!你這毒婦竟也來了庐船?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤嘲更,失蹤者是張志新(化名)和其女友劉穎筐钟,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體赋朦,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡篓冲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了宠哄。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片壹将。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖毛嫉,靈堂內(nèi)的尸體忽然破棺而出诽俯,到底是詐尸還是另有隱情,我是刑警寧澤承粤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布暴区,位于F島的核電站,受9級特大地震影響辛臊,放射性物質(zhì)發(fā)生泄漏仙粱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一浪讳、第九天 我趴在偏房一處隱蔽的房頂上張望缰盏。 院中可真熱鬧,春花似錦淹遵、人聲如沸口猜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽济炎。三九已至,卻和暖如春辐真,著一層夾襖步出監(jiān)牢的瞬間须尚,已是汗流浹背崖堤。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工郑原, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留难捌,地道東北人要出。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓园蝠,卻偏偏與公主長得像,于是被迫代替她去往敵國和親膀哲。 傳聞我的和親對象是個殘疾皇子迹辐,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

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

  • 定義類并創(chuàng)建實例 在Python中粘拾,類通過 class 關(guān)鍵字定義堪嫂。以 Person 為例偎箫,定義一個Person類...
    績重KF閱讀 3,952評論 0 13
  • 在經(jīng)過一次沒有準備的面試后,發(fā)現(xiàn)自己雖然寫了兩年的android代碼皆串,基礎(chǔ)知識卻忘的差不多了淹办。這是程序員的大忌,沒...
    猿來如癡閱讀 2,843評論 3 10
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理恶复,服務發(fā)現(xiàn)怜森,斷路器,智...
    卡卡羅2017閱讀 134,659評論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法寂玲,類相關(guān)的語法塔插,內(nèi)部類的語法,繼承相關(guān)的語法拓哟,異常的語法,線程的語...
    子非魚_t_閱讀 31,639評論 18 399
  • 2017年8月17日伶授,把小乖送去夏令營断序,和姐妹們提著行李坐??來到大理 最開心的是我們的私家小院,真的是太...
    朱文靜_豆寶貝閱讀 194評論 0 0