开发者

Terminating subprocess in python

Completely rewritten based on my own investigation

I have a master script that runs a number of other python scripts. The scripts are created as

from subprocess import STDOUT, Popen
from signal import SIGINT
import shlex
p = Popen(shlex.split("python somescript.py arg1 arg2"), cwd="../s开发者_如何学Gorc/somedir", stderr=STDOUT)

And are terminated with

p.send_signal(SIGINT)
p.wait()

Inside them there is the following code

if __name__ == "__main__":

    import signal
    def terminate(*args):
        raise KeyboardInterrupt
    signal.signal(signal.SIGINT, terminate)

    # do some work here

Each script has some function having

try:
    # create workers
except KeyboardInterrupt:
    # cleanup, wait for the current worker to end, then return

All of the described works as supposed - the master script creates the processes, when it's execution ends, it sends them SIGINT, they handle it in the correct way, gracefully exiting.

Now, I want to run the Django dev server in the same way.

I altered the manage.py file:

if __name__ == "__main__":
    import signal
    def terminate(*args):
        print 'got SIGINT'
        raise KeyboardInterrupt
    signal.signal(signal.SIGINT, terminate)

    execute_manager(settings)

The execute_manager function after a number of calls leads to a django command method having the except KeyboardInterrupt block with sys.exit(0). So, the whole setup looks the same.

The problem: the django server is not actually stopped, though I see the got SIGINT output.

Probably an explanation:

Looks like django manage.py forks itself, or does something similar; looking into Activity Monitor (the osx's processes explorer) I see 3 python processes started - the one for the master script, and, probably, 2 for manage.py. When terminating, 2 of them stop (the master script, and the one I have the link to with p), while the third remains continuing locking the 8000 port. Is there a way to get process' subprocesses pids?


You can use psutil to find out about child processes, e.g. in pseudo-code:

p = Popen(...)
pp = psutil.Process(p.pid)
for child in pp.get_children():
    child.send_signal(signal.SIGINT)

Note the difference in processes when running without --reload, obtained using ps -ef | grep manage.py | grep -v grep:

vinay 7864 7795  9 22:10 pts/0 00:00:00 python ./manage.py runserver
vinay 7865 7864 16 22:10 pts/0 00:00:00 /usr/bin/python ./manage.py runserver

compared with using the --noreload option:

vinay 7874 7795  7 22:10 pts/0 00:00:00 python ./manage.py runserver --noreload
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜