如何在没有任何缓冲的情况下将 python 子进程命令标准输出到文件?

问题描述 投票:0回答:4

我正在尝试使用 subprocess 命令将其标准输出输出发送到日志文件。 我希望用户能够使用

tail -f logfile
同时查看日志。

但是,我观察到子进程模块在写入文件之前会缓冲输出日志很长时间。 有什么办法可以避免这种缓冲行为吗?

file_stdout=open("/var/log/feeder.log","w")
file_stderr=open("/var/log/feeder.err","w")
proc = subprocess.Popen("python /etc/feeder/feeder.py -i " + input_file + " -o " + output_file + " -r " + str(rate) + " -l " +str(lines), stdout=file_stdout, stderr=file_stderr, shell=True)

当我运行

tail -f /var/log/feeder.log
时,我想看到流输出。 有什么办法可以实现这个目标吗?

python logging subprocess buffer tail
4个回答
2
投票

这里 file_stdout 是 /var/log/feeder.log

不,不是。您不能将字符串作为

stdout
传递。正如文档所明确的那样。它需要一个文件对象或文件描述符(一个数字)。

因此,问题几乎肯定出在您“打开”文件的方式上,而您尚未向我们展示。我猜您是使用 open

 函数完成的,并且将 
buffering 参数保留为默认值。正如文档所说:

当没有给出
buffering

参数时,默认缓冲策略的工作原理如下:

    二进制文件以固定大小的块缓冲;缓冲区的大小是通过尝试确定底层设备的“块大小”并依靠
  • io.DEFAULT_BUFFER_SIZE

    来选择的。在许多系统上,缓冲区的长度通常为 4096 或 8192 字节。

    
    

  • “交互式”文本文件(
  • isatty()

    返回

    True
    的文件)使用行缓冲。其他文本文件使用上述二进制文件的策略。
    
    

(这是Python 3.x版本的
open

;2.x中情况有所不同,但基本问题是等效的,解决方案也是如此。)

因此,它将以块的形式写入,例如 8192 字节。

如果你想要无缓冲的输出,你可以使用

buffering=0

(当然要确保以二进制模式打开文件)。或者只使用

os.open
并传递 fd,然后让
subprocess
创建自己的文件对象。

当我们这样做时,您可能不应该使用
shell=True

(理论上,shell 可以引入自己的缓冲,更重要的是,它对您没有任何好处,并且如果,比如说,任何这些字符串中都有空格)。另外,您可能需要使用

sys.executable
而不是
'python'
作为程序名称;确保用于运行父脚本的相同版本的 Python 也用于运行子脚本,而不是恰好是第一个版本的 Python
PATH
    


0
投票
subprocess.Popen

错了。


proc = subprocess.Popen(["python", "/etc/feeder/feeder.py", "-i", input_file, "-o", output_file, "-r", str(rate), "-l", str(lines)], stdout=file_stdout, stderr=file_stderr)

子进程没有缓冲任何东西。被调用的 python 进程进行缓冲。您必须使用 
sys.stdout.flush()

中的

/etc/feeder/feeder.py
将数据写入文件。
    


0
投票

file_stdout = open('output_log','a+') file_stderr = open('error_log','a+') proc = subprocess.Popen("python /etc/feeder/feeder.py -i " + input_file + " -o " + output_file + " -r " + str(rate) + " -l " +str(lines), stdout=file_stdout, stderr=file_stderr)

这是演示:

Here is demo


0
投票

proc = subprocess.Popen("python -u /etc/feeder/feeder.py -i " + input_file + " -o " + output_file + " -r " + str(rate) + " -l " +str(lines), stdout=file_stdout, stderr=file_stderr, shell=True)

注意
-u

    

© www.soinside.com 2019 - 2024. All rights reserved.