Boost Python: 停止解释器
Boost Python: stop interpreter
在 在 [=34 内通过 Boost Python 调用 Python 方法后,有什么方法可以停止 运行 Python 解释器=] C++?
我想中断通话有两个原因:
- 如果超时期限已过(即脚本运行 "too long")。
- 如果另一个(并行 运行)Python 脚本失败。
我在网络和 Boost 文档中的搜索没有找到任何结果,但另一方面,我有时很难在 Boost 文档中找到正确的段落...
我唯一的"sort of idea"就是从这个Whosebug 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 */);
现在的问题是:
我可以interrupt/abort pythonFunction() 触发后执行吗?
如果我调用它的方式不可能,是否有另一种方法可以使用 Boost Python 调用 Python 函数,所以我 可以 中止调用?
我 运行 在 Linux 下(以防万一这启用了一些依赖于平台的解决方案,我会非常满意)。
我没有找到真正的"stop interpreter from the outside"方法。 但是 我创建了一个解决方法,至少可以在我的情况下完成工作。也许它会对其他人有所帮助...
我的想法是,我在 Python 脚本中有一个线程,它除了等待被唤醒外什么都不做。它通过从 C++ 中调用 "abort" 函数来唤醒。一旦它被唤醒,它就会从内部杀死脚本。在这个例子中我选择了一种粗略的方法来停止脚本:
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 方法returns 之后,助手向条件变量发出信号。主线程只是等待这个条件。如果我想从外部中止,我也只通知条件。当主线程结束时,辅助线程已经结束,或者在外部中止的情况下,将被清理。
关注
如果中止,辅助线程将无法正确清理。所以你必须处理它或手动处理它。
在 在 [=34 内通过 Boost Python 调用 Python 方法后,有什么方法可以停止 运行 Python 解释器=] C++?
我想中断通话有两个原因:
- 如果超时期限已过(即脚本运行 "too long")。
- 如果另一个(并行 运行)Python 脚本失败。
我在网络和 Boost 文档中的搜索没有找到任何结果,但另一方面,我有时很难在 Boost 文档中找到正确的段落...
我唯一的"sort of idea"就是从这个Whosebug 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 */);
现在的问题是:
我可以interrupt/abort pythonFunction() 触发后执行吗? 如果我调用它的方式不可能,是否有另一种方法可以使用 Boost Python 调用 Python 函数,所以我 可以 中止调用?
我 运行 在 Linux 下(以防万一这启用了一些依赖于平台的解决方案,我会非常满意)。
我没有找到真正的"stop interpreter from the outside"方法。 但是 我创建了一个解决方法,至少可以在我的情况下完成工作。也许它会对其他人有所帮助...
我的想法是,我在 Python 脚本中有一个线程,它除了等待被唤醒外什么都不做。它通过从 C++ 中调用 "abort" 函数来唤醒。一旦它被唤醒,它就会从内部杀死脚本。在这个例子中我选择了一种粗略的方法来停止脚本:
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 方法returns 之后,助手向条件变量发出信号。主线程只是等待这个条件。如果我想从外部中止,我也只通知条件。当主线程结束时,辅助线程已经结束,或者在外部中止的情况下,将被清理。
关注
如果中止,辅助线程将无法正确清理。所以你必须处理它或手动处理它。