在 C ++中通过Boost Python调用Python方法后,有没有办法停止正在运行的Python解释器?
我想打断电话有两个原因:
我在网络和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下运行(以防万一这会启用一些平台相关的解决方案,我会非常酷)。
答案 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方法(执行我实际想做的事情)。 在工作方法返回后,帮助程序发出条件变量的信号。主线程只是等待这种情况。如果我想从外面流产,我也只是通知了这个条件。当主线程结束时,辅助线程已经结束或者从外部中止的情况下,将被清除。
注意
如果中止,辅助线程将无法正常清理。因此,您必须手动处理或手动处理它。