Boost Python:停止翻译

时间:2015-01-16 14:23:57

标签: python c++ linux boost boost-python

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

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

  1. 如果超时时间已到期(即脚本运行“太长时间”)。
  2. 如果另一个(并行运行的)Python脚本失败。
  3. 我在网络和Boost文档中的搜索没有发现任何内容,但另一方面,我有时很难在Boost文档中找到正确的段落......

    我从StackOverflow question得到的唯一“想法”。想法是向脚本发送信号,但是当解释器在我的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 imp\n"
        << "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下运行(以防万一这会启用一些平台相关的解决方案,我会非常酷)。

1 个答案:

答案 0 :(得分:3)

没有从外面发现了一个真正的&#34;停止翻译&#34;做法。 但是我创建了一个解决方法,至少可以在我的情况下完成工作。也许它会帮助别人...

我的想法是,我在Python脚本中有一个线程,除了等待被唤醒之外什么都不做。通过拨打&#34; abort&#34;来唤醒它。在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_);
}

修改

不同(类似)方法

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

注意

如果中止,辅助线程将无法正常清理。因此,您必须手动处理或手动处理它。