我正在尝试使用subprocess命令将其stdout输出发送到日志文件。
我希望用户能够使用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
时,我希望看到流输出。
有没有办法实现这个目标?
答案 0 :(得分:2)
这里file_stdout是/var/log/feeder.log
不,不是。您不能将字符串作为stdout
传递。正如the docs所述。它需要一个文件对象或一个文件描述符(一个数字)。
因此,问题几乎可以肯定是打开文件的方式,而您尚未向我们展示。我猜你是用open
函数做的,你把buffering
参数作为默认值。正如文档所说:
如果未给出 buffering 参数,则默认缓冲策略的工作方式如下:
二进制文件以固定大小的块缓冲;使用启发式方法选择缓冲区的大小,尝试确定底层设备的“块大小”并回退到
io.DEFAULT_BUFFER_SIZE
。在许多系统上,缓冲区的长度通常为4096或8192字节。“交互式”文本文件(
isatty()
返回True
的文件)使用行缓冲。其他文本文件使用上述策略用于二进制文件。
(这是open
的Python 3.x版本; 2.x中的情况有所不同,但基本问题是等效的,解决方案也是如此。)
因此,它将以大块写入,例如8192字节。
如果您想要无缓冲输出,可以使用buffering=0
(当然也一定要以二进制模式打开文件)。或者只使用os.open
并传递fd,让subprocess
创建自己的文件对象。
虽然我们正在使用它,你可能不应该使用shell=True
(shell理论上可以引入它自己的缓冲 - 更重要的是,它对你没有任何好处,它会导致所有例如,如果这些字符串中的任何一个字符串中都有空格,则会出现各种问题。此外,您可能希望使用sys.executable
代替'python'
作为程序名称;这确保了用于运行父脚本的相同版本的Python也被用来运行子脚本,而不是任何版本的Python恰好是PATH
。
答案 1 :(得分: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)
Subprocess不会缓冲任何东西。被调用的python进程执行缓冲。您必须使用sys.stdout.flush()
中的/etc/feeder/feeder.py
将数据写入文件。
答案 2 :(得分: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)
这是演示: