我有以下python代码,它应该为C ++程序提供初始输入,然后获取其输出并将其反馈给它,直到程序完成执行:
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'1\n'
while True:
p.stdin.write(x)
p.stdin.flush()
p.stdout.flush()
x = p.stdout.readline()
print(x)
if p.poll() != None:
break
我目前正在使用两个简单的C ++程序对其进行测试:
#include <iostream>
using namespace std;
int main()
{
for( int i = 0; i < 3; ++i )
{
int n;
cin >> n;
cout << n+1 << endl;
}
return 0;
}
#include <cstdio>
int main()
{
for( int i = 0; i < 3; ++i )
{
int n;
scanf("%d", &n);
printf("%d\n", n+1);
}
return 0;
}
当 comm.py 打开 test__1.exe 时,一切正常,但是当它打开 test__2.exe 时,它会在第一次调用时挂起的的ReadLine()即可。 请注意,在执行前将 test__2.exe 输入整个输入时(即最初设置 x =&#39; 1 \ n2 \ n3 \ n&#39; )
可能导致此问题的原因是什么?
(另外,comm.py应该能够处理任何有效的C ++程序,所以只使用iostream不是一个可接受的解决方案。)
编辑:我还需要解决方案才能在Windows上运行。
答案 0 :(得分:1)
这是因为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("%d\n", n+1);
fflush(stdout); //<-- add this
}
return 0;
}
你说你想让模块与任何C ++程序一起正常工作,所以 你不能依赖它冲洗标准输出(或标准错误) 每次写完之后。
这意味着您必须使程序的标准流 unbuffered
并且外部执行程序本身。你需要这样做
在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'1\n'
while True:
p.stdin.write(x)
x = p.stdout.readline()
print(x)
if p.poll() != None:
break
取消所有标准流。对于Windows,您将需要 研究如何做同样的事情。目前我不知道。