boostpython:停止解释器 有没有办法阻止Python解释器在Python方法中从Boost Python中调用< > C++ >?

boostpython:停止解释器 有没有办法阻止Python解释器在Python方法中从Boost Python中调用< > C++ >?,python,c++,linux,boost,boost-python,Python,C++,Linux,Boost,Boost Python,我想中断通话有两个原因: 如果超时时间已过(即脚本运行“过长”) 如果另一个(并行运行)Python脚本失败 我在web和Boost文档中的搜索没有找到任何结果,但另一方面,我有时很难在Boost文档中找到正确的段落 我从中得到的唯一“想法”。这个想法是向脚本发送一个信号,但是当解释器在我的C++进程中运行时,这可能不是一个可行的选项?!p> 我正在做以下工作: const boost::filesystem::path pythonScriptPath=/*我要从中执行函数的脚本的路径*/ c

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

  • 如果超时时间已过(即脚本运行“过长”)
  • 如果另一个(并行运行)Python脚本失败
  • 我在web和Boost文档中的搜索没有找到任何结果,但另一方面,我有时很难在Boost文档中找到正确的段落

    我从中得到的唯一“想法”。这个想法是向脚本发送一个信号,但是当解释器在我的C++进程中运行时,这可能不是一个可行的选项?!p> 我正在做以下工作:

    const boost::filesystem::path pythonScriptPath=/*我要从中执行函数的脚本的路径*/
    const std::string pythonFunctionName=/*要调用的Python函数的名称。*/;
    boost::python::object mainModule=boost::python::import(“_umain__;”);
    boost::python::object mainnespace=mainModule.attr(“_dict__”);
    boost::python::dict局部变量;
    局部变量[“moduleName”]=pythonScriptPath.stem().string();
    局部变量[“modulePath”]=pythonScriptPath.string();
    std::stringstream importModuleStream;
    导入模块流
    我还没有找到一种真正的“从外部阻止口译员”的方法。但我创造了一个变通办法,至少能在我的情况下完成工作。也许它会帮助其他人

    我的想法是在Python脚本中有一个线程,它不做任何其他事情,只是等待唤醒。它会被C++中的“中止”函数调用唤醒。一旦它醒来,它就会从内部杀死脚本。在本例中,我选择了一种粗略的方法来停止脚本:

    os.\u退出(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()
    
    // 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 */);
    
    C++中,我这样终止脚本:

    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()
    
    // 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_);
    }
    
    #包括
    期末考试
    {
    公众:
    获得gil();
    ~gil();
    私人:
    皮吉州;
    };
    AcquireGIL::AcquireGIL()
    :gilState(PyGILState_sure()){
    //无事可做。。。
    }
    AcquireGIL::~AcquireGIL(){
    PyGILState_发布(gilState_);
    }
    
    编辑

    不同(相似)方法

    在脚本的entry函数中,我启动了一个线程作为守护进程来调用helper函数。helper函数调用一个worker方法(该方法完成我真正想要做的事情)。worker方法返回后,helper将发出一个条件变量的信号。主线程只是等待这种情况。如果我想从外部中止,我也会通知条件。当主线程结束时,辅助线程已经结束,或者在外部中止的情况下,将被清除

    注意


    在中止的情况下,辅助线程将无法正确清理。因此,您必须手动处理该问题。

    为什么不将
    os.\u exit(1)
    放入中止功能?
    os.\u exit(1)
    只有在从入口点上下文(即从刚刚等待中止的线程)调用时才有效吗?@peschü:是的,我认为您可以直接从(C++)线程调用
    os.\u exit(1)
    。我想额外的线索源于我尝试过的方法,我试图让解释器更优雅地终止,然后终止整个过程(包括C++框架)。这就是“不同(类似)方法”试图实现的:停止Python代码,而C++应用程序则保持运行。