print输出重定向介绍

首先我们需要明确一点:

print()在打印时,实际上是调用了sys.stdout.write()

只不过print在把内容打印到控制台后,追加了一个换行符(linefeed)。

所以以下两种写法是一样的:

print("HELLO WORLD")
sys.stdout.write("HELLO WORLD\n")

所以当我们需要将输出重定向到文本中,该如何操作呢?

首先我们看一下普通文本对象和标准输出对象的区别:

1. 标准输出对象

print(type(sys.stdout)) # <class '_io.TextIOWrapper'>
print(dir(sys.stdout))

# 输出见下
'''
['_CHUNK_SIZE', '__class__', '__del__', '__delattr__', '__dict__', '__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_checkClosed', '_checkReadable', '_checkSeekable', '_checkWritable', '_finalizing', 'buffer', 'close', 'closed', 'detach', 'encoding', 'errors', 'fileno', 'flush', 'isatty', 'line_buffering', 'mode', 'name', 'newlines', 'read', 'readable', 'readline', 'readlines', 'reconfigure', 'seek', 'seekable', 'tell', 'truncate', 'writable', 'write', 'write_through', 'writelines']
'''

2.文本对象

with open('redirect.txt', 'w') as fp:
    print(fp)  # <_io.TextIOWrapper name='redirect.txt' mode='w' encoding='cp936'>
    print(dir(fp))

# 输出见下
'''
['_CHUNK_SIZE', '__class__', '__del__', '__delattr__', '__dict__', '__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_checkClosed', '_checkReadable', '_checkSeekable', '_checkWritable', '_finalizing', 'buffer', 'close', 'closed', 'detach', 'encoding', 'errors', 'fileno', 'flush', 'isatty', 'line_buffering', 'mode', 'name', 'newlines', 'read', 'readable', 'readline', 'readlines', 'reconfigure', 'seek', 'seekable', 'tell', 'truncate', 'writable', 'write', 'write_through', 'writelines']
'''

可见两者都属于文件对象(_io.TextIOWrapper)。所以,如果把文件对象的引用赋值给sys.stdout,那么print调用的即为文件对象的write方法,这样就实现了重定向。代码如下:

with open('redirect.txt', 'w') as fp:
    sys.stdout = fp
    print("HELLO WORLD")

如果只是临时向文件中打印内容,之后仍要在控制台上打印的话,我们需要先将原始的控制台引用对象保存下来,之后将该引用恢复到sys.stdout中。如下所示:

with open('redirect.txt', 'w') as fp:
    old_stdout = sys.stdout
    sys.stdout = fp
    try:
        help(list)
    finally:
        sys.stdout = old_stdout
print("HELLO WORLD")

在python3.4中,加入了上下文管理器redirect_stdout实现重定向的方法contextlib.redirect_stdout

with open('redirect.txt', 'w') as fp:
    with contextlib.redirect_stdout(fp):
        help(dir)

同样也是实现临时向文件中打印内容,之后仍要在控制台上打印的功能。实际上redirect_stdout的内在逻辑也是保存控制台的引用,而后恢复而已。所以我们可以实现自己的类似redirect_stdout的上下文管理器。代码示例如下:

def redirect_stdout(file):
    old_stdout = sys.stdout
    sys.stdout = file
    try:
        yield file
    finally:
        sys.stdout = old_stdout

def redirect()
    with open('redirect.txt', 'w') as fp:
        with redirect_stdout(fp): # 忽略返回值
            help(dir)

    print("Hello World")

以上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值