使用来自Python的PID检查进程的状态

问题描述 投票:0回答:1

我用Python编写的REST API产生的过程大约需要3分钟才能完成。我将PID存储在全局数组中,并设置辅助检查方法,该方法应确认进程是否仍在运行或是否已完成。

我唯一能找到的方法是轮询子进程(在此路由中我没有访问权限),或尝试杀死该进程以查看它是否仍在运行。是否有任何干净的方法可以直接获得二进制答案,即它是否仍基于PID运行,如果不是,则成功完成?

from flask import Flask, jsonify, request, Response
from subprocess import Popen, PIPE
import os

app = Flask(__name__)

QUEUE_ID = 0

jobs = []

@app.route("/compile", methods=["POST"])
def compileFirmware():

    f = request.files['file']
    f.save(f.filename)

    os.chdir("/opt/src/2.0.x")

    process = Popen(['platformio', 'run', '-e', 'mega2560'], stdout=PIPE, stderr=PIPE, universal_newlines=True)

    global QUEUE_ID
    QUEUE_ID += 1

    data = {'id':QUEUE_ID, 'pid':process.pid}
    jobs.append(data)

    output, errors = process.communicate()
    print (output)
    print (errors)

    response = jsonify()
    response.status_code = 202 #accepted
    response.headers['location'] = '/queue/' + str(QUEUE_ID)
    response.headers.add('Access-Control-Allow-Origin', '*')
    return response

@app.route("/queue/<id>", methods=["GET"])
def getStatus(id):

    #CHECK PID STATUS HERE

    content = {'download_url': 'download.com'}
    response = jsonify(content)
    response.headers.add('Access-Control-Allow-Origin', '*')
    return response

if __name__ == '__main__':
    app.run(host='0.0.0.0',port=8080)
python rest flask pid flask-restful
1个回答
0
投票

这里有一个模拟的例子:

from flask import Flask, jsonify, request, Response, abort
from subprocess import Popen, PIPE
import os

app = Flask(__name__)

QUEUE = { }

@app.route("/compile", methods=["POST"])
def compileFirmware():
    process = Popen(['python','-c','"import time; time.sleep(300)"'], stdout=PIPE, stderr=PIPE, universal_newlines=True)
    QUEUE[str(process.pid)] = process # String because in GET the url param will be interpreted as str
    response = jsonify()
    response.status_code = 202 #accepted
    response.headers['location'] = '/queue/' + str(process.pid)
    response.headers.add('Access-Control-Allow-Origin', '*')
    return response

@app.route("/queue/<id>", methods=["GET"])
def getStatus(id):
    process = QUEUE.get(id, None)
    if process is None:
        abort(404, description="Process not found")
    retcode = process.poll()
    if retcode is None:
        content = {'download_url': None, 'message': 'Process is still running.'}
    else:
        # QUEUE.pop(id) # Remove reference from QUEUE ?
        content = {'download_url': 'download.com', 'message': f'process has completed with retcode: {retcode}'}
    response = jsonify(content)
    response.headers.add('Access-Control-Allow-Origin', '*')
    return response

if __name__ == '__main__':
    app.run(host='0.0.0.0',port=8080)

如果要将此应用程序用作一个单独的项目,则还必须考虑其他因素。

  • 我们使用QUEUE全局变量存储进程的状态。但是在实际项目中,通过wsgi / gunicorn进行的部署可以有多个工作程序,每个工作程序都有自己的全局变量。因此,要进行扩展,请考虑使用redis / mq数据存储。

  • 是否需要清理队列?应该清理吗?这样做的缺点是,如果在获得GET值一次后将其清除,则下一个GET将获取404。如果GET api必须是幂等的(这很可能是),则是设计决策。

© www.soinside.com 2019 - 2024. All rights reserved.