我正在尝试使用 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
时,我想看到流输出。
有什么办法可以实现这个目标吗?
这里 file_stdout 是 /var/log/feeder.log
不,不是。您不能将字符串作为
stdout
传递。正如文档所明确的那样。它需要一个文件对象或文件描述符(一个数字)。
因此,问题几乎肯定出在您“打开”文件的方式上,而您尚未向我们展示。我猜您是使用 open
函数完成的,并且将
buffering
参数保留为默认值。正如文档所说:
当没有给出 buffering参数时,默认缓冲策略的工作原理如下:
二进制文件以固定大小的块缓冲;缓冲区的大小是通过尝试确定底层设备的“块大小”并依靠
(这是Python 3.x版本的- “交互式”文本文件(
io.DEFAULT_BUFFER_SIZE
来选择的。在许多系统上,缓冲区的长度通常为 4096 或 8192 字节。
isatty()
返回
的文件)使用行缓冲。其他文本文件使用上述二进制文件的策略。True
open
;2.x中情况有所不同,但基本问题是等效的,解决方案也是如此。)
因此,它将以块的形式写入,例如 8192 字节。如果你想要无缓冲的输出,你可以使用
buffering=0
(当然要确保以二进制模式打开文件)。或者只使用
os.open
并传递 fd,然后让 subprocess
创建自己的文件对象。
当我们这样做时,您可能不应该使用shell=True
(理论上,shell 可以引入自己的缓冲,更重要的是,它对您没有任何好处,并且如果,比如说,任何这些字符串中都有空格)。另外,您可能需要使用
sys.executable
而不是 'python'
作为程序名称;确保用于运行父脚本的相同版本的 Python 也用于运行子脚本,而不是恰好是第一个版本的 Python PATH
。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
将数据写入文件。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)
这是演示:
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