Boost Python:停止解释器

Boost Python: stop interpreter

本文关键字:解释器 Python Boost      更新时间:2023-10-16

在C++通过Boost Python调用Python方法后,有没有办法停止正在运行的Python解释器?

我想打断通话有两个原因:

  1. 如果超时期限已过期(即脚本运行"太长")。
  2. 如果另一个(并行运行的)Python 脚本失败。

我在 Web 和 Boost 文档中的搜索没有找到任何东西,但另一方面,我有时很难在 Boost 文档中找到正确的段落......

我从这个StackOverflow问题中得到的唯一"想法"。这个想法是向脚本发送信号,但是由于解释器在我的C++进程中运行,这可能不是一个可行的选择?!

我正在执行以下操作:

const boost::filesystem::path pythonScriptPath = /* Path to the script I want to execute a function from. */
const std::string pythonFunctionName = /* Name of the Python function to call. */;
boost::python::object mainModule = boost::python::import("__main__");
boost::python::object mainNameSpace = mainModule.attr("__dict__");
boost::python::dict locals;
locals["moduleName"] = pythonScriptPath.stem().string();
locals["modulePath"] = pythonScriptPath.string();
std::stringstream importModuleStream;
importModuleStream
    << "import impn"
    << "newModule = imp.load_module(moduleName, open(modulePath), modulePath, ('py', 'U', imp.PY_SOURCE))n";
boost::python::exec(importModuleStream.str().c_str(), mainNameSpace, locals);
auto pythonScript = locals["newModule"];
auto pythonFunction = pythonScript_.attr(pythonFunctionName .c_str());
pythonFunction(/* args */);

现在的问题是:

我可以在触发pythonFunction()后中断/中止它的执行吗?如果不可能以我调用它的方式,是否有另一种方法可以使用 Boost Python 调用 Python 函数,以便我可以中止调用?

我在 Linux 下运行(以防万一这启用了一些依赖于平台的解决方案,我会非常酷)。

还没有找到真正的"从外部停止解释器"的方法。我创建了一个解决方法,至少可以在我的情况下完成工作。也许它会帮助其他人...

这个想法是我在 Python 脚本中有一个线程,它什么都不做,只是等待被唤醒。它通过从C++内部调用"中止"函数来唤醒。一旦它被唤醒,它就会从内部杀死脚本。在此示例中,我选择了一种粗略的方法来停止脚本:

os._exit(1)

肯定有更好的方法可以做到这一点,但这超出了这里的重点。整个中止和终止的东西也可以包装得更好,但再一次:我只想勾勒出这个想法。

我的测试Python脚本如下所示:

import threading
import time
import os
def abort():
    global run
    run = False
    global condition
    with condition:    
        condition.notify()
def threadBlock():
    while True:
        print( "Blocking!" )
        time.sleep(3)
def threadTerminate():    
    while run:
        global condition
        with condition:
            condition.wait()
    global kill
    if kill:
        os._exit(1)
def myEntryFunction()
    blockingThread = threading.Thread( target = threadBlock )
    terminatingThread = threading.Thread( target = threadTerminate )
    blockingThread.start()
    terminatingThread.start()
    threadBlock().join()
    global kill
    kill = False
    global condition
    with condition:    
        condition.notify()      
    terminatingThread.join()

run = True;
kill = True;
condition = threading.Condition()

C++内部,我像这样杀死脚本:

// other code (see question)
std::thread killer([&pythonScript] () {
    std::chrono::seconds d(15);
    std::this_thread::sleep_for(d);
    AcquireGIL gil;
    pythonScript.executeFunction("abort");          
});
pythonFunction(/* args */);

AcquireGIL看起来像这样:

#include <boost/python.hpp>
class AcquireGIL final
{
public:
    AcquireGIL();
    ~AcquireGIL();

private:
    PyGILState_STATE gilState_;
};
AcquireGIL::AcquireGIL()
: gilState_(PyGILState_Ensure()) {
    // nothing to do...
}
AcquireGIL::~AcquireGIL() {
    PyGILState_Release(gilState_);
}

编辑

不同(相似)的方法

在我的脚本的入口函数中,我启动一个线程作为守护程序调用帮助程序函数。帮助程序函数调用一个工作器方法(它执行我实际想要做的事情)。工作器方法返回,帮助程序会发出条件变量的信号。主线程只是等待这种情况。如果我想从外面流产,我也只是通知条件。当主线程结束时,将清理已经结束的帮助程序线程,或者在从外部中止的情况下。

注意力

如果中止,帮助程序线程将无法正确清理。因此,您必须应对或手动处理它。