我正在编写一个脚本,我有一个选项,要在命令行上传递,脚本是应该将结果打印到stdout还是打印到预定义的结果文件。代码大纲如下所示。我现在已经阅读了一些Python中的上下文管理器,但我不确定是否以及如何在这种特定情况下使用上下文管理器。所以我在寻找建议
因此,没有上下文管理器的代码是:
option_file = True # would come from OptionParser in real code
if option_file:
out = open("resultsfile", "w")
else:
out = sys.stdout
# do some computations
out.write("Results of script")
# more computations and calls to out.write
if option_file:
out.close()
答案 0 :(得分:4)
您可以使用with
语句来使用上下文管理器。它明确地旨在:
例如,open
可以用作上下文管理器。在以下代码中
with open(...) as f:
# do stuff
stuff
是什么并不重要,文件将永远关闭。 (好吧,通常。除了电源被关闭或过程被杀之外的愚蠢情况。)
在这种情况下,您应该使用上下文管理器。它看起来并不像你,所以我认为没有理由让一个上下文管理器。
有一种替代方法(不是更好或更糟,只是不同)编写使用上下文管理器的代码的方式。如果您想暂时重定向stdout
- 但确保在完成后还原它 - 那么您就是在上面的情况。这是一个例子:
@contextlib.contextmanager
def redirect_stdout(stream):
import sys
sys.stdout = stream
yield
sys.stdout = sys.__stdout__
然后您可以编写类似
的代码with open(...) as f:
with redirect_stdout(f):
# do stuff
并且stuff
中对stdout的任何写入都将转到f
。
编辑:你是正确的,没有办法有条件地拥有一个上下文管理器:要么你在一个或你不是。你总是可以编写自己的东西,它可能什么都不做:
@contextlib.contextmanager
def maybe_open(path, do_nothing=True):
if do_nothing:
f = None
yield sys.stdout
else:
f = open(path)
yield f
if f:
f.close()
这几乎肯定是矫枉过正的。