Python學習手冊之Python異常和檔案
在上一篇文章中,我們介紹了 Python 的函式和模組,現在我們介紹 Python 中的異常和檔案。
檢視上一篇文章請點選:https://www.cnblogs.com/dustman/p/9963920.html
異常和檔案
異常
異常也叫例外。在之前的幾篇文章中,你已經看到過 異常 。當程式執行錯誤是出現,比如不正確的呼叫和程式碼不規範等。當你的程式出現意外情況是就會發生異常並終止執行。
下面程式碼用 5 除以 0 產生 ZeroDivisionError 異常。
num1 = 5 num2 = 0 print(num1/num2)
執行結果:
>>> ZeroDivisionError: division by zero >>>
不同的原因產生不同的異常,一般有:
ImportError :引入模組錯誤,通常是模組不存在。
IndexError :讀取列表超出索引範圍。
NameError :使用未宣告的變數。
SyntaxError :程式碼語法錯誤。
TypeError :當操作或函式處理不合適型別。
ValueError:內建操作或函式,接收到型別正確,但值不正確。
Python 還有其他幾個內建的異常,比如 ZeroDivisionError 和 OSError。第三方庫也經常定義自己的異常。
異常處理
我們使用 try/except 語句捕捉程式執行時產生的異常。
try塊用來包含可能產生異常的程式碼塊。如果產生異常 try 塊停止執行, except 塊裡的程式碼開始執行,如果程式執行一切正常,則不會執行 except 塊裡的程式碼。
try: num1 = 5 num2 = 0 print(num1/num2) print("Done!") except ZeroDivisionError: print("Has a error") print("due to zero division")
執行結果:
>>> Has a error due to zero division >>>
上面的例子裡 except 語句定義了 ZeroDivisionError 異常捕捉。
try語句可以擁有多個 except 定義語句來處理異常。多個異常也可以使用一個 except 塊來捕捉。
try: var = 5 print(var + "string!") print(var/2) except ZeroDivisionError: print("Divided by zero!") except (ValueError,TypeError): print("Has a error!")
執行結果:
>>> Has a error! >>>
except語句如果沒有申明要鋪獲的異常,將捕獲所有的異常。我們應該謹慎地使用這種異常處理方式,它雖然捕獲了意外錯誤但是卻把程式設計錯誤隱藏了。
try: var = 5 print(var + "string!") print(var/2) except: print("An error occurred")
執行結果:
>>> An error occurred >>>
這種異常處理方式通常用在處理使用者輸入。
finally 語句
假設你正在讀取一份檔案。你應該確保檔案物件被正確關閉,無論是否會發生異常。
為了確保程式碼最終能夠執行不論是否有異常發生,我們可以使用 finally 語句。 finally 放在 try/except 語句的後面。
try: str = "Hello" var = 5 print(str) print(var/0) except ZeroDivisionError: print("Divided by zero") finally: print("This code will run no matter what")
執行結果:
>>> Hello Divided by zero This code will run no matter what >>>
下面程式碼會輸出什麼?
try: print(1) except: print("a") finally: print("Hello")
執行結果:
>>> 1 Hello >>>
finally語句最終會被執行不管前面的異常到沒有捕捉到,包括在 except 語句裡產生的異常。
try: print(1) print(5/0) except ZeroDivisionError: print(Error_var) finally: print("This is executed last!")
執行結果:
>>> 1 This is executed last! ZeroDivisionError: division by zero During handling of the above exception, another exception occurred: NameError: name 'Error_var' is not defined >>>
丟擲異常
使用 raise 語句丟擲一個異常
print(1) raise ZeroDivisionError print(5)
執行結果:
>>> 1 ZeroDivisionError >>>
你需要宣告你要丟擲的例外名稱。
丟擲的異常可以用引數來指出這是什麼錯誤。
age = 12 raise TypeError("Invalid type!")
執行結果:
>>> TypeError("Invalid type!") >>>
在 except 塊裡, raise 語句可以不用宣告異常的名稱重新丟擲捕捉到的異常。
try: num= 5/0 except: print("Has a error") raise
執行結果:
>>> ZeroDivisionError: division by zero Has a error >>>
斷言
Python 的斷言就是檢測一個條件。如果條件為真,它什麼都不做,條件為假會觸發一個錯誤資訊。
斷言可以開啟或關閉。斷言使用 assert 語句宣告。
print(1) assert 1 + 2 == 3 print("Yes") assert 1 + 1 == 0 print("Yes")
執行結果:
>>> 1 Yes AssertionError >>>
程式設計師通常在函式的開頭放置斷言以檢查有效的輸入,在函式呼叫之後放置斷言以檢查有效的輸出。 斷言可以在執行是通過新增 -O 或 -OO 選項來關閉。
下面程式碼打印出來什麼?
print(1) assert 1 != 2 print(2) assert True print(3) assert False print(4) assert 1 + 1 == 2 print(5)
執行結果:
>>> 1 2 3 AssertionError >>>
斷言的第二個引數可以用來給 AssertionError 做引數。
num = 5 assert (num <= 0),"The num is bigger than zero"
執行結果:
>>> AssertionError: The num is bigger than zero >>>
AssertionError 異常可以像任何其他異常一樣使用 try/except 語句被捕捉和處理,如果程式不處理,這種型別的異常將終止程式的執行。
檔案處理
開啟檔案
讀寫檔案是最常見的 IO (輸入輸出)操作。Python 內建了讀寫檔案的函式,要讀寫檔案需要開啟一個檔案物件,使用 open 函式。
open函式開啟的物件在 Python 中統稱為 file-like Object 。除了檔案外,還可以是記憶體的位元組流,網路流,自定義流等等。
f = open("test.txt")
注意:open 函式的引數是檔案的路徑。如果檔案與程式位於同一個目錄中,則可以不要指定路徑直接使用檔名。
可以使用 open 函式的第二個引數來指定開啟檔案的模式。
# read mode open("test.txt", "r") open("test.txt") # write mode open("test.txt", "w") # binary write mode open("test.txt", "wb")
開啟檔案模式列表:
特別注意:使用 "w" 模式時,如果檔案已經存在,會把舊檔案的內容全部都清除掉。
檔案開啟後應該使用 close 方法關閉檔案。
f = open("test.txt","w") # close the file f.close()
接下來我們會讀取和寫入檔案。
讀取檔案
使用 open 方法開啟的檔案可以使用 read 方式來讀取內容。
f = open("test.txt","r") content = f.read() print(content) f.close()
列印檔名為 "test.txt" 的所有內容。
若要讀取一定數量的檔案內容,可以使用一個數字作為引數來呼叫 read 函式。該數字確定要讀取多少個位元組的內容。
可以對同一個檔案物件進行多次的 read 呼叫,該位元組讀取檔案內容。在沒有引數的情況下, read 函式返回檔案的其餘部分。
f = open("test.txt","r") print(f.read(32)) print(f.read(16)) print(f.read(8)) print(f.read()) f.close()
當所有的內容被讀取後,再呼叫 read 函式返回空字串。
f = open("test.txt","r") f.read() print("reading") print(f.read()) print("finished!") f.close()
執行結果:
>>>reading finished! >>>
開啟一個檔案讀取它的內容,列印內容的長度。
f = open("test.txt","r") str = f.read() print(len(str)) f.close()
執行結果:
>>> 16 >>>
要一行一行地讀取,我們可以使用 readline 方法,也使用 readlines 一次讀取所有內容並返回一個列表,列表裡的每一項元素表示一行內容。
f = open("test.txt","r") print(f.readlines()) f.close()
執行結果:
>>> ['I like Python!!!'] >>>
使用 for 語句遍歷檔案的每一行:
f = open("test.txt","r") for line in f: print(line) f.close()
執行結果:
>>>
Line 1 : Hello world!
Line 2 : I like Python!
Line 3 : I like Java!
>>>
在輸出中,返回的行包含換行符,列印 print 函式在輸出的末尾自動新增新行。
寫檔案
使用 write 方法把內容寫到檔案裡。
f = open("test.txt","w") f.write("I am happy!") f.close() f = open("test.txt","r") print(f.read()) f.close()
執行結果:
>>> I am happy! >>>
如果檔案不存在,"w" 將會建立一個檔案。
寫入模式下,如果檔案存在將清除全部內容並往檔案寫入新內容。
f = open("test.txt","r") print("Reading...") print(f.read()) print("Finished!") f.close() f = open("test.txt","w") f.write("New text") f.close() f = open("test.txt","r") print("Reading new contents") print(f.read()) print("Finished!") f.close()
執行結果:
>>> Reading... I am happy! Finished! Reading new contents New text Finished! >>>
特別注意:原有的檔案將被新內容重寫。
如果 write 寫入成功,方法返回寫入的位元組數。
msg = "I like Python!!!" f = open("test.txt","w") count = f.write(msg) print(count) f.close()
執行結果:
>>> 16 >>>
讀寫檔案
確保檔案在使用後始終關閉,避免浪費資源是良好的程式設計習慣。我們使用 try/finally 語句。
try: f = open("test.txt") print(f.read()) finally: f.close()
當異常發生時也能確保檔案物件被正確關閉。
每次都這樣要關閉檔案是在太繁瑣。所以,Python 引入了 with 語句來幫我們自動呼叫 close() 方法。
with open("test.txt") as f: print(f.read())
使用 with 語句開啟檔案是個好習慣,就算有例外發生,with 語句也會自動幫我們關閉檔案控制代碼。
“朝著一個方向瘋狂奔跑的感覺,真好。”