【问题标题】:Using fork() and exec() to execute Python code from C++使用 fork() 和 exec() 从 C++ 执行 Python 代码
【发布时间】:2021-12-27 00:35:56
【问题描述】:

我正在尝试使用 exec() 从 C++ 运行 Python,并使用管道在进程之间进行通信。我发现C++进程在Python进程终止后一直在exec()命令处等待,导致它无法执行该行下面的代码。

请检查我下面的代码(我已将问题最小化,因此删除了实际通信部分)

C++ 文件:

int main()
{
    int pipe_cpp_to_py[2];
    int pipe_py_to_cpp[2];
    if (pipe(pipe_cpp_to_py) || pipe(pipe_py_to_cpp))
    {
        std::cout << "Couldn't open pipes" << std::endl;
        exit(1);
    }
    pid_t pid = fork(); 
    if (pid == 0)
    {
        std::cout<<"child started"<<std::endl;
        char *intrepreter="python3"; 
        char *pythonPath="./Pipetest.py"; 
        char *pythonArgs[]={intrepreter,pythonPath,NULL};
        std::cout<<"child before exec"<<std::endl;
        execvp(intrepreter,pythonArgs);
        std::cout<<"child after exec"<<std::endl;
        close(pipe_py_to_cpp[0]);
        close(pipe_cpp_to_py[1]);
        close(pipe_py_to_cpp[1]);
        close(pipe_cpp_to_py[0]);
        std::cout<<"child terminated"<<std::endl;
    }
    else if (pid < 0)
    {
        std::cout << "Fork failed." << std::endl;
        exit(1);
    }
    else
    {
        std::cout<<"parent started"<<std::endl;
        std::cout<<"parent terminated"<<std::endl;
        exit(0);
    }
    std::cout<<"cpp terminated"<<std::endl;
    return 0;
}

Python 文件:

import os  
import time
import struct
    
if __name__ == "__main__":
    print("in python")
    exit()

输出:

ece:~/cpp> ./Pipetest
parent started
parent terminated
child started
child before exec
ece:~/cpp> in python
(blinking cursor here)

对于 C++ 文件,如果我删除 fork 命令并简单地在 main 函数中调用 exec() 来执行 Python 程序,它将按预期运行并成功终止。谁能告诉我这是怎么回事?

更新:感谢所有答案!现在我看到 exec() 之后的代码不会被执行。但是,输出仍然让我感到困惑,因为没有显示新的命令提示符(在我的情况下,它是 ece:~/cpp>)。事实上,它只有在我输入某些内容后才会出现。即使我用 system() 替换 exec() 也会发生这种情况。为什么会这样?

【问题讨论】:

  • 来自文档,execvp 用新的过程映像替换当前过程映像。 exec 之后的任何内容都不应运行。如果确实如此,则表明 execvp 失败。打印它的返回码会很有趣。
  • The documentation 说:“exec() 函数仅在发生错误时返回。返回值为 -1,设置 errno 以指示错误。 "所以,你在这里使用了错误的功能。在 StackOverflow 上发布之前,请阅读您正在使用的函数的文档。
  • 你签过popen()
  • 注意:execvp() 之后,您的代码不再存在。您刚刚用新代码替换了您的代码。所以execvp() 之后的任何语句都不会被执行。这永远不会做任何事情:std::cout&lt;&lt;"child after exec"&lt;&lt;std::endl;
  • 您的进程不会在execvp等待 - 它不再存在。这似乎完全符合其应有的行为; exec 函数的重点是用新进程替换当前进程。我怀疑您希望它的行为类似于 system,但它不是这样工作的。

标签: python c++ pipe exec ipc


【解决方案1】:

您不是 waiting 子进程,因此父进程 退出 在(或,如您的示例输出中,之前)Python 的(相对较长的)启动时间和在孩子打印任何东西之前,shell 会打印下一个提示。您可以看到,如果您在“(此处闪烁光标)”行键入任何内容,它会执行作为下一个 shell 命令。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-01
    • 1970-01-01
    • 2023-03-14
    • 2013-05-06
    • 2015-12-01
    • 1970-01-01
    相关资源
    最近更新 更多