在wsgi上为多个进程共享变量

时间:2018-12-15 20:48:46

标签: python rest flask mod-wsgi

我是不熟悉烧瓶-wsgi-一般的API。我想编写API以多次启动一个进程并获取当前状态。另外,基于首次运行时间,我想估算总时间。我想将其部署到wsgi服务器。

我按照these的说明将flask应用程序部署到wsgi服务器。虽然,我需要python3.6时使用python mod_wsgi。

该代码在多线程环境中工作正常,但在多处理环境中无法共享变量。据我了解,wsgi是一个多处理环境。我尝试使用multiprocessing Manager,但无济于事。

我的API代码

from flask import Flask, request, session, copy_current_request_context
from json import dumps
import requests
from threading import Thread as thread
from flask_session import Session
import logging
import time

from multiprocessing import Manager, Process

app = Flask(__name__)

#sess = Session()
#app.secret_key = 'THISISASECRETKEY'
#app.config['SESSION_TYPE'] = 'null'
#sess.init_app(app)
#app.debug =True

logger = logging.getLogger('Gen API Logger')
logger.setLevel(logging.DEBUG)
fh = logging.FileHandler("/tmp/api.log")
formatter = logging.Formatter('%(process)d %(threadName)s - %(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
logger.addHandler(fh)

man = Manager()
st_dict = man.dict()
cnt = man.Value('i',-1)

time_per_run = []

st_dict['status'] = 'notstarted'
print(f"State of run dict is {st_dict.get('status')}")

class Main:
    def __init__(self):
        self.g = -1
        self.runs = 5

    def run(self):
        st_dict['status'] = 'running'
        for g in range(self.runs):
            self.g = g
            cnt.value = g
            time.sleep(30)
        return 1

m = Main()

def run_running():
    running_done = m.run()
    st_dict['status'] = 'finished'

@app.route('/start-running',methods=['GET'])
def api_start():
    try:
        global time_per_run, startTime
        logger.info('Got request for start running.')
        if st_dict.get('status') == 'running':
            msg = {"success":"running already started"}
            logger.info(f'Start running responded with response: {msg}')
            return dumps(msg)
        startTime = time.time()
        start_time = time.time()
        try:
            logger.debug(f"Value of run status before starting thread: {st_dict.get('status')}")
            #thread(target=run_running).start()
            Process(target=run_running).start()
            st_dict['status'] = 'started'
            logger.debug(f"Value of run status after starting thread: {st_dict.get('status')}")
        except Exception as e:
            logger.error(f"Error while starting thread: {e}")
            raise Exception(e)

        while cnt.get() < 1:
            logger.debug(f"Value of cnt: {cnt.get()}")
            time.sleep(10)
            msg = {"success":"true"}
        time_per_run = time.time() - start_time
        logger.debug(f"Value of run status after finishing first run: {st_dict.get('status')}")

    except Exception as e:
        msg = {"error":str(e)}

    logger.info(f'Start running responded with response: {msg}')
    return dumps(msg)


@app.route('/running-status',methods=['GET'])
def api_running_status():
    logger.info('Got request for running status.')
    logger.debug(f"Value of run status in running-status: {st_dict.get('status')}")
    try:
        if st_dict.get('status') != 'notstarted':
            if st_dict.get('status') == 'started':
                msg = {"timeLeft":"calculating"}
            else:
                if st_dict.get('status') == 'running':
                    time_left = ((m.runs) * time_per_run / float(cnt.get())) - time_per_run
                    time_left = time_left if time_left >= 0 else 0
                    msg = {"timeLeft":str(int(time_left))}
                else:
                    msg = {"timeLeft":"0"}
                    st_dict['status'] = 'finished'
        else:
            msg = {"error":"running has not yet started"}
    except Exception as e:
        msg = {"error":str(e)}
    logger.info(f'Running status responded with response: {msg}')
    return dumps(msg)

if __name__ == "__main__":
    #app.config.from_object(__name__)
    app.config['SESSION_TYPE'] = 'memcache'
    #sess.init_app(app)
    app.debug =True
    app.run(threaded=False,processes=5)
    #app.run(threaded=True)

以下是演示代码以对其进行测试:

import requests
import time

gen_url = 'http://127.0.0.1:5000'

run_resp = requests.get(f'{gen_url}/running-status')
print(f'Running status response {run_resp.content}')

if run_resp.json()['error'] == 'running has not yet started':

    tr_resp = requests.get(f'{gen_url}/start-running')
    print(f"Running response: {tr_resp.content}")

    run_resp = requests.get(f'{gen_url}/running-status')
    print(f'Running status response {run_resp.content}')

    while(requests.get(f'{gen_url}/running-status').json()['timeLeft'] != '0'):
        print("Entered while")
        time.sleep(10)
    print("While exited")

在线程环境中正确运行时的日志:

4222 Thread-2 - 2018-12-15 12:12:44,265 - Gen API Logger - INFO - Got request for running status.
4222 Thread-2 - 2018-12-15 12:12:44,267 - Gen API Logger - DEBUG - Value of run status in running-status: notstarted
4222 Thread-2 - 2018-12-15 12:12:44,267 - Gen API Logger - INFO - Running status responded with response: {'error': 'running has not yet started'}
4222 Thread-3 - 2018-12-15 12:12:44,273 - Gen API Logger - INFO - Got request for start running.
4222 Thread-3 - 2018-12-15 12:12:44,275 - Gen API Logger - DEBUG - Value of run status before starting thread: notstarted
4222 Thread-3 - 2018-12-15 12:12:44,278 - Gen API Logger - DEBUG - Value of run status after starting thread: started
4222 Thread-3 - 2018-12-15 12:12:44,279 - Gen API Logger - DEBUG - Value of cnt: -1
4222 Thread-3 - 2018-12-15 12:12:54,289 - Gen API Logger - DEBUG - Value of cnt: 0
4222 Thread-3 - 2018-12-15 12:13:04,300 - Gen API Logger - DEBUG - Value of cnt: 0
4222 Thread-3 - 2018-12-15 12:13:14,311 - Gen API Logger - DEBUG - Value of cnt: 0
4222 Thread-3 - 2018-12-15 12:13:24,323 - Gen API Logger - DEBUG - Value of run status after finishing first run: running
4222 Thread-3 - 2018-12-15 12:13:24,323 - Gen API Logger - INFO - Start running responded with response: {'success': 'true'}
4222 Thread-4 - 2018-12-15 12:13:24,333 - Gen API Logger - INFO - Got request for running status.
4222 Thread-4 - 2018-12-15 12:13:24,336 - Gen API Logger - DEBUG - Value of run status in running-status: running
4222 Thread-4 - 2018-12-15 12:13:24,337 - Gen API Logger - INFO - Running status responded with response: {'timeLeft': '160'}
4222 Thread-5 - 2018-12-15 12:13:24,344 - Gen API Logger - INFO - Got request for running status.
4222 Thread-5 - 2018-12-15 12:13:24,346 - Gen API Logger - DEBUG - Value of run status in running-status: running
4222 Thread-5 - 2018-12-15 12:13:24,346 - Gen API Logger - INFO - Running status responded with response: {'timeLeft': '160'}
4222 Thread-6 - 2018-12-15 12:13:34,363 - Gen API Logger - INFO - Got request for running status.
4222 Thread-6 - 2018-12-15 12:13:34,365 - Gen API Logger - DEBUG - Value of run status in running-status: running
4222 Thread-6 - 2018-12-15 12:13:34,366 - Gen API Logger - INFO - Running status responded with response: {'timeLeft': '160'}
4222 Thread-7 - 2018-12-15 12:13:44,378 - Gen API Logger - INFO - Got request for running status.
4222 Thread-7 - 2018-12-15 12:13:44,381 - Gen API Logger - DEBUG - Value of run status in running-status: running
4222 Thread-7 - 2018-12-15 12:13:44,382 - Gen API Logger - INFO - Running status responded with response: {'timeLeft': '60'}
4222 Thread-8 - 2018-12-15 12:13:54,400 - Gen API Logger - INFO - Got request for running status.
4222 Thread-8 - 2018-12-15 12:13:54,402 - Gen API Logger - DEBUG - Value of run status in running-status: running
4222 Thread-8 - 2018-12-15 12:13:54,403 - Gen API Logger - INFO - Running status responded with response: {'timeLeft': '60'}
4222 Thread-9 - 2018-12-15 12:14:04,418 - Gen API Logger - INFO - Got request for running status.
4222 Thread-9 - 2018-12-15 12:14:04,421 - Gen API Logger - DEBUG - Value of run status in running-status: running
4222 Thread-9 - 2018-12-15 12:14:04,422 - Gen API Logger - INFO - Running status responded with response: {'timeLeft': '60'}
4222 Thread-10 - 2018-12-15 12:14:14,439 - Gen API Logger - INFO - Got request for running status.
4222 Thread-10 - 2018-12-15 12:14:14,442 - Gen API Logger - DEBUG - Value of run status in running-status: running
4222 Thread-10 - 2018-12-15 12:14:14,443 - Gen API Logger - INFO - Running status responded with response: {'timeLeft': '26'}
4222 Thread-11 - 2018-12-15 12:14:24,461 - Gen API Logger - INFO - Got request for running status.
4222 Thread-11 - 2018-12-15 12:14:24,463 - Gen API Logger - DEBUG - Value of run status in running-status: running
4222 Thread-11 - 2018-12-15 12:14:24,465 - Gen API Logger - INFO - Running status responded with response: {'timeLeft': '26'}
4222 Thread-12 - 2018-12-15 12:14:34,483 - Gen API Logger - INFO - Got request for running status.
4222 Thread-12 - 2018-12-15 12:14:34,485 - Gen API Logger - DEBUG - Value of run status in running-status: running
4222 Thread-12 - 2018-12-15 12:14:34,487 - Gen API Logger - INFO - Running status responded with response: {'timeLeft': '26'}
4222 Thread-13 - 2018-12-15 12:14:44,504 - Gen API Logger - INFO - Got request for running status.
4222 Thread-13 - 2018-12-15 12:14:44,507 - Gen API Logger - DEBUG - Value of run status in running-status: running
4222 Thread-13 - 2018-12-15 12:14:44,508 - Gen API Logger - INFO - Running status responded with response: {'timeLeft': '10'}
4222 Thread-14 - 2018-12-15 12:14:54,526 - Gen API Logger - INFO - Got request for running status.
4222 Thread-14 - 2018-12-15 12:14:54,529 - Gen API Logger - DEBUG - Value of run status in running-status: running
4222 Thread-14 - 2018-12-15 12:14:54,530 - Gen API Logger - INFO - Running status responded with response: {'timeLeft': '10'}
4222 Thread-15 - 2018-12-15 12:15:04,544 - Gen API Logger - INFO - Got request for running status.
4222 Thread-15 - 2018-12-15 12:15:04,547 - Gen API Logger - DEBUG - Value of run status in running-status: running
4222 Thread-15 - 2018-12-15 12:15:04,548 - Gen API Logger - INFO - Running status responded with response: {'timeLeft': '10'}
4222 Thread-16 - 2018-12-15 12:15:14,566 - Gen API Logger - INFO - Got request for running status.
4222 Thread-16 - 2018-12-15 12:15:14,568 - Gen API Logger - DEBUG - Value of run status in running-status: finished
4222 Thread-16 - 2018-12-15 12:15:14,570 - Gen API Logger - INFO - Running status responded with response: {'timeLeft': '0'}

在失败的多进程环境中记录日志:

5029 Thread-1 - 2018-12-15 12:29:04,487 - Gen API Logger - INFO - Got request for running status.
5029 Thread-1 - 2018-12-15 12:29:04,490 - Gen API Logger - DEBUG - Value of run status in running-status: notstarted
5029 Thread-1 - 2018-12-15 12:29:04,490 - Gen API Logger - INFO - Running status responded with response: {'error': 'running has not yet started'}
5031 Thread-1 - 2018-12-15 12:29:04,501 - Gen API Logger - INFO - Got request for start running.
5031 Thread-1 - 2018-12-15 12:29:04,505 - Gen API Logger - DEBUG - Value of run status before starting thread: notstarted
5031 Thread-1 - 2018-12-15 12:29:04,509 - Gen API Logger - DEBUG - Value of run status after starting thread: started
5031 Thread-1 - 2018-12-15 12:29:04,510 - Gen API Logger - DEBUG - Value of cnt: -1
5031 Thread-1 - 2018-12-15 12:29:14,521 - Gen API Logger - DEBUG - Value of cnt: 0
5031 Thread-1 - 2018-12-15 12:29:24,532 - Gen API Logger - DEBUG - Value of cnt: 0
5031 Thread-1 - 2018-12-15 12:29:34,543 - Gen API Logger - DEBUG - Value of cnt: 0
5031 Thread-1 - 2018-12-15 12:29:44,555 - Gen API Logger - DEBUG - Value of run status after finishing first run: running
5031 Thread-1 - 2018-12-15 12:29:44,555 - Gen API Logger - INFO - Start running responded with response: {'success': 'true'}
5071 Thread-1 - 2018-12-15 12:29:44,571 - Gen API Logger - INFO - Got request for running status.
5071 Thread-1 - 2018-12-15 12:29:44,573 - Gen API Logger - DEBUG - Value of run status in running-status: running
5071 Thread-1 - 2018-12-15 12:29:44,573 - Gen API Logger - INFO - Running status responded with response: {'error': "unsupported operand type(s) for /: 'list' and 'float'"}
5073 Thread-1 - 2018-12-15 12:29:44,584 - Gen API Logger - INFO - Got request for running status.
5073 Thread-1 - 2018-12-15 12:29:44,588 - Gen API Logger - DEBUG - Value of run status in running-status: running
5073 Thread-1 - 2018-12-15 12:29:44,589 - Gen API Logger - INFO - Running status responded with response: {'error': "unsupported operand type(s) for /: 'list' and 'float'"}

如何在多个请求中正确共享st_dict的值?

EDIT1: 我还尝试按照建议的here使用flask的会话。但是结果是相似的。有时,主线程将处理该请求,从而将st_dict重置为默认值。

0 个答案:

没有答案