catching errors in embedded Python on Windows

Howard Lightstone howard at eegsoftware.com
Fri Aug 24 01:22:27 EDT 2001


Examples? Sure (although I first tried the python redirection method in my
embedded code).  Of course they're in the error conditions...otherwise, why
would I care :)  Even worse, the exact same Python scripts work fine in
python/pythonw but not when run from a PyRunSimpleString.........sigh

Python2.0 (it takes a lot to move embedded stuff from one version so ...)
pythonrun.c (starting about line 674):

void
PyErr_PrintEx(int set_sys_last_vars)
{
.......
 if (PyErr_GivenExceptionMatches(exception, PyExc_SystemExit)) {
  if (Py_FlushLine())
   PyErr_Clear();
  fflush(stdout);        <== this is supposed to be the CRT file pointer

.......
   PyObject_Print(v, stderr, Py_PRINT_RAW);
   fprintf(stderr, "\n");
   Py_Exit(1);
......
 f = PySys_GetObject("stderr");            <== it looks like someone thought
 if (f == NULL)                                               about it but...
  fprintf(stderr, "lost sys.stderr\n");       <=== huh?
 else {
  if (Py_FlushLine())
   PyErr_Clear();
  fflush(stdout);                                    <=== only stderr was
checked??
.......

Anyway, when tracing through the debugger....stdout/stderr do not point to CRT
stream outputs so the CRT cannot be used for this output.  Windows leaves them
pointing to the wrong kind of object (according to Microslush)...and they even
tell you that *sometimes* you have to call your program *differently* to make
them *work*.

What I do is breakpoint on each error line, trace in a few routines until I get

to where the obj->str part is being printed and 'look' at it.  Of course, I
have to do it for EACH damn element being printed....look at a traceback
sometime and count how many elements are being printed!

I am still working up my nerve to try a real fix.  The problem is that this is
*Windows* peculiar (aren't they all) and I'm not sure of the *right*..make that
'Pythonic'.. fix.

Thanks

Howard

David Bolen wrote:

> Howard Lightstone <howard at eegsoftware.com> writes:
>
> > OK, I made up a Python class/methods to take over stderr/stdout when
> > running Pythonw applications and display them in a Tkinter window.
> > Works slick.
> >
> > However, this DOESN'T work when embedding Python since pythonrun.c still
> > refers to stdout/stderr directly...which Windows doesn't have set to
> > anything useful.
>
> I don't see many direct references to stdout/stderr in pythonrun.c (at
> least current source) except in some specific low level error
> conditions or system exit scenarios.  It seems to be using the
> sys.stdout and sys.stderr objects pretty consistently, so if they're
> redirected you should be fine.  Certainly anything your prior
> class/methods did in your pythonw applications should be doable in an
> embedded environment.
>
> I think there was a recent thread here on some manner to handle this
> with actual internal API calls (probably PySys_SetObject to point
> stdout/stderr in the sys module to your internal object), but in an
> early embedded application I had, I didn't yet grok Python that well,
> so instead took a more straight forward approach that more closely
> matched how I had done it in pure Python code - by executing actual
> Python code to perform the redirection.
>
> That is, I did the following:
>
> * Created an embedded Python interpreter, and then declared my own code
>   as a module to extend that embedded interpreter (see the recent extending
>   and embedding thread for further info).  The extension was also for other
>   purposes in addition to redirection.
>
> * Wrote internal stdout and stderr functions that routed the messages
>   to an internal display window.  I then declared them as functions in
>   my module I extended the interpreter with.
>
> * Before executing any scripts with the newly created embedded interpreter,
>   I used PyRun_SimpleFile to execute a fixed initialization file that
>   re-routed stdout/stderr, as in ("ecna" is my extension module name):
>
>       import sys
>
>       class StdoutCatcher:
>           def write(self, stuff):
>               ecna.stdout(stuff)
>
>       class StderrCatcher:
>           def write(self, stuff):
>               ecna.stderr(stuff)
>
>       sys.stdout = StdoutCatcher()
>       sys.stderr = StderrCatcher()
>
>   I expect you could also use PyRun_SimpleString instead if you didn't
>   want to depend on an external file.
>
> > How does one reroute/catch these errors?  Unfortunately, the only thing
> > I can think of  involves changing pythonrun.c to use the 'objects'
> > attached to sys.stdout and sys.stderr so they COULD be rerouted.
>
> Could you point at the section of pythonrun.c you think won't follow a
> sys.{stdout,stderr} redirection?
>
> --
> -- David
> --
> /-----------------------------------------------------------------------\
>  \               David Bolen            \   E-mail: db3l at fitlinxx.com  /
>   |             FitLinxx, Inc.            \  Phone: (203) 708-5192    |
>  /  860 Canal Street, Stamford, CT  06902   \  Fax: (203) 316-5150     \
> \-----------------------------------------------------------------------/




More information about the Python-list mailing list