1

Based on this Stackoverflow question, I am attempting to get the outputs of a process via Python.

Here you have the code:

from subprocess import Popen, PIPE

connection_string = "yowsup-cli demos --yowsup --config config"
popen_parameters = connection_string.split(" ")
proc = Popen(popen_parameters, stdout=PIPE, stderr=PIPE)

while True:
    line = proc.stdout.readline()

    if line != '':
        #the real code does filtering here
        print "Result:", line.rstrip()

    proc.stdout.flush()

Unfortunately nothing is being returned. Btw, I need to interact with the process sending and receiving data. How can I get this done?

Thanks!

Community
  • 1
  • 1

2 Answers2

1

There is no conditional exit from the while loop, even after the command's output has been sent. Try this:

if line != '':
    #the real code does filtering here
    print "Result:", line.rstrip()
else:
    break
user1016274
  • 4,071
  • 1
  • 23
  • 19
1

First of all, your code should work if the child process is actually writing to its stdout. If there is an error in your command, the output might appear on stderr instead.

Note though that your code does not exit the loop so you need to fix that up, e.g. by calling break when you read an empty string.

But there is a better way. Instead of reading the child process' stdout directly, Use Popen.communicate():

from subprocess import Popen, PIPE

connection_string = "yowsup-cli demos --yowsup --config config"
popen_parameters = connection_string.split(" ")
proc = Popen(popen_parameters, stdout=PIPE, stderr=PIPE)

out, err = proc.communicate()
if out:
    print "Received stdout output of length {} from child process".format(len(out))
    print out
elif err:
    print "Received stderr output of length {} from child process".format(len(err))
    print err

The other part of your question deals with interacting with the child process. In the simple case that you start the child process and send it a single input you can still use Popen.communicate() by passing a string argument to it. Note that you need to setup the stdin pipe too. So, as above but:

proc = Popen(popen_parameters, stdin=PIPE, stdout=PIPE, stderr=PIPE)

data = 'data to send to child'
out, err = proc.communicate(data)

If your interaction with the child is more complex, you should consider using the pexpect module which is designed for this usage. While it is possible to do it with Popen() there are some issues with buffering and deadlocking of processes reading/writing pipes, so that is best avoided.

glglgl
  • 89,107
  • 13
  • 149
  • 217
mhawke
  • 84,695
  • 9
  • 117
  • 138
  • Thanks for your comments mhwake. If I replace the connection_string to "ping 192.168.0.9 -c 4" your code works just great. However I still have two issues: 1- I need to keep the connection to the process alive because I will interact with it. Communicate in this case will wait until the process is done. 2- Different than with the ping command, I get no answer from the yowsup. Any idea how I can get this fixed? Thanks!!!! –  Mar 22 '15 at 07:11
  • @glglgl: thanks for the edit. "It's" due to a typo, not ignorance. – mhawke Mar 22 '15 at 08:49
  • @user1688175 - I'm not overly familiar with `yowsup-cli` - what do you see when you run the same command from the command line? Does the output (if there is any) appear on stdout or stderr? Did you take a look at `pexpect`? – mhawke Mar 22 '15 at 09:10