On Sat, 25 Sep 2010, Bill Janssen wrote:
Andi Vajda <va...@apache.org> wrote:
On Sep 25, 2010, at 13:54, Bill Janssen <jans...@parc.com> wrote:
I've got a subclass of PythonMultiFieldQueryParser. I'd like to be
able
to throw a custom Python exception with parameters in that code, and
catch it in the Python code that's using it. To do this, the
exception
has to somehow travel through Java. I thought I could perhaps
subclass
PythonException to do this, but it looks like that's not really an
extension class.
How to do this?
Have you tried just throwing your exception ? It should be picked up
at the JVM crossing point and thrown on in some form back to Python,
no ?
Yep, it shows up again in Python as a JavaError, but the error type and
any arguments associated with it have been stripped out. I'm trying to
use it to communicate a really exceptional condition, and I need that
info.
The error reporting code is a bit tricky but if you're using shared mode -
the mode where the PythonException java class exists since it's part of the
JCC runtime shared library - a Python exception reported in an extension
class _should_ cross the VM boundaries back and forth (to Java and then back
to the original caller in Python) unadultered since - unless there is a bug
somewhere along the way - the Python error state is not cleared until the
stack has unwound to original call in the Python interpreter.
The error you raise from your Python code is detected by the NULL return
value in the C++ extension code (JCC-generated) that calls your method. That
NULL return value is then reported on to Java by throwing a PythonException
Java exception (line 1087 in functions.cpp).
This Java exception is then caught by one the call<something> macros in
JCCENv.cpp (line 447) which calls reportException() - in other words, after
every JNI method call, reportException() is called to check for an exception
raised in the JVM.
reportException(), JCCEnv.cpp line 407, checks to see if there is an
exception thrown in the JVM, checks it against PythonException and if so
throws the _EXC_PYTHON C++ exception which is turned into a NULL return
value by one of the OBJ_CALL()/INT_CALL() macros in macros.h, line 17, which
wrap every C++ call from Python (these macros also release the GIL for the
time of the call).
In other words, unless there is a bug or you're not using shared mode, your
Python exception state should not be getting lost. Then, I could be missing
something here, this code is a bit hairy as it uses three language exception
systems together across shared libraries.
Note also that there was a bug with this code in throwing C++ exception
objects across shared libraries that I fixed in the latest JCC by just
throwing ints instead of C++ exception objects. If you're not using the
latest JCC release, you may be hitting this bug too.
Andi..