在我的一个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)
答案 0 :(得分:2)
真的,你所做的是错的。使用像subprocess.Popen
这样的高级包装器时,需要通过该对象管理进程。在其他地方拥有PID并不足以管理它。
如果您坚持处理PID而不是Popen
个对象,那么您应该使用os
中的低级API。
幸运的是,你没有做任何复杂的事情,比如创建管道来与子进程交谈。因此,您可以使用您最喜欢的spawn
变体启动它,然后使用waitpid
或其中一个变体等待它。
我假设您在单进程Web服务器中执行此操作。如果您正在使用分叉Web服务器,其他页面可能处于不同的进程中,即使使用PID也无法正常工作。父进程必须收获子进程,而不是其他任意进程。如果你想做那些工作,你将不得不让事情变得更复杂,而且你真的必须先了解Unix流程模型,然后才能向你解释。
答案 1 :(得分:1)
Unix中的进程会一直存在,直到父进程等待它们为止。对thepopen返回的对象进行调用wait将等待进程完成并等待它以使其消失。在你这样做之前,它将作为zombie process以this 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(),