我需要在问题面前给出一些背景信息。请多多包涵。使用boost :: python我向Python公开了一些异常类型,比如MyExceptionType
。我有一个boomTest
我向Python公开以检查它是否有效。 Python调用boomTest
并正确处理MyExceptionType
,到目前为止一直很好。这是C ++方面的事情:
static void boomTest() {
throw MyExceptionType("Smoked too many Cohibas!");
}
static PyObject *myExceptionPtr = NULL;
static void translate(MyExceptionType const &exception) {
assert(myExceptionPtr != NULL);
boost::python::object pythonExceptionInstance(exception);
PyErr_SetObject(myExceptionPtr, pythonExceptionInstance.ptr());
}
BOOST_PYTHON_MODULE(test) {
class_<MyExceptionType> myException("MyExceptionType", no_init);
myException.add_property("message", &MyExceptionType::what);
myExceptionPtr = myException.ptr();
register_exception_translator<MyExceptionType>(&translate);
}
这是Python的一面:
import sys
import example
reload(example)
from example import MyExceptionType, boomTest
def tryBoomTest():
try:
boomTest()
except MyExceptionType as ex:
print 'Success! MyExceptionType gracefully handled:' \
'\n message="%s"' % ex.message
except:
print 'Caught unhandled exception: %s "%s"' % (sys.exc_info()[0], sys.exc_info()[1])
现在事情变得有点毛茸茸了,因为在一个真实的用例中,我从C ++ Boost(非Python)线程回调Python,如下所示:
# this is a Python callback invoked from a C++ boost non-Python thread
def handle(future):
try:
# future.get() throws MyExceptionType if there was a cluster exception
"Cluster response received with value: %s" % future.get()
except MyExceptionType as ex:
print 'Success! MyExceptionType gracefully handled:' \
'\n message="%s"' % ex.message
现在OP :
为什么我的C ++回调触发器会在boost::python::error_already_set
调用抛出future.get()
以供Python处理时遇到MyExceptionType
异常?我怀疑这种行为是由于在C ++(非Python)线程中引发异常这一事实引起的......
强制Python处理异常需要什么,如开头的示例案例那样?
我已尝试使用C ++的回调触发器执行以下操作:
void callbackTrigger() {
try {
pythonHandle_(getFuture());
}
// why do I get this???
catch (boost::python::error_already_set&) {
// this doesn't help, Python doesn't still handle MyExceptionType
boost::python::handle_exception();
}
}
答案 0 :(得分:1)
我验证了我的Python理论,不喜欢处理抛出的异常(即使在Python代码中),但作为外来C ++线程的一部分执行。因此,我构建了这个纯Python包装器,以便能够处理主Python线程中的回调。
import example
reload(example)
from example import MyExceptionType
condition = threading.Condition()
futures = []
# Actual handle executed by the main Python THREAD
# __after__ submitting all the jobs to the Cluster
# N is the number of jobs that were submitted to the Cluster
def handle(N):
while (N > 0):
condition.acquire()
try:
# wait for max of a second to prevent this thread waiting indefinitely
# when it misses notify while being busy processing responses
condition.wait(1.0)
for future in futures:
try:
print 'callback received! the response is:\n %s' % future.get()
except MyExceptionType as ex:
print 'MyExceptionType gracefully handled:' \
'\n message="%s"' % ex.message
except:
print 'Caught unhandled exception: %s "%s"' % (sys.exc_info()[0], sys.exc_info()[1])
finally:
N -= len(futures)
del(futures[:])
condition.release()
# callback called from a C++ boost THREAD
def callback(future):
condition.acquire()
try:
# do not consume the future here, rather let the main
# Python thread deal with it ...
futures.append(future)
condition.notify()
finally:
condition.release()
它不理想,但它有效并且输出正确:
registering callback 1 ...
registering callback 2 ...
registering callback 3 ...
registering callback 4 ...
registering callback 5 ...
MyExceptionType gracefully handled:
message="Smoked too many Cohibas!"
MyExceptionType gracefully handled:
message="Smoked too many Cohibas!"
MyExceptionType gracefully handled:
message="Smoked too many Cohibas!"
MyExceptionType gracefully handled:
message="Smoked too many Cohibas!"
MyExceptionType gracefully handled:
message="Smoked too many Cohibas!"
Process finished with exit code 0