Differences between revisions 2 and 3
Revision 2 as of 2008-03-10 18:44:22
Size: 2740
Editor: 69-30-77-125
Comment:
Revision 3 as of 2008-03-11 10:50:20
Size: 2737
Editor: localhost
Comment: converted to 1.6 markup
Deletions are marked like this. Additions are marked like this.
Line 14: Line 14:
So you can see from this example how easy it is for the C++ and Python layers of this sandwich to be built up to [http://en.wikipedia.org/wiki/Dagwood_sandwich Dagwood proportions]... So you can see from this example how easy it is for the C++ and Python layers of this sandwich to be built up to [[http://en.wikipedia.org/wiki/Dagwood_sandwich|Dagwood proportions]]...
Line 16: Line 16:
[[HTML(<center>)]] [[ImageLink(http://upload.wikimedia.org/wikipedia/commons/3/3a/Dagwood.JPG,http://en.wikipedia.org/wiki/Dagwood_sandwich, width=250)]] [[HTML(</center>)]] <<HTML(<center>)>> [[http://en.wikipedia.org/wiki/Dagwood_sandwich|{{http://upload.wikimedia.org/wikipedia/commons/3/3a/Dagwood.JPG||width=250}}]] <<HTML(</center>)>>
Line 18: Line 18:
Now for the explanation: In the past when an exception happens in a Python layer of the sandwich there was not any safe way to propagate that exception across the C++ layer to the next Python layer up the stack, so instead when control returns from Python to a C++ layer it checks if there was an exception and simply calls [http://docs.python.org/api/exceptionHandling.html PyErr_Print()] if there was. This prints the traceback to sys.stderr, clears the error, and then continues on normally, essentially stopping the propagation of the exception at that layer of the sandwich. Now for the explanation: In the past when an exception happens in a Python layer of the sandwich there was not any safe way to propagate that exception across the C++ layer to the next Python layer up the stack, so instead when control returns from Python to a C++ layer it checks if there was an exception and simply calls [[http://docs.python.org/api/exceptionHandling.html|PyErr_Print()]] if there was. This prints the traceback to sys.stderr, clears the error, and then continues on normally, essentially stopping the propagation of the exception at that layer of the sandwich.

The C++ and Python Sandwich

One of the often asked questions for wxPython has to do with why you can't use a global exception handler wrapped around the call to the app object's MainLoop method. To understand the answer to this question you need to keep in mind that wxWidgets and the wxPython wrappers are C++ code and whenever an event handler or other callback is called you end up with another layer of C++ and Python code on the stack. I usually refer to this as the C++/Python sandwich. For example:

  1. You call MainLoop: this is a Python to C++ transition.

  2. The user clicks a button and your EVT_BUTTON handler is called, which transitions back to Python
  3. The handler calls self.SetSize, now we are back in C++

  4. You have a EVT_SIZE handler that is called, which puts us back in Python
  5. The handler calls Layout(), back in C++
  6. The Layout causes some other panel to get resized, and it has it's own EVT_SIZE handler, now we're back in Python again.
  7. That EVT_SIZE handler calls Update to force an immediate repaint of the panel, putting us back in C++
  8. The handler for the EVT_PAINT is called, which puts control on the Python side once more.

So you can see from this example how easy it is for the C++ and Python layers of this sandwich to be built up to Dagwood proportions...

http://en.wikipedia.org/wiki/Dagwood_sandwich

Now for the explanation: In the past when an exception happens in a Python layer of the sandwich there was not any safe way to propagate that exception across the C++ layer to the next Python layer up the stack, so instead when control returns from Python to a C++ layer it checks if there was an exception and simply calls PyErr_Print() if there was. This prints the traceback to sys.stderr, clears the error, and then continues on normally, essentially stopping the propagation of the exception at that layer of the sandwich.

Another way to think about this is to imagine that every call to an event handler or other callback is wrapped in a try/except that simply prints the traceback. So if you want to catch exceptions yourself before the default behavior happens then you need to do it within the same Python layer where the exception happens, before the event handler or callback returns to the C++ layer. It is possible that this can be changed now since wxWidgets has taken more care to be "exception safe" and I think I know how to do it, it's just a matter of finding some time.

C++ & Python Sandwich (last edited 2015-01-15 08:34:48 by RobinDunn)

NOTE: To edit pages in this wiki you must be a member of the TrustedEditorsGroup.