Python:使用< cstdio>时,与c ++命令行程序的通信不起作用 [英] Python : communication with c++ command line program not working when using <cstdio>

查看:71
本文介绍了Python:使用< cstdio>时,与c ++命令行程序的通信不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下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 ='1 \ n2 \ n3 \ n')时,不会发生此问题 >

什么可能导致此问题?

(此外,comm.py应该能够处理任何有效的C ++程序,因此仅使用iostream是不可接受的解决方案.)

我还需要在Windows上运行的解决方案.

解决方案

这是由于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,您将需要 研究如何做同样的事情.暂时我不知道.

I have the following python code, which is supposed to provide the intial input to a C++ program, then take its output and feed it back into it, until the program finishes execution:

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

I am currently testing it with two simple C++ programs:

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;
}

When comm.py opens test__1.exe everything works fine, but when it opens test__2.exe it hangs on the first call to readline(). Note that this problem does not occur when I feed test__2.exe the whole input before execution (i.e. initially set x = '1\n2\n3\n')

What could be causing this issue?

(Also, comm.py should be able to handle any valid C++ program, so only using iostream would not be an acceptable solution.)

EDIT: I also need the solution to work on Windows.

解决方案

It is caused by the fact that std::endl flushes the ostream and printf does not flush stdout, as you can see by amending test__2.cpp as follows:

#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;
}

You say that you want to module to work correctly with any C++ program, so you can't rely upon it flushing the standard output (or standard error) after every write.

That means you must cause the program's standard streams to be unbuffered and do so externally to the program itself. You will need to do that in comm.py.

In Linux (or other host providing GNU Core Utils), you could so by executing the program via stdbuf, e.g.

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

which unbuffers all the standard streams. For Windows, you will need to research how do the same thing. For the time being I don't know.

这篇关于Python:使用&lt; cstdio&gt;时,与c ++命令行程序的通信不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆