在python中终止子进程

发布于 2024-10-09 22:06:49 字数 1543 浏览 3 评论 0原文

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

我有一个运行许多其他 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 开发服务器。

我更改了 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 KeyboardInterrupt 块,其中 <代码>sys.exit(0)。所以,整个设置看起来是一样的。

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

可能是一个解释:

看起来像 django manage.py fork 本身,或者做类似的事情;查看活动监视器(osx 的进程资源管理器),我看到启动了 3 个 python 进程 - 一个用于主脚本,可能还有 2 个用于管理.py。终止时,其中两个停止(主脚本和我通过 p 链接到的脚本),而第三个仍然继续锁定 8000 端口。 有没有办法获取进程的子进程pid?

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="../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.

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

末骤雨初歇 2024-10-16 22:06:49

您可以使用 psutil 来查找有关子进程的信息,例如在伪代码中:

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

请注意差异在没有 --reload 的情况下运行时的进程中,使用 ps -ef | 获得grep 管理.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

与使用 --noreload 选项相比:

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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文