简体   繁体   English

如何与 python 中的 EXE 交互?

[英]How to interact with an EXE from python?

I'm doing some work that need to call an EXE with c++ in Python.我正在做一些需要在 Python 中使用 c++ 调用 EXE 的工作。 Take an example, I want to interact with below program to get the output message and enter the necessary input in Python.举个例子,我想和下面的程序交互来获取 output 消息并在 Python 中输入必要的输入。

    #include <iostream>
    #include <cmath>
    using namespace std;
    int main()
    {
        double init_asset;  // the money you have at the beginning
        double ratio;       // the gain ratio you will get after every year
        double years;       // how many years you want to wait
        double future_gain;
        cout << "Please tell me how much money you want to invest now:\n";
        fflush(stdout);
        cin >> init_asset;
        cout << "Please tell me the gain ratio you will have after each year:\n";
        fflush(stdout);
        cin >> ratio;
        cout << "Please tell me how many years you want to wait:\n";
        fflush(stdout);
        cin >> years; 
        future_gain = init_asset*pow((1+ratio),years);
        cout << "Your future gain is: " << future_gain << " after " << years << " years.\n";
        fflush(stdout);
        return 0;
    } 

In Python, I tried below code:在 Python 中,我尝试了以下代码:

p1 = subprocess.Popen(["./calc_return"],stdin=subprocess.PIPE, stdout=subprocess.PIPE)
for line in iter(p1.stdout.readline, b''):
    print(line)
    info = input("Please enter info based on the above request:")
    out, err = p1.communicate(bytes(info,'utf-8'))
    print(out)

But the code doesn't work, the communication function terminates the calc_return program and the但是代码不起作用,通信 function 终止了 calc_return 程序并且
code stuck in the for loops.代码卡在 for 循环中。

Can anyone help me out this question?谁能帮我解决这个问题? Thanks in advance.提前致谢。

You can create a wrapper in Python to get all the parameters and then call the Exe with just one line.您可以在 Python 中创建一个包装器以获取所有参数,然后只需一行即可调用该 Exe。

os.system("program.exe {} {}".format(param1, param2))

Ref: https://stackabuse.com/executing-shell-commands-with-python/参考: https://stackabuse.com/executing-shell-commands-with-python/

Well communicate name confused you... It does not manage a true 2 channel communication but rather:communicate的名字让你感到困惑......它不管理真正的 2 通道通信,而是:

  1. pass an initial input to the command将初始输入传递给命令
  2. wait for the command to terminate with no other interaction等待命令终止,没有其他交互
  3. give back the stout and stderr output to the caller.将粗壮和标准错误 output 还给调用者。

And it is not what you want.这不是你想要的。

You must instead simply read the stdout channel without waiting for the command to terminate and pass the user input to the stdin channel of the command.您必须改为简单地读取标准输出通道,而无需等待命令终止并将用户输入传递到命令的标准输入通道。

You code could become:你的代码可能变成:

p1 = subprocess.Popen(["./calc_return"],stdin=subprocess.PIPE, stdout=subprocess.PIPE)
for line in iter(p1.stdout, b''):   # do not use readline here...
    print(line)
    if p1.poll() is not None:  # exit loop if the command completed
        break
    info = input("Please enter info based on the above request:")
    print(info, file=p1.stdin)

But beware:但请注意:

  • this will only work because the program consistently flushes its output before inputting anything这只会起作用,因为程序会在输入任何内容之前始终刷新其 output
  • this code has a minor race condition: nothing can guarantee that the command will be ended before you reach p1.poll() .这段代码有一个次要的竞争条件:没有什么可以保证命令会在你到达p1.poll()之前结束。 A possible workaround is to just warn your users that if the message is not a question they can provide any input.一种可能的解决方法是警告您的用户,如果消息不是问题,他们可以提供任何输入。

Unfortunately that last point is not easy to cope with.不幸的是,最后一点并不容易应付。 It would require multithreading to have one thread processing the input channel while the other processes the output channel.需要多线程才能让一个线程处理输入通道,而另一个线程处理 output 通道。 It would be overkill here but cannot be avoided in a portable way for more serious use cases.这将是矫枉过正,但不能以便携的方式避免更严重的用例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM