2012-02-05 49 views
4

Python新手在這裏。我正在編寫一個腳本,可以將某些輸出轉儲到文件或stdout,具體取決於傳遞給它的參數。在解釋參數時,我將open'ed文件或stdout分配給名爲output_file的全局變量,腳本的其餘部分可以使用該全局變量寫入輸出,而不管選擇了何種類型的流。在腳本的最後我closeoutput_file。這對於文件流來說是適當的,雖然對於標準輸出而言它是多餘的,但我對其他編程語言的經驗表明,在程序結束之前立即顯式關閉標準輸出並不會損害。爲什麼顯式關閉stdout時會出現ValueError?

但是,無論何時將stdout用於輸出(並隨後關閉),我都會在「關閉的文件」上收到「ValueError:'I/O操作。我知道這個錯誤不是由我的調用關閉stdout而直接產生的,而是在腳本返回後發生。我的問題是:爲什麼會發生這種情況,並且有沒有辦法手動關閉stdout而不觸發它? (我知道,我可以很容易地通過有條件地關閉流,只有當選擇了一個文件來解決這個問題,但我想知道是否/爲什麼這是必要的。)

很簡單示範段:

from sys import stdout 
stdout.close() 
+0

請關閉stdout()後,在output_file的任何操作上檢查您的代碼,或者在此處放置更多代碼,因爲只有在代碼段後面使用了output_file.write(..)時,給定代碼段纔會生成ValueError。 – Vladimir 2012-02-05 08:48:23

+0

給定片段自身產生錯誤。 – nonoitall 2012-02-05 09:16:16

回答

5

問題是,在python-3.2有一個嘗試在關機時刷新stdout而不檢查它是否關閉。

issue13444就是這樣。

fixing patch之後的版本中,您不應該在python-2.7中遇到此問題。

+0

很高興聽到這不是我不知道的Python。感謝您指出了這一點。 :-) – nonoitall 2012-02-05 10:18:47

4

以這種方式關閉stdout後,您必須絕對確定沒有任何內容會嘗試打印任何內容到stdout。如果有事情發生,你會得到這個例外。

我的建議是關閉output_file條件:

if output_file != sys.stdout: 
    output_file.close() 

編輯這裏是sys.stdout在腳本的最末端右側封閉的例子,並且仍然產生ValueError: 'I/O operation on closed file時運行。

import atexit 

@atexit.register 
def goodbye(): 
    print "You are now leaving the Python sector." 

import sys 
sys.stdout.close() 
+0

我的腳本沒有任何內容在關閉它的調用之後打印到標準輸出。 (關閉它的呼叫是腳本中的最後一行。)有沒有其他方法可以阻止這個「神祕罪犯」在我關閉它之後使用stdout? :-P – nonoitall 2012-02-05 08:58:00

+0

@nonoitall:當然,你可以抑制它(例如,通過將'stdout'分配給某些丟棄所有寫入它的流)。然而,鑑於此時你甚至不知道它寫給'stdout'的內容,一味地丟棄這個輸出似乎是一件相當愚蠢的事情。 – NPE 2012-02-05 09:05:52

+0

*任何人*知道它寫入標準輸出是什麼?即使從示例腳本中刪除了atexit部分,該錯誤仍然會發生。 (請參閱我的代碼片段。)整個腳本中的唯一一行可以是關閉stdout的調用,並且錯誤仍然會被拋出。 /我想知道爲什麼。 – nonoitall 2012-02-05 09:13:54

0

關閉,您可以檢查output_file.closed文件之前:

if not output_file.closed: 
    output_file.close() 

並確保您有沒有I/O調用結束後OUTPUT_FILE。

+0

不能解決問題。我關閉stdout的電話不是錯誤的直接原因;標準輸出在我關閉時打開。這是在我的腳本返回之後,其他的東西試圖使用流,導致錯誤。我想知道別的是什麼,如果有辦法壓制它。 – nonoitall 2012-02-05 09:01:13

+0

您能否提供錯誤堆棧跟蹤? – Vladimir 2012-02-05 09:57:50

0

有兩件事似乎需要避免這個錯誤:reset(i)reset stdout; (ii)不關閉標準輸出,關閉重定向到的文件。

f=open(filename, 'w') 
sys.stdout = f 
print("la la-la"), file = sys.stdout) 
f.close() 
sys.stdout = sys.__stdout__ 

對這一問題的各種方案建議複製「原始」的stdout指針變量文件標準輸出分配之前(即原來的stdout = ... =標準輸出F),然後將其複製回來之後(標準輸出=原版的)。但他們沒有提到他們日常工作中的最後一次手術,這浪費了數小時的時間。

找到解決方案here

相關問題