繁体   English   中英

Python子进程脚本在完成后继续运行

[英]Python subprocess script keeps running after it is done

在我的一个Django视图中,我调用python脚本并获取其pid:

from subprocess import Popen
p = Popen(['python', 'script.py'])
mypid = p.pid

当试图找出进程是否仍在从另一个页面运行时,我在mypid上使用以下函数(感谢这个问题 ):

def doesProcessExist(pid):
    if pid < 0:
        return False
    try:
        os.kill(pid, 0)
    except OSError, e:
        return e.errno == errno.EPERM
    else:
        return True

无论我等待多久, 该过程仍然显示为正在运行 唯一阻止它的是,如果我用Popen生成一个新的python脚本进程。 无论如何我可以解决这个问题吗? 我不确定这是否是由于Django在脚本完成后没有正确关闭python或其他原因造成的。 在Ubuntu的进程状态管理器中,该进程显示为[python] <defunct>

-

对于我尝试过的所有script.py ,问题都是正确的。 我目前正在使用一个简单的:

from time import sleep
sleep(5)

真的,你在做什么是错的。 当您使用像subprocess.Popen这样的高级包装器时,您需要通过该对象管理进程。 在其他地方拥有PID并不足以管理它。

如果你坚持处理PID而不是Popen对象,那么你应该在os使用低级API。

幸运的是,你没有做任何复杂的事情,比如创建管道来与子进程交谈。 因此,您可以使用您最喜欢的spawn变体启动它,然后使用waitpid或其中一个变体等待它。


我假设您在单进程Web服务器中执行此操作。 如果您正在使用分叉Web服务器,其他页面可能处于不同的进程中,即使使用PID也无法正常工作。 父进程必须收获子进程,而不是其他任意进程。 如果你想做这项工作,你将不得不让事情变得更复杂,而且你真的必须先了解Unix流程模型才能向任何人解释。

Unix中的进程一直存在,直到父进程等待它们。 对thepopen返回的对象进行调用wait将等待进程完成并等待它以使其消失。 直到你这样做它将作为一个僵尸进程存在请参阅此消息 ,了解有关在Web服务器运行时让进程在后台运行而不在前台线程/视图中等待它的信息。

所以,让我们说你这样做

p = subprocess.Popen(...)

在某些时候你需要调用p.wait()

你看到的是一个僵尸进程。 它不会继续运行。 它不能。 它死了。 唯一剩下的就是一些允许相关进程检索其状态的信息。

要查明子p.poll()是否处于活动状态而不阻塞,请调用p.poll() 如果它返回None那么进程仍处于活动状态,否则你可以安全地忘记它(它已经被.poll() )。

subprocess进程模块调用_cleanup()函数来_cleanup() Popen()构造函数中的僵尸进程。 所以通常你的脚本不会创建很多僵尸进程。

要查看僵尸进程列表:

import os
#NOTE: don't use Popen() here
print os.popen(r"ps aux | grep Z | grep -v grep").read(),

暂无
暂无

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

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