Guification of console app
Fredrik Lundh
fredrik at pythonware.com
Fri Nov 25 04:49:54 EST 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 = 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>
More information about the Python-list
mailing list