continuous redirection of stdout & stderr to Tkinter Text

Howard Lightstone howard at eegsoftware.com
Thu Jun 27 02:51:17 EDT 2002


Fabien Hénon <ffjhenon at club-internet.fr> wrote in 
news:3D1A32B0.CA7D3618 at club-internet.fr:

> I am using Tkinter as an editor and a launcher (under Linux) for a
> raytracer (POV-RAY)
> 
> Once started, the raytracer does two things in the same time :
> - it displays the image being raytraced
> - it spits out information to the console (ie : the line which is being
> raytraced). 
> I get the image displayed but not the redirection of stdout
> 
It was always too much for me so I built this simple class (which I use to 
get errors when running with pythonw):
"""
Pseudo debug screens

These capture stderr/std and route them to a Tkinter text widget.
This implementation uses a common window for stdout/stderr with
an asterisk at the beginning of each stderr line.

"""
import Tkinter
import sys,string

class DbgText:
    Dbgtopwin=None
    Dbgwidget=None
    DbgRoot=None
    
    def _kill_topwin(self):
        DbgText.Dbgwidget=None
        if DbgText.Dbgtopwin != None:
            DbgText.Dbgtopwin.destroy()
        DbgText.Dbgtopwin=None
       
    def __init__(self,kind=''):
        self.kind=kind
        self.window=None
        self.widget=None
        self.called=0
        self.hide=0
        self.buffer=''

    def __del__(self):
        "On deletion, wait for user to see the output"
        if DbgText.Dbgtopwin != None:
            See()
        self._kill_topwin()
    
    def write(self,charstr):
        "write text to buffer or window"
        if self.hide:
            self.buffer.append(charstr)
        else:
            if self.window == None:
                if DbgText.Dbgtopwin == None:
                    DbgText.Dbgtopwin=Tkinter.Tk()
                    DbgText.Dbgtopwin.protocol('WM_DELETE_WINDOW',Dbg_kill_
topwin)
                    DbgText.Dbgwidget=Tkinter.Text(DbgText.Dbgtopwin)
                    DbgText.Dbgwidget.pack(expand=1)
                top=DbgText.Dbgtopwin
                wid=DbgText.Dbgwidget
            else:
                if self.widget == None:
                    self.widget=Tkinter.Text(self.window)
                top=self.window
                wid=self.widget
            if self.kind != '':
                ep=wid.index('end')
                sp=string.split(ep,'.')
                # determine length of 'previous' line
                prevl=int(sp[0])
                tx='\n'
                if prevl:
                    pl='%d.0' % (prevl-1)
                    tx=wid.get(pl,ep)
                # if this is start of a new line
                if tx[0] == '\n':
                    wid.insert('end',self.kind)
            wid.insert('end',charstr)     
        self.called=1
        top.update()

def Dbg_kill_topwin():
    f=DbgText()
    f._kill_topwin()
    
def Take_stdout():
    "DIsplay stdout in text widget"
    if not isinstance(sys.stdout,DbgText):
        f=DbgText()
        f.prev=sys.stdout
        sys.stdout=f

def Take_stderr():
    "DIsplay stderr in text widget"
    if not isinstance(sys.stderr,DbgText):
        f=DbgText('*')
        f.prev=sys.stderr
        sys.stderr=f

    
def Restore_stdout():
    f=sys.stdout
    if isinstance(f,DbgText):
        sys.stdout=f.prev
        del f

def Restore_stderr():
    f=sys.stderr
    if isinstance(f,DbgText):
        sys.stderr=f.prev
        del f

def Define_Root():
    root=Tkinter.Tk()
    root.withdraw()
    DbgText.DbgRoot=root


def See():
    db=DbgText()
    if db.Dbgtopwin != None:
        db.Dbgtopwin.mainloop() # loop for me to see

def Take_all():
    "send stderr/stdout to Tkinter text window/widget"
    Take_stdout()
    Take_stderr()

def Restore_all():
    "restore stderr/stdout"
    Restore_stdout()
    Restore_stderr()

        
if __name__ == '__main__':
    print 'stdout is here'
    Take_stdout()
    print 'stdout should now be in window'
    print ' this is the second line'
    raw_input()
    Restore_stdout()
    print 'stdout back to original'
    



More information about the Python-list mailing list