在python中终止子进程

时间:2010-12-29 14:05:27

标签: python django subprocess

根据我自己的调查完全重写

我有一个运行许多其他python脚本的主脚本。 脚本创建为

from subprocess import STDOUT, Popen
from signal import SIGINT
import shlex
p = Popen(shlex.split("python somescript.py arg1 arg2"), cwd="../src/somedir", stderr=STDOUT)

并以

结束
p.send_signal(SIGINT)
p.wait()

在其中有以下代码

if __name__ == "__main__":

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

    # do some work here

每个脚本都有一些功能

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

所有描述的工作都是假定的 - 主脚本创建进程,当执行结束时,它会向它们发送SIGINT,它们以正确的方式处理它,正常退出。

现在,我想以同样的方式运行Django dev服务器。

我修改了manage.py文件:

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

    execute_manager(settings)

多个调用后的execute_manager函数会导致django命令方法具有except KeyboardInterruptsys.exit(0)。所以,整个设置看起来都一样。

问题:django服务器实际上并没有停止,但我看到got SIGINT输出。

可能是一个解释:

看起来django manage.py会自行分叉,或做类似的事情;查看Activity Monitor(osx的进程资源管理器)我看到3个python进程已经启动 - 一个用于主脚本,而且可能是2个用于manage.py。终止时,其中2个停止(主脚本,以及我与p链接的那个),而第三个仍然继续锁定8000端口。 有没有办法获得进程'subprocesses pids?

1 个答案:

答案 0 :(得分:0)

您可以使用psutil查找子进程,例如:在伪代码中:

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

请注意使用ps -ef | grep manage.py | grep -v grep

获取的没有--reload运行时的流程差异
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

与使用--noreload选项进行比较:

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