在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
4 个回答
1
最简单的方法就是使用“老派”的流式文件名,这样你的代码就不需要修改了。在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)
这段代码是在Python 2.7.3和3.3.5版本中测试的。
3
在Python 3中,有一个可选的参数叫做closefd
。如果把它设置为False
,那么生成的输入输出对象在关闭的时候不会关闭底层的文件描述符(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)
4
其实,你不需要在使用 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()
14
你可以创建一个上下文管理器,然后像这样使用它
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
,也就是输出到屏幕上。