[英]Boost Python: stop interpreter
在 C ++中通過Boost Python調用Python方法后,是否有任何方法可以停止正在運行的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.