2017-08-04 61 views
1

看過其他stackoverflow帖子後,我似乎無法找出這個重定向問題。我想要做的是壓制stdout和stderr,然後在捕獲錯誤之後恢復它們。壓制工作正常,但恢復他們只有一半作品。如果我試圖壓制並恢復stderr和stdout,那麼壓制就會起作用,但不會恢復。如果我只是試圖壓制/恢復標準輸出它可以工作(但是我得到了所有我不想要的標準輸入文本)。我無法推斷爲什麼會有任何差異導致stderr阻止標準輸出恢復,希望爲什麼可能是(或如果我做的事情奇怪/愚蠢)輸入

繼承人的代碼,我想工作,但只抑制了/犯錯,也不會恢復(「恢復標準輸出」從不打印):恢復重定向sys.stdout和sys.stderr產生奇怪的結果

sys.stdout = None 
sys.stderr = None 
try: 
    op_args = op_parse.parse_args(selection.split(' ')) 
except SystemExit: 
    sys.stdout = sys.__stdout__ 
    sys.stderr = sys.__stderr__ 
    print("Restored stdout") 


繼承人抑制stdout和恢復它(在印刷討厭的標準錯誤的成本)的代碼

sys.stdout = None 
#sys.stderr = None 
try: 
    op_args = op_parse.parse_args(selection.split(' ')) 
except SystemExit: 
    sys.stdout = sys.__stdout__ 
    #sys.stderr = sys.__stderr__ 
    print("Restored stdout") 

編輯:我想了一個窩周圍,​​但我仍然對上述問題發生的原因感興趣。我的工作是將stdout/stderr重新分配給= open(「/ dev/null」,「w」),它產生了我想要的行爲。再次,我仍然想對原始問題的輸入

回答

0

作爲一個高層次的評論,這種技術是容易出錯,通常意味着其他事情出錯了。例如 - 在上面的except中恢復(而不是在finally中)意味着如果失敗,則恢復stdout和stderr 只有

我懷疑你觀察到的問題可能是由於你的op_parse調用。考慮下面的代碼

from __future__ import print_function 
import sys 

sys.stdout = None 
sys.stderr = None 
try: 
    print('before', file=sys.stdout) 
    print('before', file=sys.stderr) 
    # sys.stderr.write('hi') 
    assert False 
except AssertionError: 
    sys.stdout = sys.__stdout__ 
    sys.stderr = sys.__stderr__ 
    print("Restored stdout", file=sys.stdout) 

當我運行它時,我看到:Restored stdout

如果我取消註釋sys.stderr.write一行,我看到:lost sys.stderr

一個更安全的方法是使用上下文到stdout/ERR重定向到/dev/null或您的操作過程中IOStream - 或者更好的是,找到驗證功能正在內部使用和調用,而不是直接尋找一個系統的出口上更高級的功能(是op_parse == opt_parse?)

+0

感謝您的意見,我同意恢復需要發生在finally塊中,在這個測試程序中我每次都故意給它一個錯誤,所以我沒有打擾。在看到此消息之前,我發現了「/ dev/null」技巧,所以我可以確認您的解決方案是否有效。 (也op_parse不是opt_parse它只是一個不好的變量名稱來代表'選項解析') – sliceOfPi

2

您可以通過創建一個上下文管理典雅的做多這一點:

import os 
from contextlib import contextmanager 

@contextmanager 
def nullout(): 
    save_stdout = sys.stdout 
    save_stderr = sys.stderr 
    sys.stdout = open(os.devnull, 'w') 
    sys.stderr = open(os.devnull, 'w') 
    yield 
    sys.stdout = save_stdout 
    sys.stderr = save_stderr 

with nullout(): 
    op_args = op_parse.parse_args(selection.split(' ')) 

關於上下文管理一個很好的事情是,yield後的代碼將得到執行不管是否異常發生與否。

的原因,你不能只設置sys.stdoutsys.stderrNone可能是因爲None沒有write()close()方法,一般不會表現得像一個輸出流。