如果不用“with”,那么Python會在何時關閉文件呢?答案是:視情況而定。
Python程序員最初學到的東西里有一點就是可以通過迭代法很容易地遍歷一個打開文件的全文:
f = open('/etc/passwd')for line in f: print(line)
注意上面的代碼具有可行性,因為我們的文件對象“f”是一個迭代器。換句話說,“f“ 知道在一個循環或者任何其他的迭代上下文中做什么,比如像列表解析。
我的Python課堂上的大多數學生都具有其他編程語言背景,在使用以前所熟悉的語言時,他們總是在完成文件操作時被期望關閉文件。因此,在我向他們介紹了Python文件操作的內容不久后他們問起如何在Python中關閉文件時,我一點都不驚訝。
最簡單的回答就是我們可以通過調用f.close()顯式地關閉文件。一旦我們關閉了文件,該文件對象依然存在,但是我們無法再通過它來讀取文件內容了,而且文件對象返回的可打印內容也表明文件已經被關閉。
>>> f = open('/etc/passwd')>>> f<open file '/etc/passwd', mode 'r' at 0x10f023270>>>> f.read(5)'##n# ' f.close()>>> f<closed file '/etc/passwd', mode 'r' at 0x10f023270> f.read(5)---------------------------------------------------------------------------ValueError Traceback (most recent call last)<ipython-input-11-ef8add6ff846> in <module>()----> 1 f.read(5)ValueError: I/O operation on closed file
所以是這樣,我在用Python編程的時候,很少明確地對文件調用 “close” 方法。此外,你也很可能不想或不必那樣做。
打開文件的優選最佳實踐方式是使用 “with” 語句,就像如下所示:
with open('/etc/passwd') as f: for line in f: print(line)
“with”語句對 “f” 文件對象調用在Python中稱作“上下文管理器”的方法。也就是說,它指定 “f” 為指向 /etc/passwd 內容的新的文件實例。在 “with” 打開的代碼塊內,文件是打開的,而且可以自由讀取。
然而,一旦Python代碼從 “with” 負責的代碼段退出,文件會自動關閉。試圖在我們退出 “with”代碼塊后從 f 中讀取內容會導致和上文一樣的 ValueError 異常。所以,通過使用 “with”,你避免了顯式地關閉文件的操作。Python 會以一種不那么有 Python 風格的方式在幕后神奇而靜靜地替你關閉文件。
但是你不顯式地關閉文件會怎樣?如果你有點懶,既不使用 “with” 代碼塊也不調用f.close()怎么辦?這時文件會什么時候關閉?何時應該關閉文件?
我之所以問這個,是因為我教了這么多年Python,確信努力教授“with”或上下文管理器的同時又教很多其它的話題超出了學生接受的范圍。在介紹性課程談及 “with” 時,我一般會告訴學生在他們職業生涯中遇到這個問題時,讓Python去關閉文件就好,不論文件對象的應用計數降為0還是Python退出時。
新聞熱點
疑難解答