简体   繁体   English

将sys.stdout重定向到文件而不在Python 3中进行缓冲

[英]redirect sys.stdout to a file without buffering in Python 3

I have a script that writes to a log file. 我有一个写入日志文件的脚本。 In Python 2, my quick solution to allow tailing/viewing of the log as it progressed was by assigning sys.stdout to a file object with buffering set to 0: 在Python 2中,我允许在日志前进时sys.stdout /查看日志的快速解决方案是将sys.stdout分配给缓冲设置为0的文件对象:

original_stdout = sys.stdout
sys.stdout = open(log_file, 'w', 0)

Once set, any print statements in the script's functions redirect to the log file very nicely. 设置后,脚本功能中的所有打印语句都会很好地重定向到日志文件。

Running the 2to3-converted version under Python 3 gives the following error: ValueError: can't have unbuffered text I/O . 在Python 3下运行2to3转换版本会产生以下错误: ValueError: can't have unbuffered text I/O Changing the 'w' above to 'wb' solves that, so the structure of the block is 将上面的'w'更改为'wb'可以解决此问题,因此该块的结构为

original_stdout = sys.stdout
sys.stdout = open(log_file, 'wb', 0)
print("{}".format(first_message))

but now the first print statement errors with TypeError: 'str' does not support the buffer interface . 但是现在第一个带有TypeError: 'str' does not support the buffer interface打印语句错误TypeError: 'str' does not support the buffer interface I tried explicitly casting the string to bytes 我尝试将字符串显式转换为字节

print(bytes("{}".format(first_message), "UTF-8"))

but that produces the same TypeError as before. 但这会产生与以前相同的TypeError

What is the easiest way to write unbuffered text to a file in Python 3? 在Python 3中将无缓冲文本写入文件的最简单方法是什么?

According to Python 3.4.3 documentation at https://docs.python.org/3/library/io.html#raw-io and 3.5 documenmtation at https://docs.python.org/3.5/library/io.html#raw-io the way to get unbuffered IO is with Raw IO which can be enabled as in: 据当时的Python 3.4.3文档https://docs.python.org/3/library/io.html#raw-io和3.5 documenmtation在https://docs.python.org/3.5/library/io.html #raw-io获取未缓冲IO的方法是使用Raw IO,可以按以下方式启用:

f = open("myfile.jpg", "rb", buffering=0)

That means "wb" should work for writing. 这意味着“ wb”应该可以写作。

Details on Raw IO are at https://docs.python.org/3/library/io.html#io.RawIOBase and https://docs.python.org/3.5/library/io.html#io.RawIOBase which appear to be the same. 原始IO的详细信息位于https://docs.python.org/3/library/io.html#io.RawIOBasehttps://docs.python.org/3.5/library/io.html#io.RawIOBase看起来是一样的。

I did some testing and found buffering of Text IO to be severe and can amount to hundreds of lines and this happens even when writing to sys.stderr and redirecting the error output to a file, on Windows 7 at least. 我进行了一些测试,发现Text IO的缓冲非常严格,可能多达数百行,即使在写入sys.stderr并将错误输出重定向到文件(至少在Windows 7上)时,也会发生这种情况。 The I tried Raw IO and it worked great! 我尝试了Raw IO,效果很好! - each line printed came through immediately and in plain text in tail -f output. -打印的每一行立即以纯文本形式通过-f输出。 This is what worked for me on Windows 7 with Python 3.4.3 and using tail bundled with GitHub tools: 这是在Windows 7上使用Python 3.4.3并使用与GitHub工具捆绑在一起的tail的结果:

import time
import sys
f = open("myfile.txt", "ab", buffering=0)
c = 0
while True:
    f.write(bytes("count is " + str(c) + '\n','utf-8'))
    c += 1
    time.sleep(1)

If by unbuffered you mean having the outputs immediately flushed to disk, you can simply do this: 如果通过无缓冲的方式意味着立即将输出刷新到磁盘,则可以执行以下操作:

original_stdout = sys.stdout
sys.stdout = open(log_file, 'w')
print(log_message, flush=True)

As print is now a first-class function you can also specify which file to print to, such as: 由于print现在是一流的功能,因此您还可以指定要打印到的file ,例如:

fd = open(log_file, 'w')
print(log_message, file=fd, flush=True)

The issue seems to be in the way you open the file - 问题似乎在于您打开文件的方式-

open(log_file, 'w', 0)

From Python 3.x documentation - Python 3.x文档 -

open(file, mode='r', buffering=-1 , encoding=None, errors=None, newline=None, closefd=True, opener=None) 打开(文件,模式='r', 缓冲= -1 ,编码=无,错误=无,换行=无,closefd =真,打开器=无)

The third argument for open() determines the buffering mode for the file, 0 means no buffering. open()的第三个参数确定文件的缓冲模式, 0表示没有缓冲。 I do not think you can make it work by just using 'wb' instead of 'w' . 我认为您不能仅使用'wb'而不是'w'来使其工作。

You should remove that 0 third argument, and let open() use default line buffering for text files. 您应该删除该第三个参数0 ,并让open()对文本文件使用默认的行缓冲。 Example - 范例-

open(log_file, 'w')

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

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