10.檔案和異常
檔案和異常
從檔案中讀取資料
要使用文字檔案中的資訊,首先需要將資訊讀取到記憶體中
pi_digits.txt
3.1415926535 8979323846 2643383279
file_reader.py
with open('pi_digits.txt') as file_object: contents = file_object.read() print(contents.rstrip())
函式open()返回一個表示檔案的物件
也可以呼叫open()和close()來開啟和關閉檔案,但是如果程式有Bug,導致close()語句未執行,檔案將不會關閉,可能會導致資料丟失或受損。如果過早呼叫close(),會發現需要使用檔案時它已經關閉,會導致更多錯誤。
方法read()讀取這個檔案的全部內容,並將其作為一個長長的字串儲存在變數contents中;到達檔案末尾時返回一個空字串,顯示出來為一個空行,可用restrip()方法刪除
檔案路徑
將'pi_digits.txt'傳給open()時,Python將在當前執行的檔案所在目錄中查詢檔案
使用相對檔案路徑開啟檔案:Python到相對於當前執行的程式所在目錄進行查詢
with open('text_files\filename.txt') as file_object:
使用絕對路徑:可讀取系統任何地方的檔案
file_path = 'C:\Users\19405\Desktop\filename.txt'
with open(file_path ) as file_object:
絕對路徑通常比相對路徑更長,因此將其儲存在一個變數中,再將該變數傳遞給open()會有所幫助
逐行讀取
file_path = 'pi_digits.txt' with open(file_path) as file_object: for line in file_object: print(line)
消除多餘空白行:
print(line.rstrip())
建立一個包含檔案各行內容的列表
使用關鍵字with時,open()返回的檔案物件只在with程式碼塊內可用
filename = 'pi_digits.txt' with open(filename) as file_object: lines = file_object.readlines() for line in lines: print(line.rstrip())
方法readlines()從檔案中讀取每一行,並將其儲存再一個列表中
filename = 'pi_digits.txt' with open(filename) as file_object: lines = file_object.readlines() pi_string = '' for line in lines: pi_string += line.strip() print(pi_string) print(len(pi_string))
包含一百萬位的大型檔案
filename = 'pi_million_digits.txt' --snip-- print(pi_string[:52] + '...') print(len(pi_string))
birthday = input("Enter your birthday, in the form mmddyy: ") if birthday in pi_string: print("Your birthday appears in the first million digits of pi") else: print("No")
儲存資料最簡單的方式之一
寫入空檔案
filename = 'programming.txt' with open(filename, 'w') as file_object: file_object.write("I love programming.")
open()的第二個實參:
'r':讀取模式
'a':附加模式
'r+':讀取和寫入模式
Python只能將字串寫入文字檔案
寫入多行
函式write()不會再你寫入的文字末尾新增換行符,因此寫入多行時需要指定換行符
filename = 'programming.txt' with open(filename, 'w') as file_object: file_object.write("I love programming.\n") file_object.write("I love creating new games.\n")
給檔案新增內容,而不是覆蓋原有的內容
附加模式
filename = 'programming.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 new games.\n")
異常
每當發生錯誤時,都會建立一個異常物件
異常是使用try-except程式碼塊處理的。使用了該模組,即便出現異常,程式也將繼續執行
處理ZeroDivisionError異常
print(5/0)
程式執行失敗,並返回一個Traceback,建立了一個ZeroDivisionError物件
使用try-except程式碼塊
編寫一個try-except程式碼塊來處理可能發生的異常
try: print(5 / 0) except ZeroDivisionError: print("You can't divide by zero")
如果try程式碼塊中的程式碼執行沒有問題,將跳過except程式碼塊;
如果try程式碼塊的程式碼導致了錯誤,Python將查詢這樣的expect程式碼塊,並執行其中的程式碼,即其中指定的錯誤與引發的錯誤相同
經常用於要求使用者提供輸入的程式中
如果程式能夠妥善地處理無效輸入,就能再提示使用者提供有效輸入,而不至於崩潰
division.py
print("Give me two number, and I will divide them.") print("Enter 'q' to quit.") while True: first_number = input("\nFirst number: ") if first_number == 'q': break second_number = input("\nSecond number: ") if second_number == 'q': break answer = int(first_number) / int(second_number) print(answer)
second_number輸入為0會導致程式崩潰
將可能引發錯誤地程式碼放在try-except程式碼塊中,可提高這個程式地低於錯誤地能力
print("Give me two number, and I will divide them.") print("Enter 'q' to quit.") while True: first_number = input("\nFirst number: ") if first_number == 'q': break second_number = input("\nSecond number: ") if second_number == 'q': break try: answer = int(first_number) / int(second_number) except ZeroDivisionError: print("You can't divide by 0!") else: print(answer)
依賴於try程式碼塊成功執行地程式碼都放在else程式碼塊中
處理FileNotFoundError異常
找不到檔案
filename = 'alice.txt' try: with open(filename) as f_obj: contents = f_obj.read() except FileNotFoundError: print("Sorry, the file " + filename + " dose not exist.")
分析文字
split()方法:根據一個字串建立一個單詞列表;以空格為分隔符拆分字串
def count_words(filename): """計算一個檔案大致包含多少單詞""" try: with open(filename) as f_obj: contents = f_obj.read() except FileNotFoundError: print("Sorry, the file " + filename + " dose not exist.") else: # 計算檔案大致包含多少個單詞 words = contents.split() num_words = len(words) print("The file " + filename + " has about " + str(num_words) + "words.") filename = 'alice.txt' count_words(filename)
在expect程式碼塊中明確告訴Python什麼都不要做
pass語句:讓Python什麼都不做
except FileNotFoundError: pass
決定報告哪些錯誤
憑藉經驗判斷該在程式地什麼地方包含異常處理塊,以及出現錯誤時該向使用者提供多少相關資訊
儲存資料
使用模組josn來儲存資料
使用json.dump()和json.load()
json.dump()儲存資料列表
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()將列表讀取到記憶體中
import json filename = 'numbers.json' with open(filename) as f_obj: numbers = json.load(f_obj) print(numbers)
import json #如果以前儲存了使用者名稱,就載入它;否則,就提示使用者輸入使用者名稱並存儲它 filename = 'name.json' try: with open(filename) as f_obj: username = json.load(f_obj) except FileNotFoundError: username = input("What's your name: ") with open(filename, 'w') as f_obj: json.dump(username, f_obj) print("Hello, " + username) else: print("Welcome back, " + str(username) + "!")
重構
import json def get_stored_username(): """如果儲存了使用者名稱,就獲取它""" filename = 'name.json' try: with open(filename) as f_obj: username = json.load(f_obj) except FileNotFoundError: return None else: return username def get_new_username(): """提示使用者輸入使用者名稱""" username = input("What's your name: ") filename = 'name.json' with open(filename, 'w') as f_obj: json.dump(username, f_obj) return username def greet_user(): """問候使用者,並指出其名字""" username = get_stored_username() if username: print("Welcome back, " + username + "!") else: username = get_new_username() print("We'll remeber you when you come back, " + username + "!") greet_user()