【问题标题】:Python : communication with c++ command line program not working when using <cstdio>Python:使用 <cstdio> 时与 C++ 命令行程序的通信不起作用
【发布时间】:2017-01-15 11:47:36
【问题描述】:

我有以下 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') p>

什么可能导致这个问题?

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

编辑:我还需要在 Windows 上工作的解决方案。

【问题讨论】:

    标签: python c++ subprocess iostream stdio


    【解决方案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++ 程序一起正常工作,所以 你不能依赖它刷新标准输出(或标准错误) 每次写入后。

    这意味着您必须使程序的标准流无缓冲 并对程序本身进行外部。你需要这样做 在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,您将需要 研究如何做同样的事情。暂时不知道。

    【讨论】:

    • 这是一个有效的解决方案,但不幸的是它不能解决我的问题,因为我需要 comm.py 才能使用任何有效的 C++ 程序。在刷新 ostream 时,为什么行:p.stdout.flush() 不做同样的事情?
    • @black-goat 是的,我一直在思考这个问题,现在仍然如此。查看更新。
    • 感谢您的意见。遗憾的是,我忘了提到我也需要它在 Windows 上工作,但我会尝试找到与您的建议类似的东西。
    猜你喜欢
    • 1970-01-01
    • 2012-10-05
    • 1970-01-01
    • 1970-01-01
    • 2015-07-11
    • 2013-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多