使用上下文管理器将python脚本输出到文件?

时间:2011-12-13 20:04:20

标签: python file-io contextmanager

我正在编写一个脚本,我有一个选项,要在命令行上传递,脚本是应该将结果打印到stdout还是打印到预定义的结果文件。代码大纲如下所示。我现在已经阅读了一些Python中的上下文管理器,但我不确定是否以及如何在这种特定情况下使用上下文管理器。所以我在寻找建议

  1. 在此问题中使用上下文管理器是否有意义
  2. 如何实施它。
  3. 因此,没有上下文管理器的代码是:

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

1 个答案:

答案 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()

这几乎肯定是矫枉过正的。