我有 Flask 应用程序,它暴露了可以在后台运行应用程序的 API,并且可以稍后通过指定 PID 来终止它。但是,出于单元测试的目的,在杀死 PID 并检查 PID 是否被杀死后,psutil.pid_exists(pid)
它似乎总是返回 true。我手动检查了 PID 不存在并psutil.pid_exists(pid)
在不同的 python 控制台上运行,它返回 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