Python:使用<cstdio>时,与c ++命令行程序的通信无法正常工作

时间:2017-01-15 11:47:37

标签: python c++ subprocess iostream stdio

我有以下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'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 ++程序对其进行测试:

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("%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上运行。

1 个答案:

答案 0 :(得分:1)

这是因为std::endl刷新了ostreamprintf没有刷新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,您将需要 研究如何做同样的事情。目前我不知道。