Guification of console app

Fredrik Lundh fredrik at
Fri Nov 25 10:49:54 CET 2005

"metiu" wrote:

> you have a compression utility that works as a standard *nix filter, so
> it takes something from stdin and gives it back compressed to stdout
> you like to use it as such, because it's nice to call it from the
> command line
> now someone finds your utility quite nice, and says it would be nice to
> have a GUI that shows you, for example, how long it will take to
> compress...
> one way for sure it would be to fork your app, but this would be a
> waste of time
> you'd like to reuse the compression library you've already written for
> your GUI and your console, but:
> - you'd like to have your console app clean and simple, such as:
> import sys
> import CompressLib
> data =
> cdata = CompressLib.compress(data)
> print cdata
> but you'd like the GUI to show some progress and status info.

here's a simple, stupid, and portable solution.  the first script simulates
your compression utility:

    # (simulator)

    import time, sys

    for i in range(100):
        sys.stderr.write("%d%% done\r" % i)

(it prints "N% done" messages to stderr during the compression)

the second script simulates your GUI.  the stuff in the while loop should
be run by a timer/alarm function, at regular intervals:

    import re, subprocess, time, os

    class monitor:
        # looks for "N% done" messages in the output stream
        def __init__(self, tfile):
            # could use dup/reopen instead
            self.file = open(, "r")
        def poll(self):
            pos = self.file.tell()
            data =
            if data:
                data = re.findall("(\d+)% done", data)
            if not data:
                return int(data[-1])
        def close(self):

    ifile = open("in.txt", "rb")
    ofile = open("out.dat", "wb")
    tfile = open("out.tmp~", "wb")

    p = subprocess.Popen(
        stdin=ifile, stdout=ofile, stderr=tfile,

    m = monitor(tfile)

    while 1:
        # this should be placed in a background task that's called
        # every second or so
        if p.poll() is not None:
            print "DONE"
        status = m.poll()
        if status is not None:
            # update status monitor
            print status, "PERCENT DONE"
        # wait a while before calling the background task again
        print "."

    # clean up
    name =

if you limit yourself to Unix only, you can simplify things quite a bit (e.g.
using a pipe instead of the temporary file and use select to poll it, or use
dup/reopen tricks to avoid opening the temporary file twice; if you do
the latter, you can also use safe tempfile creation methods (see the
"tempfile" method for details.  etc).

hope this helps!


More information about the Python-list mailing list