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

James C. Ahlstrom jim@interet.com
Mon, 08 Jan 2001 14:16:45 -0500

Mark Hammond wrote:

> Note that the original problem was _embedding_ Python - thus, you need to
> patch _their_ WinMain to make it work for them - something you can't do.

Correct, if they don't use pythonw.exe, but use a different
main program, the new stdout will not be installed.  But then
they must have their own main.c, and they can add the C call.
> Even if PyWin_StdoutReplace() was a public symbol so they _could_ call it, I

Yes, the symbol PyWin_StdoutReplace() is public, and they
can call it.

> am not convinced they would - it is almost certain they will still need to
> redirect output to somewhere useful, so why bother redirecting it
> temporarily just to redirect it for real immediately after?

Redirecting it temporarily is valuable, because if the sys.stdout
replacement occurs in (for example) myprog.py, then "pythonw.exe
will fail to produce any error messages for a syntax error in myprog.py.

Also, I was hoping further sys.stdout redirection would be unnecessary.
> Finally, I am slightly concerned about the possibility of "hanging" certain
> programs. For example, I believe that DCOM will often invoke a COM server in
> a different "desktop" than the user (this is also true for Services, but
> Python services don't use pythonw.exe).  Thus, a Python program may end up
> hanging with a dialog box, but in the context where no user is able to see
> it.  However, this could be addressed by adding a command-line option to
> prevent this new behaviour kicking in.

Limiting the code to pythonw.exe instead of trying to install
it in python20.dll was supposed to prevent damage to the use
of Python in servers.  Since pythonw.exe is a Windows (GUI) program,
I am assuming there is a screen.  The dialog box is started with
MessageBox() and a window handle of GetForegroundWindow().  So
there doesn't need to be an application window.  I have tested it
with GUI programs, and it also works when run from a console.

Having said that, you may be right that there is some way to
hang on a dialog box which can not be seen.  It depends on what
MessageBox() and GetForegroundWindow() actually do.  If it seems
that this patch has merit, I would be grateful if you would review
the code to look for issues of this type.
> I would prefer to see a decent API for extracting error and traceback
> information from Python.  On the other hand, I _do_ see the problem for
> "newbies" trying to use pythonw.exe.

There could be an API added to the winstdout module such as
  msg = winstdout.GetMessageText()
which would return saved text, control its display etc.
But then the problem remains of actually displaying the messages
especially in the context of tracebacks and errors.  And it is
probably easier to redirect sys.stdout so it does what you want
rather than use the API.

I do not view winstdout as a "newbie" feature, but rather a
generally useful C-language addition to Python.

> So - I guess I am saying that I don't see this as optimal, and it doesnt
> solve the original problem you pointed at - but in the interests of making
> pythonw.exe seem "less broken" for newbies, I could live with this as long
> as I could prevent it when necessary.

I guess I am saying, perhaps incorrectly, that the mechanism provided
will make further redirection of sys.stdout unnecessary 99% of the
time.  Experimentation shows that Python composes tracebacks and
error messages a line or partial line at a time.  That is, you can
not display each call to printf(), but must wait until the system is
idle to be sure that multiple calls to printf() are complete.  So this
forces you to use the idle processing loop, not rocket science but
at least inconvenient.  And the only source of stdout/err is tracebacks,
error messages and the "print" statement.  What would you do with
these in a Windows program except display an "OK" dialog box?

If someone out there knows of a different example of sys.stdout
redirection in use in the real world, it would be helpful if
they would describe it.  Maybe it could be incorporated.

> Another option would be to use the Win32 Console APIs, and simply attempt to
> create a console for the error message.  Eg, maybe PyErr_Print() could be
> changed to check for the existance of a console, and if not found, create
> it.  However, the problem with this approach is that the error message will
> often be printed just as the process is terminating - meaning you will see a
> new console with the error message for about 0.025 of a second before it
> vanishes due to process termination.  Any sort of "press any key to
> terminate" option then leaves us in the same position - if no user can see
> the message, the process appears hung.

Yes, this a problem with the console API approach.  Another is that
popping up a black console for output instead of the usual "OK"
dialog box is unnatural, and will force the user to replace sys.stdout.
I was hoping this C stdout will make this unnecessary.