Guification of console app
Chris Mellon
arkanes at gmail.com
Fri Nov 25 08:50:54 EST 2005
On 11/25/05, Fredrik Lundh <fredrik at pythonware.com> wrote:
> "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 = sys.stdin.read()
> > 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:
>
> # compress.py (simulator)
>
> import time, sys
>
> for i in range(100):
> sys.stdout.write(".")
> sys.stderr.write("%d%% done\r" % i)
> sys.stderr.flush()
> time.sleep(0.1)
>
> (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(tfile.name, "r")
> def poll(self):
> pos = self.file.tell()
> data = self.file.read()
> if data:
> data = re.findall("(\d+)% done", data)
> if not data:
> self.file.seek(pos)
> else:
> return int(data[-1])
> def close(self):
> self.file.close()
>
> ifile = open("in.txt", "rb")
> ofile = open("out.dat", "wb")
> tfile = open("out.tmp~", "wb")
>
> p = subprocess.Popen(
> "python compress.py",
> 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"
> break
> 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 "."
> time.sleep(0.5)
>
> # clean up
> ifile.close()
> ofile.close()
> m.close()
> name = tfile.name
> tfile.close()
> os.remove(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!
>
> </F>
>
>
If you are using wxPython, you can skip writing this scaffolding
yourself and use wx.Execute and wx.Process, which will allow you to
execute other processes and re-direct thier input and output. The
wxPython demo has an example.
>
> --
> http://mail.python.org/mailman/listinfo/python-list
>
More information about the Python-list
mailing list