python - 两个并发的 Python 进程可以在 Boost Python 中运行吗?

标签 python c++ boost boost-python

我正在尝试在 boost::python 的 Python 解释器中运行并发 Python 脚本。这是一个简短的示例程序:

#include <Python.h>

#include <boost/python/exec.hpp>
#include <iostream>
#include <thread>

#include <boost/python/extract.hpp>
#include <boost/python/import.hpp>
#include <boost/python/object.hpp>

int main(int argc, char const *argv[]) {

  const char *prog = "def ack(m, n):\n"
                     "  if m == 0:\n"
                     "    return n + 1\n"
                     "  elif n == 0:\n"
                     "    return ack(m - 1, 1)\n"
                     "  else:\n"
                     "    return ack(m - 1, ack(m, n - 1))";

  Py_Initialize();
  try {
    std::thread t1([&prog]() {
      std::cout << "t1" << std::endl;

      boost::python::object mainModule = boost::python::import("__main__");
      boost::python::object mainNamespace = mainModule.attr("__dict__");

      boost::python::exec(prog, mainNamespace, mainNamespace);
      int val = boost::python::extract<int>(
          boost::python::eval("ack(3,3)", mainNamespace, mainNamespace));
      std::cout << "t1 result: " << val << std::endl;
    });

    std::thread t2([&prog]() {
      std::cout << "t2" << std::endl;

      boost::python::object mainModule = boost::python::import("__main__");
      boost::python::object mainNamespace = mainModule.attr("__dict__");

      boost::python::exec(prog, mainNamespace, mainNamespace);
      int val = boost::python::extract<int>(
          boost::python::eval("ack(3,4)", mainNamespace, mainNamespace));
      std::cout << "t2 result: " << val << std::endl;
    });

    t1.join();
    t2.join();
  } catch (boost::python::error_already_set const &e) {
    PyErr_Print();
  }

  return 0;
}

问题是程序间歇性地失败。我已经在两个不同的 Linux 机器上试过了。一方面,它大约有 3/4 的时间失败;另一方面大约有 1/10 的时间。最常见的失败消息是没有帮助的:

RUN FINISHED; Segmentation fault; core dumped; real time: 60ms; user: 0ms; system: 0ms

Boost Python 文档中有几个关于并发的诱人调用,但我尝试过的组合都没有帮助。 global interpreter lock (GIL) 似乎被设计为允许 C++ 访问 相同 Python 解释器线程,除非我误解了它。我想要同时运行两个完全独立的 Python 解释器。

This example很接近,但使用两个独立的 C 线程偶尔调用 Python 来完成一些工作。我正在尝试同时运行两个独立的 Python 进程。

This question是相似的,尽管它提供的细节较少。在我的案例中,Python 解释器用于将需要大量时间在 super 计算机上运行的外部进程捆绑在一起;他们不需要回调我的 C++ 应用程序。一旦完成,C++ 应用程序就会从外部拖放文件中收集并显示结果。

最佳答案

据我所知,John 是正确的。我们从未找到在 Boost Python 中运行两个并发 Python 项目的方法。有三种方法可以避免这个问题。这是第一个:运行两个不同 Python 解释器。

#include <Python.h>

#include <boost/python/exec.hpp>
#include <iostream>
#include <thread>
#include <sys/wait.h>

#include <boost/python/extract.hpp>
#include <boost/python/import.hpp>
#include <boost/python/object.hpp>

void python (std::string fork, int m, int n) {
  const char *prog = "def ack(m, n):\n"
                     "  if m == 0:\n"
                     "    return n + 1\n"
                     "  elif n == 0:\n"
                     "    return ack(m - 1, 1)\n"
                     "  else:\n"
                     "    return ack(m - 1, ack(m, n - 1))";

  Py_Initialize();
  try {
    std::cout << fork << std::endl;

    boost::python::object mainModule = boost::python::import("__main__");
    boost::python::object mainNamespace = mainModule.attr("__dict__");

    std::stringstream commandstream;
    commandstream << "ack(" << m << "," << n << ")";
    std::string command = commandstream.str();
    boost::python::exec(prog, mainNamespace, mainNamespace);
    int val = boost::python::extract<int>(boost::python::eval(command.c_str(), mainNamespace, mainNamespace));
    std::cout << fork << " result: " << val << std::endl;
  } catch (boost::python::error_already_set const &e) {
    PyErr_Print();
  }
}

int main (int argc, char const *argv[]) {
  pid_t pid = fork();
  if (pid == 0) {
    python("f1", 3, 4);
  } else if (pid > 0) {
    python("f2", 3, 3);

    int status;
    waitpid(pid, &status, 0);
  } else {
    std::cout << "Fork failed." << std::endl;
  }

  return 0;
}

第二种方法,也是我们最终使用的方法,是将运行 Python 解释器的代码放在外部可执行文件中并运行它。

第三种是阻塞线程,直到第一个 Python 进程结束。如果预计每个 Python 进程都需要很短的时间,那是可行的,但在我们的应用程序中情况并非如此,因此我们拒绝了这种替代方案。

关于python - 两个并发的 Python 进程可以在 Boost Python 中运行吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45489225/

相关文章:

python - 根据 pandas 中的组用行值填充列的优雅方法

c++ - Qt qglobal.h 的 Boost 版本

c++ - 如何防止在其他智能指针中存储基于 intrusive_ptr 的类

c++ - 如何确保 Windows 和 Linux 上的浮点行为相同?

c++ - 通过轮换 boost 2 个文件的日志记录

python - 创建并填充 PySpark 数据框,其中列作为 period_range

python - 可以做更多的pythonic吗?

python - 从 PySpark 的 RDD 中的数据中查找最小和最大日期

c++ - ADL 名称查找问题,正在使用 std::swap; swap(a,b) 与函数重载或内部作用域函数隐藏外部作用域函数有关?

c++ - 具有 C++11 构造的映射函数