我有以下python代码,它应该为C++程序提供初始输入,然后将其输出并反馈回其中,直到程序完成执行:
comm.py
p = subprocess.Popen('test__1.exe', bufsize=1, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=False)
p.stdin.flush()
p.stdout.flush()
x = b'1n'
while True:
p.stdin.write(x)
p.stdin.flush()
p.stdout.flush()
x = p.stdout.readline()
print(x)
if p.poll() != None:
break
我目前正在使用两个简单的C++程序对其进行测试:
test__1.cpp:
#include <iostream>
using namespace std;
int main()
{
for( int i = 0; i < 3; ++i )
{
int n;
cin >> n;
cout << n+1 << endl;
}
return 0;
}
test__2.cpp
#include <cstdio>
int main()
{
for( int i = 0; i < 3; ++i )
{
int n;
scanf("%d", &n);
printf("%dn", n+1);
}
return 0;
}
当 comm.py 打开时test__1.exe一切正常,但是当它打开时test__2.exe它在第一次调用readline()时挂起。请注意,当我在执行之前馈送test__2.exe整个输入时,不会发生此问题(即最初设置 x = '123')
可能导致此问题的原因是什么?
(此外,comm.py 应该能够处理任何有效的C++程序,因此仅使用 iostream 将不是一个可接受的解决方案。
编辑:我还需要在Windows上运行的解决方案。
这是由于std::endl
冲洗ostream
而printf
不冲洗stdout
,您可以通过修改test__2.cpp
看到如下:
#include <cstdio>
int main()
{
for( int i = 0; i < 3; ++i )
{
int n;
scanf("%d", &n);
printf("%dn", n+1);
fflush(stdout); //<-- add this
}
return 0;
}
您说您希望模块与任何C++程序正常工作,因此您不能依赖它刷新标准输出(或标准错误)每次写入后。
这意味着您必须使程序的标准流未缓冲并在程序本身外部执行此操作。您将需要这样做在comm.py
.
在Linux(或其他提供GNU Core Utils的主机)中,你可以通过以下方式通过stdbuf
执行程序,例如
import subprocess
cmd = ['/usr/bin/stdbuf', '-i0','-o0', '-e0', './test__2']
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=False)
p.stdin.flush()
p.stdout.flush()
x = b'1n'
while True:
p.stdin.write(x)
x = p.stdout.readline()
print(x)
if p.poll() != None:
break
这将取消缓冲所有标准流。对于Windows,您将需要研究如何做同样的事情。暂时我不知道。