If I try to spawn a process from a pylons controller, the server does not close the connection after sending the reply.
Assume that test.py
is a long running process, then this method in a pylons controller creates a response, but keeps the connection open:
def index(self):
from subprocess import Popen
Popen(["python", "/temp/test.py"])
return "<h1>Done!</h1>"
Moving the Popen
to a new thread did not help.
Luckily, I found a workaround: I start a new thread and add a sleep
before the Popen
. If the Popen starts after the response has been sent, the connection will be closed properly.
def test(self):
def worker():
import time
time.sleep(5)
from subprocess import Popen
Popen(["python", "/temp/test.py"])
from threading import Thread
Thread(target=worker).start()
return "<h1>Done!</h1>"
Can anyone explain this behavior? I'd like to be sure I won't be causing strange problems down the line.
I'm using Python 2.5 and Pylons 0.9.6.1 on Windows XP SP3.
UPDATE: bnonlan's answer is definitely on the right track. Popen
has a parameter named close_fds
which is supposed to solve this problem. In the Python 2.5 version of the subprocess
module, this parameter is unsupported on Windows. However, in the Python 2.6 version you can set this parameter to True
if you don't redirect stdin/stdout/stderr.
def index(self):
# I copied the 2.6 version of subprocess.py into my tree
from python26.subprocess import Popen
Popen(["python", "/temp/test.py"], close_fds=True)
return "<h1>Done!</h1>"
Sadly, I do want to redirect stdout, so I need to find another solution. Also, this implies that the workaround I found might keep other requests from closing if they happen to be running when the Popen executes. This is troubling.