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

时间:2013-11-23 01:01:31

标签: python django python-2.7 subprocess

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

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

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

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)

3 个答案:

答案 0 :(得分:2)

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

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

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


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

答案 1 :(得分:1)

Unix中的进程会一直存在,直到父进程等待它们为止。对thepopen返回的对象进行调用wait将等待进程完成并等待它以使其消失。在你这样做之前,它将作为zombie processthis message存在,以获取有关在Web服务器运行时让进程在后台运行而无需在前台线程/视图中等待的信息。

所以,让我们说你做了

p = subprocess.Popen(...)

在某些时候你需要打电话     p.wait()

答案 2 :(得分:1)

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

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

subprocess模块调用_cleanup()函数,用于获取Popen() constructor内的僵尸进程。所以通常你的脚本不会创建很多僵尸进程。

要查看僵尸进程列表:

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