2009-09-03 33 views
10

要讀取文件的內容:文件打開:這是不好的Python風格?

data = open(filename, "r").read() 

打開文件立即停止當前的任何地方引用,因此該文件對象將最終報收...它不應該使用它影響其他程序,因爲該文件是隻開放閱讀,不寫作。

編輯:這實際上已經咬傷了我的項目,我寫的 - 它促使我提出this問題。只有在內存不足時清理文件對象,而不是用完文件句柄。所以如果你經常這樣做,你最終可能會耗盡文件描述符,導致IO嘗試打開文件以引發異常。

+3

請注意,這將讀取整個文件到內存中,不管它有多大。所以確保它是一個你可以處理的文件。除此之外,我同意答案。 – balpha 2009-09-03 14:23:23

+0

@balpha:但答案是相互矛盾的。 ;)(我假設你在所有答案都在之前發表了評論。) – 2009-09-04 02:55:51

回答

29

只是爲了記錄: 這只是稍長,並立即關閉文件:

from __future__ import with_statement 

with open(filename, "r") as f: 
    data = f.read() 
+4

+1爲了防止他們使用Python 2.5,我添加了'import': – 2009-09-03 14:26:24

+0

後續樣式問題:將open(「t1.py」,「r」)作爲f:f是否真的很糟糕。 read()*全部在一行上?我知道這不是可讀的,但經常閱讀文件是非常基本的事情,下一個閱讀代碼的人真的不在乎你是如何做到的。 – 2009-09-03 17:47:56

+0

@Jenn D:'with'的一點是將所有的處理都限制在一個整潔的範圍內。把'open()作爲f:f.read()'放在一行中會使'with'的作用範圍失效。 – 2009-09-03 18:19:18

3

不,這是完全合理的Python風格IMO,按照你的理由。

更新:這裏有很多關於文件對象是否立即整理的評論。而不是推測,我做了一些挖掘。這是我看到:


從Python的 object.h評論:

宏Py_INCREF(OP)和 Py_DECREF(OP)用於增加或 遞減引用計數。

功能表文件對象指向功能file_dealloc:當引用計數下降到0

展望Python的fileobject.c Py_DECREF 調用該對象的釋放器 功能。此功能 調用close_the_file,後者依次關閉該文件。


所以它似乎是合理的狀態,在目前,在CPython的,當沒有 更上一個文件對象的引用,它沒有任何延遲關閉。如果你認爲這種解釋是錯誤的,請發表評論,說明你爲什麼這樣認爲。

+0

雖然合理,但是操作系統資源可能並非完全可用。例如,試圖在讀取文件後立即刪除文件可能無法正常工作,因爲即使認爲Python文件對象已被垃圾收集,底層C庫也保留了操作系統資源。在操作系統認爲該文件不再被使用之前,您可能無法刪除它。 – 2009-09-03 14:32:27

+0

@ S.洛特:你是說垃圾收集的'文件'對象沒有關閉(以便操作系統知道它不再被使用)?我會*期望*刪除一個文件對象關閉文件,但在文檔中找不到任何東西。 – EOL 2009-09-03 14:58:02

+5

我的理解是,CPython(大多數人認爲當他們認爲Python的參考實現)確實會在所有未引用的對象離開作用域時銷燬所有未引用的對象。在這種情況下,只要read()操作完成,文件對象就會離開作用域。所以它應該做你想要的。然而,這不是保證的行爲。 Python的其他實現(Jython我認爲是一個很好的例子)可能會以不同方式處理垃圾收集。我的直覺是如果你知道你正在使用CPython並且不關心可移植性,那就使用簡單的實現。 – 2009-09-03 15:12:01

1

看起來好像沒什麼問題。我經常讀文件那樣。

6

這是事實,它最終會關閉,但最終可能不會很快。特別是如果你在一個循環中使用它,在GC到達文件對象之前,系統可能會耗盡文件句柄。

+0

哦,沒想到那個! – Claudiu 2009-09-03 14:33:37

+0

但是,如果fileobj是引用計數..它直接進入0,並立即刪除?在CPython(?)中。 – u0b34a0f6ae 2009-09-03 19:03:27

+0

@ kaizer.se:它仍然不一定會立即刪除。只有當CPython需要更多內存時。 – Claudiu 2009-09-04 16:44:20

4

代碼工作完全按照您說的這樣做,但它的壞作風不過。你的代碼依賴於現在可能是正確的假設,但並不總是如此。你的代碼在文件被打開的情況下運行並不是不可能的,確實是的問題。僅僅爲了保存1或2行代碼真的值得冒這個風險嗎?我不這麼認爲。

2

即使它正常工作,我認爲它在兩項失敗:

  1. 您的代碼將無法無縫地擴展,因爲你正在閱讀的整個文件到內存中,這可能是也可能不是一定是你想要的。
  2. 根據Python的Zen(在Python提示符下嘗試import this來檢索它),「顯式比隱式更好」,並且由於未能明確關閉文件,可能會混淆某些在路上將要離開的人與您的代碼進行維護。

這真的有助於明確! Python鼓勵顯式風格。

除此之外,對於一次性腳本,你的風格是有道理的。

也許你會受益於this answer