Capture output from stderr
Jeff Epler
jepler at unpythonic.net
Tue Aug 5 22:15:57 EDT 2003
On Wed, Aug 06, 2003 at 12:30:13AM +0000, Grant Edwards wrote:
> I've always used a read handler for this in the past, and it worked fine.
> I don't have an example handy...
... this is found at _tkinter.createfilehandler() or
Tkinter.createfilehandler() [though this didn't work for me!], doesn't
exist on Windows (AFAIK), and seems to be undocumented in pydoc. I think
they're a wrapper on Tcl_CreateFileHandler, which has a manpage.
Here's a little program I just put together, it shows the
output from a command in a scrolling text area, using popen and
_tkinter.createfilehandler. It doesn't do anything in particular about
stderr, but that's a matter of switching to popen4 or a friend (Another
way, on systems that use /bin/sh as their shell, is to use
'exec 2>&1; actual command' as the popen argument). Other niceties need
to be observed, like making the Text and refuse keybooard
focus and be non-editable ...
On my system, a good command that takes some time to execute and only
produces a few hundred lines of output is
$ python tktail.py rpm -qa
... but that'll only work on systems with rpm. Something that would
work on more systems would be
$ python tktail.py "for i in /*; do echo $i; sleep 1; done"
# The following code is placed in the public domain
import Tkinter, _tkinter, fcntl, os, sys
t = Tkinter.Tk()
tx = Tkinter.Text(wrap="char")
tx.pack(side="left", expand=1, fill="both")
s = Tkinter.Scrollbar(orient="v", command=tx.yview)
s.pack(side="left", fill="y")
tx.configure(yscrollcommand=s.set)
command = " ".join(sys.argv[1:])
t.wm_title("%s - tktail" % command)
p = os.popen(command, "r")
pf = p.fileno()
# Make reads from the popen'd command nonblocking
# (so read returns the bytes available without waiting)
fcntl.fcntl(pf, fcntl.F_SETFL, os.O_NONBLOCK)
def readfunc(fileobj, event_type):
bytes = p.read()
if bytes == '':
bytes = "***END OF OUTPUT***"
t.wm_title("%s - COMPLETED - tktail" % command)
_tkinter.deletefilehandler(p)
# bbox is a true value if the specified location is visible
b = tx.bbox('end - 1l')
tx.insert('end', bytes)
# If the bottom line was visible before, scroll to the
# new bottom.
if b: tx.see('end')
_tkinter.createfilehandler(p, Tkinter.READABLE, readfunc)
t.mainloop()
Jeff
More information about the Python-list
mailing list