在查看其他stackoverflow帖子后,我似乎无法解决此重定向问题。我想要做的是抑制stdout
和stderr
,然后在捕获错误后恢复它们。镇压工作正常,但恢复他们只有一半工作。
如果我尝试抑制并恢复stderr
和stdout
,则抑制有效但无法恢复。如果我只是尝试压制/恢复stdout
它可以正常工作(但我会收到我不想要的所有stderr
文字)。
我无法推断为什么导致stderr
阻止stdout
被恢复会有任何差异,希望能够输入原因(或者如果我是做一些奇怪/愚蠢的事情
这里是我想要工作的代码,但只是抑制了/错误并且没有恢复('Restored 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
为代价):
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 :(得分:3)
通过创建上下文管理器,您可以更优雅地完成此任务:
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')
try:
yield
finally:
sys.stdout = save_stdout
sys.stderr = save_stderr
with nullout():
op_args = op_parse.parse_args(selection.split(' '))
关于上下文管理器的一个好处是,yield
之后的代码将被执行,无论是否发生异常。
您不能将sys.stdout
和sys.stderr
设置为None
的原因可能是因为None
没有write()
或{{1方法,通常不像输出流。
答案 1 :(得分: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
?)