Charles Reich
Charles Reich

Reputation:

why doesn't subprocess.Popen(...) always return?

I hope this is a simple python question.

When I try the following in the python interpreter:

>>> import process
>>> def test(cmd):
...   p = subprocess.Popen(cmd)
...
>>> test(['ls', '-l'])

It will run the ls -l, but I need to hit "return" to get a new >>> prompt.

However, when I try the following:

>>> import process
>>> def test(cmd):
...   p = subprocess.Popen(cmd)
...   p.wait()
...
>>> test(['ls', '-l'])

Then the ls -l will be run with a >>> prompt immediately present.

One other variation:

>>> import process
>>> def test(cmd):
...   p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
...
>>> test(['ls', '-l'])

This will give me an immediate new prompt.

The last example is closest to what I want. My goal is to launch a child process, wait for it to finish and then use its stdout in my parent process by referring to p.stdout while letting stderr just print to wherever it would otherwise.

Right now in my actual application, the last version just hangs at the: p = subprocess.Popen(cmd, stdout=subprocess.PIPE) with or without a p.wait().

Thanks,

Charlie

Upvotes: 8

Views: 13872

Answers (4)

storm_m2138
storm_m2138

Reputation: 2509

Here is a command that pings Google forever, so it needs to be manually terminated to retrieve the output.

See the subprocess documentation for instructions on converting os.popen() method calls to full subprocess.Popen classes.

host = "www.google.com"
command = "ping %s -t"%host

#p = os.popen(command) -- using Popen instead of os.popen() to allow calling terminate()
p = Popen(command, stdout=subprocess.PIPE)

time.sleep(5)
print "term"
p.terminate()
pingResultSoFar = p.communicate()[0] # get what has been printed to standard out so far
print pingResultSoFar

Upvotes: 1

user3273866
user3273866

Reputation: 604

Just use communicate() method.No need to return.

>>> test(['ls', '-l'])
>>> 
>>> def test(cmd):
...    p = subprocess.Popen(cmd).communicate()
... 
>>> test(['ls', '-l'])

Upvotes: 0

Charles Reich
Charles Reich

Reputation:

I may have answered my own question. I believe that in the final case, I need to explicitly read from p.stdout in order for my process to continue.

ie:

p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
output = p.stdout.readlines()
....

Thanks all

Upvotes: 7

dF.
dF.

Reputation: 75785

In the first variation, test() returns immediately after starting the process, but before its output is sent to the console.

If you look at the output you do get the prompt, immediately before the output of ls.

>>> test(['ls', '-l'])
>>> total 0                            <----- test() returns, new propmpt
--rw-r--r--    1 foo bar   7 Mar 24 17:38
etc etc

In the second variation, test() is waiting for the process to terminate before it returns.

In the third version, you're right that you may have to read from the child process's stdout for it to continue.

Upvotes: 8

Related Questions