[Python-Dev] Create a synthetic stdout for Windows?

James C. Ahlstrom jim@interet.com
Mon, 08 Jan 2001 10:43:05 -0500


There a number of problems which frequently recur on c.l.p
that can serve as a source of Python improvement ideas.
On December 30, 2000 gerson.kurz@t-online.de (Gerson Kurz) writes:

   If I embedd Python in a Win32 console application (using
   Demo\embed.c), everything works fine. If I take the very same piece
of
   code and put it in a Win32 Windows application (not MFC, just a plain
   WinMain()) I see no output (and more importantly so, no errors),
   because the application does not have a stdout/stderr set up.

This is well known.  Windows developers must replace sys.stdout and
sys.stderr with alternative mechanisms.  Unfortunately this solution
does not completely work because errors can occur before sys.stdout
is replaced.  I propose patching pythonw.exe (WinMain.c) and adding
a new module to fix this so it Just Works.  The patch is completely
Windows specific.  I am not sure if this constitutes a PEP, but would
like everyone's feedback anyway.

Design Requirements

1) "pythonw.exe myfile.py" will give the usual error message if
   myfile.py does not exist.

2) "pythonw.exe myfile.py" will give the usual traceback for a
   syntax error in myfile.py.

3) python.exe will provide a useful C-language stdout/stderr so
   the user does not have to replace sys.stdout/err herself.

4) None of the above will interfere will the user's replacement
   of sys.stdout/err for her own purposes.

Description of Patch

A new module winstdoutmodule.c (138 lines) is included in Windows
builds. It contains a C entry point PyWin_StdoutReplace() which
creates a valid C stdout/err, and code to display output
in a popup dialog box.  There is a Python entry point
winstdout.print() to display output, but it is only used
for special purposes, and the typical user will never import
winstdout.

The file WinMain.c calls PyWin_StdoutReplace() before it
calls Py_Main(), and PyWin_StdoutPrint() afterwards.  This
is meant to display startup error messages.  Normally,
any available output is displayed when the system is idle.

Technical Details

Some experimentation (as opposed to documentation) shows that
Win32 programs have a valid FILE * stdout, but fileno(stdout)
gives INVALID_HANDLE_VALUE; the FILE * has an invalid OS file
object.  It is tempting to hack the FILE structure directly.
But it is more prudent to use the only documented way to
replace stdout, namely the standard call "freopen()" (also
available on Unix).  The design uses this call to open a
temporary file to append stdout and stderr output.  To
display output, the file is checked when the system is
idle, and MessageBox() is called with the file contents if any.

Status

After a few false starts, I now have working code.

Is this a good idea?  If so, is the implementation optimal
(comments from MarkH especially welcome)?

JimA