我有Flask应用程序,它暴露了可以在后台运行应用程序的API,可以通过指定PID来终止它。但是,对于单元测试目的,在杀死PID并检查PID是否使用psutil.pid_exists(pid)
被终止后,它似乎总是返回true。我已手动检查PID不存在并在不同的python控制台上运行psutil.pid_exists(pid)
并返回true。这导致我的测试失败。
在views.py
中,我有:
@api.route('/cancel/<pid>', methods=['POST'])
def cancel(pid=None):
try:
os.kill(int(pid), signal.SIGTERM)
data = dict(
message = 'Successfully killed pid ' + pid)
return jsonify(status='success', data=data), 200
except:
data = dict(
message = 'Fail to kill job with pid ' + pid)
return jsonify(status='error', data=data), 400
在我的测试中:
def test_cancel_job(self):
# run_script will run something in the background and return the PID
jobid, pid, cmd = run_script('fake_db', 'fake_cancel_jobid', 'tests/doubles/child.py')
if not psutil.pid_exists(pid):
raise Exception('Process is not running')
# kill the job and assert it is successful
resp = self.client.post('/api/cancel/' + str(pid))
self.assert200(resp)
# at this point, I have confirmed that the PID has been killed
# but, the line below still get executed
# psutil.pid_exists(pid) returns true
# check pid is really killed
if psutil.pid_exists(pid):
raise Exception('Process {0} still exist'.format(pid))
如果有任何不同,我正在OSX上运行。
更新: 我已经尝试在我的构建服务器(Ubuntu 14.04)上运行测试并且测试失败。
这是我的run_script
def run_script(db, jobid, script):
log = SCRIPTS_LOG + jobid + ".log"
if not os.path.exists(SCRIPTS_LOG):
os.makedirs(SCRIPTS_LOG)
with open(log, "w") as output:
cmd = ["nohup", "python", script, db]
p = subprocess.Popen(cmd, stdout=output)
return jobid, p.pid, " ".join(cmd)
和我的child.py
#!/usr/bin/env python
import time
import os, sys
if 'TEST_ENV' not in os.environ:
os.environ['TEST_ENV'] = 'Set some env'
try:
os.execv(sys.argv[0], sys.argv)
except Exception, exc:
print "Failed re-exec:", exc
sys.exit(1)
def main(argv):
db = argv[0]
while True:
print 'Running child with params ', db
time.sleep(1)
if __name__ == '__main__':
main(sys.argv[1:])
我添加了一个简单的脚本来证明这一点。 https://github.com/shulhi/kill-pid/tree/master
答案 0 :(得分:0)
终止正在运行的进程需要时间。在这种情况下,它是一个子进程,因此os.wait()
或其中一个变体将准确知道等待多长时间。为了面向未来,请使用os.waitpid(pid, os.WEXITED)
。