subprocess.Popen() redirecting to TKinter or WXPython textwidget???

I

Ivo Woltring

Hi Pythoneers,

I am trying to make my own gui for mencoder.exe (windows port of the
terrific linux mencoder/mplayer) to convert divx to Pocket_PC size.
My current app creates a batch script to run the mencoder with the needed
params, but now I want to integrate mencoder as a subprocess in my app.

What already works:
the starting of the subprocess.Popen
and the subsequent killing of the process if I want it to.
My gui does not freeze up as it did in my first tries.

What I want to know (what does not yet work ;-)):
- Redirecting the output of the subprocess to a textwidget in my GUI

Any example or help is much appreceated.

I tried the subprocess.PIPE but I think I don't really understand how it is
suppost to work
The redirecting to a file does work but this not my objective...
So I'm stuck..... HELP
The started processes are long and I want to be able to show some kind of
progress-status.

Thanx,
Ivo Woltring
 
S

stewart.midwinter

Ivo, my initial thought would be, you need to know how much text you
will get back from popen. My Python reference has the following
example:

import os
dir = os.popen('ls -al', 'r')
while (1):
line = dir.readline()
if line:
print line,
else:
break

that example shows how to capture the process output in a file-type
object, then bring it into a string with readline().

in your app, you could create a Tkinter stringVar, say myOutput, for
the process output. In your Tkinter widget, you could then set a
textvariable=myOutput. also use the wait_variable and watch options
(hope I recall these correctly, don't have my Tkinter ref. at hand) to
detect when there's been a change to the contents of the StringVar and
update the contents of the label.
Hope this helps, if not, write back.

cheers
S
 
I

Ivo Woltring

Ivo, my initial thought would be, you need to know how much text you
will get back from popen. My Python reference has the following
example:

import os
dir = os.popen('ls -al', 'r')
while (1):
line = dir.readline()
if line:
print line,
else:
break

that example shows how to capture the process output in a file-type
object, then bring it into a string with readline().

[.... snip ....]
cheers
S


Thanx for trying Stewart,
but that is not what I need
The output of mencoder is not readable with readlines (i tried it) because
after the initial informational lines You don't get lines anymore (you get a
linefeed but no newline)
The prints are all on the same line (like a status line)
something like
Pos: 3,1s 96f ( 0%) 42fps Trem: 0min 0mb A-V:0,038 [171:63]

which is coninually updated while the process runs...
in your app, you could create a Tkinter stringVar, say myOutput, for
the process output. In your Tkinter widget, you could then set a
textvariable=myOutput. also use the wait_variable and watch options

How does this work? wait?? anyone?
(hope I recall these correctly, don't have my Tkinter ref. at hand) to
detect when there's been a change to the contents of the StringVar and
update the contents of the label.
Hope this helps, if not, write back.

I really like to know how I can catch the output of a subproces.Popen()
command and redirect it to something else (like a textwidget )
and I really like to use the subprocess module (standard in v2.4) to get to
know it.
Another reason to use the subprocess module is I can stop the process
because I know the handle of the thread. The subprocess module knows all
this.

cheerz,
Ivo.
 
P

paul koelle

Ivo said:
The output of mencoder is not readable with readlines (i tried it) because
after the initial informational lines You don't get lines anymore (you get a
linefeed but no newline)
The prints are all on the same line (like a status line)
something like
Pos: 3,1s 96f ( 0%) 42fps Trem: 0min 0mb A-V:0,038 [171:63]

Have you tried popen3 with stdout and stderr?

hth
Paul
 
J

Jeff Shannon

Ivo said:
The output of mencoder is not readable with readlines (i tried it) because
after the initial informational lines You don't get lines anymore (you get a
linefeed but no newline)
The prints are all on the same line (like a status line)
something like
Pos: 3,1s 96f ( 0%) 42fps Trem: 0min 0mb A-V:0,038 [171:63]

Hm, I'm inferring that what you mean is that you get a carriage return
(ASCII 0x0C) but no linefeed (ASCII 0x0A) -- CR returns you to the
beginning of the current line, and LF advances you to the next line.

Rather than using readlines(), you could simply read() a few
characters (or a single character) at a time, buffering it yourself
and passing it on when you see the CR.

You're likely to run into I/O blockage issues no matter how you do
this, though -- even if you're reading a single character at a time,
read(1) won't return until you've read that character, and if the
program on the other end of the pipe isn't writing anything, then your
app is stuck. The "simple" way to do this is by using an i/o thread,
which does something like this:

buffer = []
while 1:
char = outpipe.read(1)
if char == '\0x0A':
notify_gui_thread( ''.join(buffer) )
buffer = []
else:
buffer.append(char)
if StopEvent.IsSet():
raise CustomStopException

Note that you don't want to try to update your GUI widgets directly
from the worker (i/o) thread -- very few GUI toolkits are threadsafe,
so you need to make all GUI calls from a single thread.

Jeff Shannon
Technician/Programmer
Credit International
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,261
Messages
2,571,040
Members
48,769
Latest member
Clifft

Latest Threads

Top