Re: Capture output from stderr

Discussion in 'Python' started by Grant Edwards, Aug 6, 2003.

  1. In article <>, klappnase wrote:

    > I am trying to program a Tkinter application for linux, so I want to
    > run a shell command from the gui and capture its output on the fly
    > while the process is still running in order to display the progress
    > messages in a toplevel window so the user may watch what is going on
    > (the execution of the shell command may take a few minutes). Because
    > the output is printed to stderr I thought I should use a popen2.Popen4
    > instance for that, like:
    >
    > self.pp = popen2.Popen4("exec cmd")
    >
    > I tried something like
    >
    > def getmsg(self):
    > msg = self.pp.fromchild
    > newmsg = msg.read(100)
    > ...(do something)...
    > self.master.after(1000, self.getmsg)


    I've always used a read handler for this in the past, and it worked fine.
    I don't have an example handy...

    --
    Grant Edwards grante Yow! Like I always
    at say -- nothing can beat
    visi.com the BRATWURST here in
    DUSSELDORF!!
     
    Grant Edwards, Aug 6, 2003
    #1
    1. Advertising

  2. Grant Edwards

    Jeff Epler Guest

    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
     
    Jeff Epler, Aug 6, 2003
    #2
    1. Advertising

  3. In article <>, Jeff Epler wrote:

    >> I've always used a read handler for this in the past, and it worked fine.
    >> I don't have an example handy...


    I was about to look up my example program, but you beat me to it. ;)

    > 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.


    [...]

    > import Tkinter, _tkinter, fcntl, os, sys
    >
    > 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()


    I always use os.read(pf) rather than the file object's read method to gaurd
    against cases where the file descriptor is readable when the file object
    isn't. I don't know if that ever really happens, but it seemed to be the
    safe thing to do. I suspect that your setting the file descriptor to
    non-blocking accomplishes the same thing.

    > if bytes == '':
    > bytes = "***END OF OUTPUT***"
    > t.wm_title("%s - COMPLETED - tktail" % command)
    > _tkinter.deletefilehandler(p)

    [...]

    > _tkinter.createfilehandler(p, Tkinter.READABLE, readfunc)
    > t.mainloop()


    --
    Grant Edwards grante Yow! I need "RONDO".
    at
    visi.com
     
    Grant Edwards, Aug 6, 2003
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    2
    Views:
    491
    Nobody
    Oct 20, 2010
  2. Simon Strandgaard

    capture stderr

    Simon Strandgaard, Feb 10, 2004, in forum: Ruby
    Replies:
    5
    Views:
    160
    Simon Strandgaard
    Feb 10, 2004
  3. Sard Aukary

    stderr capture on Windows

    Sard Aukary, Aug 13, 2006, in forum: Ruby
    Replies:
    5
    Views:
    136
    Sard Aukary
    Aug 14, 2006
  4. Marcus Bristav
    Replies:
    1
    Views:
    160
    Chris Hulan
    Jan 30, 2008
  5. Marv
    Replies:
    3
    Views:
    193
    Leslie Hazelton
    Feb 3, 2004
Loading...

Share This Page