简体   繁体   English

在python中终止子进程

[英]Terminating subprocess in python

Completely rewritten based on my own investigation 根据我自己的调查完全重写

I have a master script that runs a number of other python scripts. 我有一个运行许多其他python脚本的主脚本。 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="../src/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. 所有描述的工作均按预期进行-主脚本创建进程,执行结束后,将其发送给SIGINT,它们以正确的方式进行处理,并正常退出。

Now, I want to run the Django dev server in the same way. 现在,我想以相同的方式运行Django开发服务器。

I altered the manage.py file: 我更改了manage.py文件:

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) . 多次调用后, execute_manager函数导致django命令方法具有sys.exit(0) except KeyboardInterrupt块。 So, the whole setup looks the same. 因此,整个设置看起来相同。

The problem: the django server is not actually stopped, though I see the got SIGINT output. 问题:虽然我看到got SIGINT输出,但django服务器实际上并未停止。

Probably an explanation: 可能是一个解释:

Looks like django manage.py forks itself, or does something similar; 看起来像django manage.py本身分叉,或执行类似操作; 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. 查看Activity Monitor(osx的进程浏览器),我看到启动了3个python进程-一个用于主脚本,可能还有2个用于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. 终止时,其中两个停止(主脚本,而我具有p的链接),而第三个仍然继续锁定8000端口。 Is there a way to get process' subprocesses pids? 有没有一种方法来获取流程的子流程pid?

You can use psutil to find out about child processes, eg in pseudo-code: 您可以使用psutil来查找有关子进程的信息,例如使用伪代码:

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 注意在不使用--reload的情况下(使用ps -ef | grep manage.py | grep -v grep ps -ef | grep manage.py | grep -v grep ps -ef | grep manage.py | grep -v grep : 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: 与使用--noreload选项相比:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM