简体   繁体   English

使用 Python 'with' 语句和 sys.stdout

[英]using Python 'with' statement with sys.stdout

I always open and write into files using with statement:我总是使用with语句打开并写入文件:

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

However, there is one instance where I need to be able to be more flexible, and write to sys.stdout (or other types of streams), if that is provided instead of file path:但是,在一个实例中,我需要能够更加灵活,并写入sys.stdout (或其他类型的流),如果提供的是文件路径而不是文件路径:

So, my question is this: Is there a way for using with statement both with real files and with sys.stdout ?所以,我的问题是:有没有办法同时使用with语句和真实文件和sys.stdout

Note that I can use the following code, but I think this defeats the purpose of using with :请注意,我可以使用以下代码,但我认为这违背了使用with的目的:

if file_path != None:
    outputHandle = open(file_path, 'w')
else:
    outputHandle = sys.stdout

with outputHandle as handle:
    print >>handle, my_stuff

You can create a context manager and use it like this您可以创建一个上下文管理器并像这样使用它

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"

If you don't pass any input to file_writer it will use sys.stdout .如果您不将任何输入传递给file_writer ,它将使用sys.stdout

Thing is, you don't need to use a context processor with stdout , because you're not opening or closing it.问题是,您不需要将上下文处理器与stdout一起使用,因为您没有打开或关闭它。 A less fancy way of abstracting this is:一种不那么花哨的抽象方法是:

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

The simplest way is to simply use "old school" streamed filenames, that way your code doesn't have to change.最简单的方法是简单地使用“老派”流文件名,这样您的代码就不必更改。 In Unix this is "/dev/tty" or in Windows this is "con" (although there are other choices for both platforms).在 Unix 中这是“/dev/tty”,在 Windows 中是“con”(尽管两个平台都有其他选择)。

if default_filename is None:
    default_filename = "/dev/tty"

with open(default_filename, 'w') as handle:
    handle.write("%s\n" % my_stuff)

This code tested in Python 2.7.3 and 3.3.5此代码在 Python 2.7.3 和 3.3.5 中测试

With python3 optional closefd argument is recognized.使用 python3 可选closefd参数被识别。 If set to False , resulting IO object won't close underlying fd:如果设置为False ,则导致 IO object 不会关闭底层 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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM