2

Here's my main file:

import subprocess, time

pipe = subprocess.PIPE
popen = subprocess.Popen('pythonw -uB test_web_app.py', stdout=pipe)
time.sleep(3)

And here's test_web_app.py:

import web

class Handler:
  def GET(self):  pass
app = web.application(['/', 'Handler'], globals())
app.run()

When I run the main file, the program executes, but a zombie process is left hanging and I have to kill it manually. Why is this? How can I get the Popen to die when the program ends? The Popen only hangs if I pipe stdout and sleep for a bit before the program ends.

Edit -- here's the final, working version of the main file:

import subprocess, time, atexit

pipe = subprocess.PIPE
popen = subprocess.Popen('pythonw -uB test_web_app.py', stdout=pipe)

def kill_app():
  popen.kill()
  popen.wait()
atexit.register(kill_app)

time.sleep(3)
Jesse Aldridge
  • 7,991
  • 9
  • 48
  • 75

2 Answers2

2

You have not waited for the process. Once it's done, you have to call popen.wait.

You can check if the process is terminated using the poll method of the popen object to see if it has completed.

If you don't need the stdout of the web server process, you can simply ignore the stdout option.


You can use the atexit module to implement a hook that gets called when your main file exits. This should use the kill method of the Popen object and then wait on it to make sure that it's terminated.

Noufal Ibrahim
  • 71,383
  • 13
  • 135
  • 169
  • The subprocess is never going to be done... it keeps serving forever. I want the subprocess to die when the parent process ends (when I close the console). And I need the stdout. – Jesse Aldridge Feb 17 '11 at 09:47
1

If your main script doesn't need to be doing anything else while the subprocess executes I'd do:

import subprocess, time

pipe = subprocess.PIPE
popen = subprocess.Popen('pythonw -uB test_web_app.py', stdout=pipe, stderr=pipe)
out, err = popen.communicate()

(I think if you specifically pipe stdout back to your program, you need to read it at some point to avoid creating zombie processes - communicate will read it in a reasonably safe way).

Or if you don't care about parsing stdout / stderr, don't bother piping them:

popen = subprocess.Popen('pythonw -uB test_web_app.py')
popen.communicate()
FredL
  • 961
  • 7
  • 13
  • The main script does need to be doing stuff. The real version of the main script captures output from the subprocess, applies some fancy formatting, and displays the output live -- non-blocking. – Jesse Aldridge Feb 17 '11 at 09:51
  • Oh, in that case it's a bit trickier, and not something I've done sorry - though this question might point you in the right direction: http://stackoverflow.com/questions/2804543/read-subprocess-stdout-line-by-line – FredL Feb 17 '11 at 09:58