将 Python 'with' 语句与 sys.stdout 一起使用



我总是打开并使用 with语句写入文件:

with open('file_path', 'w') as handle:
    print >>handle, my_stuff

但是,在一个实例中,我需要能够更灵活,并写入sys.stdout(或其他类型的流),如果提供了而不是文件路径:

那么,我的问题是:有没有办法将with语句与真实文件和sys.stdout

使用

请注意,我可以使用以下代码,但我认为这违反了使用with的目的:

if file_path != None:
    outputHandle = open(file_path, 'w')
else:
    outputHandle = sys.stdout
with outputHandle as handle:
    print >>handle, my_stuff

您可以创建一个上下文管理器并像以下那样使用

import contextlib, sys
@contextlib.contextmanager
def file_writer(file_name = None):
    # Create writer object based on file_name
    writer = open(file_name, "w") if file_name is not None else sys.stdout
    # yield the writer object for the actual use
    yield writer
    # If it is file, then close the writer object
    if file_name != None: writer.close()
with file_writer("Output.txt") as output:
    print >>output, "Welcome"
with file_writer() as output:
    print >>output, "Welcome"

如果您不将任何输入传递给file_writer,它将使用sys.stdout

的事情是,您不需要使用stdout的上下文处理器,因为您没有打开或关闭它。抽象的一种不那么花哨的方法是:

def do_stuff(file):
    # Your real code goes here. It works both with files or stdout
    return file.readline()
def do_to_stdout():
    return do_stuff(sys.stdout)
def do_to_file(filename):
    with open(filename) as f:
        return do_stuff(f)

print do_to_file(filename) if filename else do_to_stdout()

使用Python3可选的closefd参数已识别。如果设置为False,则结果IO对象不会关闭fd的基础:

if file_path != None:
    outputHandle = open(file_path, 'w')
else:
    outputHandle = open(sys.stdout.fileno(), 'w', closefd=False)
with outputHandle as handle:
    print(my_stuff, file=handle)

最简单的方法就是简单地使用"旧学校"流式文件名,这样您的代码就不必更改。在unix中,这是"/dev/tty"或Windows中,这是" con"(尽管两个平台还有其他选择)。

if default_filename is None:
    default_filename = "/dev/tty"
with open(default_filename, 'w') as handle:
    handle.write("%sn" % my_stuff)

此代码在Python 2.7.3和3.3.5

中测试

最新更新