我有一个 Python3 脚本,我想有选择地重定向stdout
到stderr
一个文件。像这样的东西:
# variable declarations
if log_output:
output_file = open('output.txt', 'w')
sys.stdout = output_file
if log_errors:
errors_file = open('errors.txt', 'w')
sys.stderr = errors_file
# code that uses variables declared above but may exit suddenly
#at the end
if log_output:
output_file.close()
if log_errors:
errors_file.close()
这行得通,除非我中间的代码决定退出。那么我的文件不能保证被关闭。无论代码中发生什么并且仅在某些时候发生,我如何才能干净地关闭这些文件?(通常,我会通过 shell 重定向,但我在 Python 中计算文件名,我不想在各种 shell 中重新计算它们。另外,我不想为是否重定向的逻辑在 shell 脚本中。如果可能的话,我希望这些分支出现在我的主代码中。)
尝试 1
似乎上下文管理器将是这里的方法,但是,当我尝试使用它们时,我必须多次重写我的代码,它不是漂亮的代码:
if log_output:
with open('output.txt', 'w') as output_file:
with contextlib.redirect_stdout(output_file):
if log_errors:
with open('errors.txt','w') as errors_file:
with contextlib.redirect_stderr(errors_file):
# log_output and log_errors
# code that uses variables declared above but may exit suddenly
else:
# log_output and not log_errors
# code that uses variables declared above but may exit suddenly
else:
if log_errors:
with open('errors.txt', 'w') as errors_file:
with contextlib.redirect_stderr(errors_file):
# not log_output and log_errors
# code that uses variables declared above but may exit suddenly
else:
# not log_output and not log_errors
# code that uses variables declared above but may exit suddenly
尝试 2
我决定为它制作一个上下文管理器。我认为它有效,Python 并没有对我大喊大叫,但我仍然不禁觉得它不是太 Pythonic,而且我不完全确定它是否安全。我正在向if
奇怪的方向推进这些陈述。有没有更好的办法?
@contextlib.contextmanager
def opt_stream(stream, name = None):
if name:
file = open(name,'w')
yield file
file.close()
else:
yield stream
output_name, errors_name = None, None
if log_output:
output_name = 'outputs.txt'
if log_errors:
errors_name = 'errors.txt'
with opt_stream(sys.stdout, output_name) as output_file:
with opt_stream(sys.stderr, errors_name) as errors_file:
with contextlib.redirect_stdout(output_file):
with contextlib.redirect_stderr(errors_file):
# code that uses variables declared above but may exit suddenly