The OutputDebugString Windows API call allows applications to produce output which can be collected by an independent debugger process reading from a pipe. The OutputDebugString function itself is exposed by the win32api module in pywin32, and is simple enough to use. Capturing the messages which applications produce using this call requires a specific set of pipes and buffers.
Update: For a useful application of this see Ken McFadden's LogDbgView class
A thread on python-list started by Dan Brotherston led to some experimentation and eventually to the solution below, reproduced with Dan's permission although slightly modified by me. The crucial thing turned out to be creating the mmap buffer with ACCESS_WRITE (although we're not quite sure why).
# # Original code by Dan Brotherston # import sys import mmap import struct import win32event buffer_ready = win32event.CreateEvent ( None, 0, 0, "DBWIN_BUFFER_READY" ) data_ready = win32event.CreateEvent ( None, 0, 0, "DBWIN_DATA_READY" ) buffer = mmap.mmap (0, 4096, "DBWIN_BUFFER", mmap.ACCESS_WRITE) while True: # # Signal that we're ready to accept debug output # win32event.SetEvent (buffer_ready) if win32event.WaitForSingleObject (data_ready, win32event.INFINITE) == win32event.WAIT_OBJECT_0: buffer.seek (0) # # The first DWORD is the process id which generated the output # process_id, = struct.unpack ("L", buffer.read (4)) data = buffer.read (4092) if "\0" in data: string = data[:data.index ("\0")] else: string = data print "Process %d: %s" % (process_id, string)
To see it in action, run this snippet which will keep spawning processes to send debug output
import os, time for i in range (10): os.system ( 'python -c "import os;import win32api;win32api.OutputDebugString ("""From %d""" % os.getpid ())"' ) time.sleep (0.5)