一文搞懂文件操作與異常模塊
本文轉(zhuǎn)載自微信公眾號「數(shù)據(jù)STUDIO」,作者云朵君 。轉(zhuǎn)載本文請聯(lián)系數(shù)據(jù)STUDIO公眾號。
大家好!我是云朵君,今天給大家?guī)硪黄狿ython文件操作與異常處理,這兩個部分往往是初學者入門時容易忽略的部分。大家重點的精力都放在如何寫出高大上的算法,如何畫出酷炫的圖形,如何使用機器學習模型等等,而常常容易忽略Python文件操作與異常處理,這兩個看似不起眼卻在python中卻擔著至關(guān)重要的角色。下面我們就來一起看看吧。
文件操作
我們的程序可以讀取文件,也可以寫入文件。默認情況下,文件以讀模式('r')打開,但也可以以寫模式('w')和附加模式('a')打開。
你的程序可以從文件中讀取信息,也可以向文件中寫入數(shù)據(jù)。從文件中讀取可以讓你處理各種各樣的信息;寫入文件允許用戶在下次運行你的程序時重新開始。您可以將文本寫入文件,還可以將Python結(jié)構(gòu)(如列表)存儲在數(shù)據(jù)文件中。
讀取文件
要從文件中讀取,程序需要打開文件,然后讀取文件的內(nèi)容。您可以一次讀取文件的全部內(nèi)容,也可以逐行讀取文件。with語句確保當程序完成對文件的訪問后,文件被正確地關(guān)閉。
- 一次讀取整個文件
- filename = 'siddhartha.txt'
- with open(filename) as f_obj:
- contents = f_obj.read()
- print(contents)
- 逐行讀取
從文件中讀取的每一行在行尾都有一個換行符,而print函數(shù)會添加它自己的換行符。rstrip()方法消除了打印到終端時會產(chǎn)生的額外空白行。
- filename = 'siddhartha.txt'
- with open(filename) as f_obj:
- for line in f_obj:
- print(line.rstrip())
- 將行存儲在列表中
- filename = 'siddhartha.txt'
- with open(filename) as f_obj:
- lines = f_obj.readlines()
- for line in lines:
- print(line.rstrip())
- 寫入文件
將'w'參數(shù)傳遞給open()告訴Python你想寫入文件。小心:如果文件已經(jīng)存在,這將刪除文件的內(nèi)容。
傳遞'a'參數(shù)告訴Python你想要添加到一個現(xiàn)有文件的末尾。
- 寫入一個空文件
- filename = 'programming.txt'
- with open(filename, 'w') as f:
- f.write("I love programming!")
- 向空文件寫入多行
- filename = 'programming.txt'
- with open(filename, 'w') as f:
- f.write("I love programming!\n")
- f.write("I love creating new games.\n")
- 追加寫入文件
- filename = 'programming.txt'
- with open(filename, 'a') as f:
- f.write("I also love working with data.\n")
- f.write("I love making apps as well.\n")
文件路徑
當Python運行open()函數(shù)時,它會在存儲正在執(zhí)行的程序的同一目錄中查找文件。可以使用相對路徑從子文件夾中打開文件。也可以使用絕對路徑來打開系統(tǒng)中的任何文件。
- 從子文件夾中打開文件
- f_path = "text_files/alice.txt"
- with open(f_path) as f_obj:
- lines = f_obj.readlines()
- for line in lines:
- print(line.rstrip())
- 使用絕對路徑打開文件
- f_path = "/home/ehmatthes/books/alice.txt"
- with open(f_path) as f_obj:
- lines = f_obj.readlines()
- 在Windows上打開文件
Windows有時會錯誤地解釋正斜杠。如果遇到這種情況,請在文件路徑中使用反斜杠。
- f_path = r"C:\Users\ehmatthes\books\alice.txt"
- with open(f_path) as f_obj:
- lines = f_obj.readlines()
Except異常模塊
異常是幫助程序以適當方式響應(yīng)錯誤的特殊對象。例如,如果程序試圖打開一個不存在的文件,可以使用異常來顯示一個信息豐富的錯誤消息,而不是使程序崩潰。
將可能導(dǎo)致錯誤的代碼放置在try塊中。響應(yīng)錯誤時應(yīng)該運行的代碼位于except塊中。只有在try塊成功時才應(yīng)該運行的代碼被放入else塊。
- prompt = "How many tickets do you need? "
- num_tickets = input(prompt)
- try:
- num_tickets = int(num_tickets)
- except ValueError:
- print("Please try again.")
- else:
- print("Your tickets are printing.")
try-except代碼塊
- 處理ZeroDivisionError異常
- try:
- print(5/0)
- except ZeroDivisionError:
- print("You can't divide by zero!")
- 處理FileNotFoundError異常
- f_name = 'siddhartha.txt'
- try:
- with open(f_name) as f_obj:
- lines = f_obj.readlines()
- except FileNotFoundError:
- msg = "Can't find file {0}.".format(f_name)
- print(msg)
在編寫代碼時,很難知道要處理哪種異常。嘗試編寫沒有try塊的代碼,并讓它生成一個錯誤。回溯將告訴您程序需要處理哪種異常。
else代碼塊
try塊應(yīng)該只包含可能導(dǎo)致錯誤的代碼。任何依賴于try塊成功運行的代碼都應(yīng)該放在else塊中。
- 使用else塊
- print("Enter two numbers. I'll divide them.")
- x = input("First number: ")
- y = input("Second number: ")
- try:
- result = int(x) / int(y)
- except ZeroDivisionError:
- print("You can't divide by zero!")
- else:
- print(result)
- 防止用戶輸入導(dǎo)致的崩潰
如果沒有下面示例中的except塊,如果用戶試圖除零,程序?qū)⒈罎ⅰU缢鶎懙模鼘?yōu)雅地處理錯誤并繼續(xù)運行。
- # 一個簡單的除法計算器。
- print("Enter two numbers. I'll divide them.")
- print("Enter 'q' to quit.")
- while True:
- x = input("\nFirst number: ")
- if x == 'q':
- break
- y = input("Second number: ")
- if y == 'q':
- break
- try:
- result = int(x) / int(y)
- except ZeroDivisionError:
- print("You can't divide by zero!")
- else:
- print(result)
默默地失敗
有時希望程序在遇到錯誤時繼續(xù)運行,而不向用戶報告錯誤。在else塊中使用pass語句可以做到這一點。
- 在else塊中使用pass語句
- f_names = ['alice.txt', 'siddhartha.txt',
- 'moby_dick.txt', 'little_women.txt']
- for f_name in f_names:
- # 報告找到的每個文件的長度。
- try:
- with open(f_name) as f_obj:
- lines = f_obj.readlines()
- except FileNotFoundError:
- # 繼續(xù)看下一個文件。
- pass
- else:
- num_lines = len(lines)
- msg = "{0} has {1} lines.".format(
- f_name, num_lines)
- print(msg)
避免空的except塊
異常處理代碼應(yīng)該捕獲在程序執(zhí)行期間預(yù)期發(fā)生的特定異常。空的except塊將捕獲所有異常,包括在強制關(guān)閉程序時可能需要的鍵盤中斷和系統(tǒng)退出。
如果你想使用try塊,但又不確定要捕獲哪個異常,那么使用exception。它將捕獲大多數(shù)異常,但仍然允許您故意中斷程序。
- 避免空的except塊
- try:
- # Do something
- except:
- pass
- 使用Exception
- try:
- # Do something
- except Exception:
- pass
- 打印異常
- try:
- # Do something
- except Exception as e:
- print(e, type(e))
使用json存儲數(shù)據(jù)
json模塊允許您將簡單的Python數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)儲到一個文件中,并在程序下次運行時從該文件加載數(shù)據(jù)。JSON數(shù)據(jù)格式不是特定于Python的,所以你也可以與使用其他語言的人共享這類數(shù)據(jù)。
在處理存儲的數(shù)據(jù)時,了解如何管理異常非常重要。在處理數(shù)據(jù)之前,通常希望確保試圖加載的數(shù)據(jù)存在。
- 使用json.dump()存儲數(shù)據(jù)
- # 存儲一些數(shù)字。
- import json
- numbers = [2, 3, 5, 7, 11, 13]
- filename = 'numbers.json'
- with open(filename, 'w') as f_obj:
- json.dump(numbers, f_obj)
- 使用json.load()存儲數(shù)據(jù)
- # 加載一些以前存儲的數(shù)字。
- import json
- filename = 'numbers.json'
- with open(filename) as f_obj:
- numbers = json.load(f_obj)
- print(numbers)
- 確保存儲的數(shù)據(jù)存在
- import json
- f_name = 'numbers.json'
- try:
- with open(f_name) as f_obj:
- numbers = json.load(f_obj)
- except FileNotFoundError:
- msg = "Can’t find {0}.".format(f_name)
- print(msg)
- else:
- print(numbers)
決定報告哪些錯誤
編寫良好、經(jīng)過適當測試的代碼不太容易出現(xiàn)內(nèi)部錯誤,比如語法或邏輯錯誤。但是,每當你的程序依賴于諸如用戶輸入或文件存在之類的外部因素時,就有可能引發(fā)異常。
如何將錯誤傳達給用戶取決于你自己。有時用戶需要知道一個文件是否丟失了;有時最好是靜默地處理錯誤。一點經(jīng)驗會幫助你知道該報告多少。