Subprocess and /usr/bin/dialog

Grant Edwards grante at visi.com
Sat Mar 22 11:44:31 EDT 2008


On 2008-03-22, harrelson <harrelson at gmail.com> wrote:

>>> proc = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
>>> stderr_value = proc.communicate()[0]
>>> print stderr_value

>> dialog displays the widget on stdout.  You've connected stdout
>> to a pipe, so you're not going to see anything displayed unless
>> you read data from the stdout pipe and write it to the terminal.
>
> Reading this tutorial on subprocess:
>
> http://blog.doughellmann.com/2007/07/pymotw-subprocess.html
>
> led me to believe this was exactly what I was doing.

Ah, my mistake.  I believed you when you named the variable
"stderr_value".  ;)

I've never used the communicate() method, but according to that
tutorial:

   "The communicate() method reads all of the output and waits for
    child process to exit before returning.

And the lib references says:

communicate(input=None)

    Interact with process: Send data to stdin. Read data from
    stdout and stderr, until end-of-file is reached. Wait for
    process to terminate. The optional input argument should be
    a string to be sent to the child process, or None, if no
    data should be sent to the child.

    communicate() returns a tuple (stdout, stderr). 

The key is that it doesn't return until after the subprocess
has terminated.
    
So, you're reading stdout and putting it in the variable you
named stderr_value.  After the dialog exits, you then print the
stdout string (which contains the widget's "display" data).
Since the widget has already exited, that string contains both
the initial display _and_ the escape sequence that clears the
screen and restores it.  So, you just see a flash of blue.  If
you want to be able to see and interact with the widget, you
need to leave stdout connected to the terminal while the widget
is running.

Try this:

------------------------------------------------------------
import subprocess
command = '/usr/bin/dialog --clear --title "title" --menu "text" 20 50 5 "a" "this and that" "c" "3 this and that" "b" "2 this and that" "d" "4 this and that"'
proc = subprocess.Popen(command, shell=True, stderr=subprocess.PIPE)
stdout,stderr = proc.communicate()
print stderr
------------------------------------------------------------

NB: using shell=True introduces a number security holes and
    adds the overhead of starting a shell.  It's good practice
    to avoid it if you don't actually need a shell (you don't).
    However, without it you need to split up the command line
    explicitly:

------------------------------------------------------------
import subprocess
command = ('/usr/bin/dialog','--clear','--title','title', '--menu','text','20','50','5',
             'a','this and that',
             'c','3 this and that',
             'b','2 this and that',
             'd','4 this and that')
proc = subprocess.Popen(command, stderr=subprocess.PIPE)
stdout,stderr = proc.communicate()
print stderr
------------------------------------------------------------

If you're generating the commands programatically, it's usually
simpler to generate them as tuples as shown in the second
example anyway.

-- 
Grant Edwards                   grante             Yow!  I joined scientology
                                  at               at a garage sale!!
                               visi.com            



More information about the Python-list mailing list