簡體   English   中英

Boost Python:停止解釋器

[英]Boost Python: stop interpreter

C ++中通過Boost Python調用Python方法后,是否有任何方法可以停止正在運行的Python解釋器?

我要中斷通話有兩個原因:

  1. 如果超時時間已過期(即腳本運行“太長”)。
  2. 如果另一個(並行運行)Python腳本失敗。

我在網上和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 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下運行(以防萬一這可以啟用某些依賴於平台的解決方案,我會很酷的)。

我還沒有找到真正的“從外部停止翻譯”的方法。 但是我創建了一個變通辦法,至少可以根據我的情況完成這項工作。 也許會幫助別人...

我的想法是,我在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_);
}

編輯

不同(相似)方法

在腳本的入口函數中,我以守護程序啟動了一個線程,該線程調用了輔助函數。 helper函數調用一個worker方法(可以執行我實際上想要做的事情)。 的輔助方法返回之后 ,輔助信號的狀態變量。 主線程只是等待這種情況。 如果我想從外面中止,我也要通知情況。 當主線程結束時,輔助線程已經結束,或者在外部中斷的情況下將被清除。

注意

萬一中止,輔助線程將無法正確清理。 因此,您必須應對或手動進行處理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM