Andi Vajda <va...@apache.org> wrote: > 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.
You mean sys.exc_info() here? Wouldn't that be clobbered by the JavaError thrown by the JVM code? Ah, but the JavaError I'm actually seeing shouldn't be thrown at all. > 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. Wonderfully twisty, but I follow. > 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. That could be it. I believe I'm using 2.9.3. Is the fix in 3.0.2? Bill