2017-08-04 5 views
1

他のstackoverflowポストを調べた後、このリダイレクト問題を解決できないようです。私がしたいのは、stdoutとstderrの両方を抑制して、エラーが捕捉された後にそれらを復元することです。抑圧はうまくいきますが、それらを半分に戻すだけです。 stderrとstdoutを抑制して復元しようとすると、抑制は機能しますが復元はしません。もし私がstdoutを抑制/復元しようとするのであれば、それはうまくいきます(しかし、私は望んでいないすべてのstderrのテキストを取得します)。なぜstderrがstdoutを復元するのを妨げる原因になるのか、私は理由を入力することを望んでいる(または私が奇妙な/愚かな何かをしている)場合は、理由を考えることができません

私は仕事をしたいだけ/ ERRアウト抑制し、(「復元stdoutが」印刷されません)復元されません。奇妙な結果を生成するリダイレクトされた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") 


HERESに標準出力を抑制し、(厄介な標準エラー出力を印刷する費用で)それを復元したコード

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") 

EDIT:私は考えましたrkの周り、しかし私はまだ上記の問題が発生する理由に興味がある。私の回避策は、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

私は、このテストプログラムでは、毎回エラーが発生したので、毎回エラーが発生していたので、最終的にブロックする必要があることに同意します。これを見る前に "/ dev/null"トリックを発見したので、あなたの解決策が機能することを確認できます。 (また、op_parseはopt_parseではなく、 'options 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後のコードが実行されますということですに関係なく例外が発生するかどうか。 Nonewrite()またはclose()メソッドを持っていないと、一般的に、出力ストリームのように動作していないので、あなただけのNonesys.stdoutsys.stderrを設定することはできません

理由は、おそらくです。