Python 子进程从 stdout 块读取(实时读取输出)
Python Subprocess reading from stdout blocks (reading output in real time)
我正在尝试使用子进程与应用程序进行交互。
我已经使用 Popen 创建了进程,但我无法在不阻塞整个线程的情况下访问输出流。
然而,写入输入流似乎工作正常(使用 communicate 对其进行了测试,但是我以后可能无法使用它,因为我需要实时数据)。
我已经尝试将缓冲区设置为 1,但它似乎不起作用。
我注意到有时如果进程终止,输出会被刷新。
我确实相信这个问题可能是由于没有发生刷新(并且在关闭时同时接收所有数据)这一事实引起的,但我不确定。
C代码:
#include <stdio.h>
int main()
{
int testInteger;
printf("Enter an integer: \n");
scanf("%d", &testInteger);
printf("Number = %d",testInteger);
return 0;
}
Python代码
import subprocess
p = subprocess.Popen("./a.out", stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True, bufsize=1, close_fds=True)
print(p.stdout.read(1)) #This should read E but instead blocks the whole thread!
管道 read()
在返回整个输出之前等待子进程终止,因此它会阻塞。
您可以按照 read subprocess stdout line by line 中的说明尝试使用 readline()
。
编辑:
您的 c 程序可能需要 fflush(stdout)
在 printf
之后。如果 printf
检测到管道,那么即使输出 \n
.
它也可以选择不刷新
在 Does printf always flush the buffer on encountering a newline? 查看更多信息。
I have already tried putting the buffer to 1 but it doesnt seem to work.
bufsize
参数指定了管道的缓冲,但是你调用的二进制文件有它自己的流缓冲,如果二进制文件没有输出到终端,它通常是全缓冲(如果stdout 是一个术语)。
如果将通信通道更改为 stderr(使用 fprintf),您可以观察到这一点。或者,如果您在 printf
之后明确 fflush(stdout)
。或者,如果您使用 setbuf(3)
/setvbuf(3)
显式更改缓冲配置(警告:这是 UB,除非它在程序启动时立即完成)。
如果您不想修改 C 程序,您也可以使用 stdbuf
(非常 GNU 特定)来自定义包装二进制文件的缓冲,只需将 "./a.out"
替换为 ['stdbuf', '-o0', 'a.out']
到 运行 a.out
无缓冲标准输出。
顺便说一句,这种混乱就是您可能不想手动编写交互式程序脚本的原因,这就是 pexpect
存在的原因。
哦,默认情况下,stdin
通常具有与 stdout
相同的缓冲(因此在连接到终端时进行行缓冲,否则完全缓冲)。
我正在尝试使用子进程与应用程序进行交互。 我已经使用 Popen 创建了进程,但我无法在不阻塞整个线程的情况下访问输出流。 然而,写入输入流似乎工作正常(使用 communicate 对其进行了测试,但是我以后可能无法使用它,因为我需要实时数据)。
我已经尝试将缓冲区设置为 1,但它似乎不起作用。
我注意到有时如果进程终止,输出会被刷新。 我确实相信这个问题可能是由于没有发生刷新(并且在关闭时同时接收所有数据)这一事实引起的,但我不确定。
C代码:
#include <stdio.h>
int main()
{
int testInteger;
printf("Enter an integer: \n");
scanf("%d", &testInteger);
printf("Number = %d",testInteger);
return 0;
}
Python代码
import subprocess
p = subprocess.Popen("./a.out", stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True, bufsize=1, close_fds=True)
print(p.stdout.read(1)) #This should read E but instead blocks the whole thread!
管道 read()
在返回整个输出之前等待子进程终止,因此它会阻塞。
您可以按照 read subprocess stdout line by line 中的说明尝试使用 readline()
。
编辑:
您的 c 程序可能需要 fflush(stdout)
在 printf
之后。如果 printf
检测到管道,那么即使输出 \n
.
在 Does printf always flush the buffer on encountering a newline? 查看更多信息。
I have already tried putting the buffer to 1 but it doesnt seem to work.
bufsize
参数指定了管道的缓冲,但是你调用的二进制文件有它自己的流缓冲,如果二进制文件没有输出到终端,它通常是全缓冲(如果stdout 是一个术语)。
如果将通信通道更改为 stderr(使用 fprintf),您可以观察到这一点。或者,如果您在 printf
之后明确 fflush(stdout)
。或者,如果您使用 setbuf(3)
/setvbuf(3)
显式更改缓冲配置(警告:这是 UB,除非它在程序启动时立即完成)。
如果您不想修改 C 程序,您也可以使用 stdbuf
(非常 GNU 特定)来自定义包装二进制文件的缓冲,只需将 "./a.out"
替换为 ['stdbuf', '-o0', 'a.out']
到 运行 a.out
无缓冲标准输出。
顺便说一句,这种混乱就是您可能不想手动编写交互式程序脚本的原因,这就是 pexpect
存在的原因。
哦,默认情况下,stdin
通常具有与 stdout
相同的缓冲(因此在连接到终端时进行行缓冲,否则完全缓冲)。