3

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

  1. 在这个问题中使用上下文管理器是否有意义
  2. 如何着手实施它。

因此,没有上下文管理器的代码是:

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

1 回答 1

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将转到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()

这几乎可以肯定是矫枉过正。

于 2011-12-13T20:30:43.130 回答