使用线程模拟Flask_restful的REST API

时间:2019-06-05 14:49:17

标签: python-3.x flask python-multithreading gevent flask-restful

我正在为一组测试模拟一组REST API。以下main()函数可以正常工作(即,当我获取{"some-data": 1234}时,它以json的形式返回localhost:8099到浏览器)。问题在于它阻塞了主线程:

from gevent import monkey, sleep, pywsgi
monkey.patch_all()

import flask
from flask_restful import reqparse, abort, Api, Resource
import queue
import sys
import threading

STUFFS = {"some-data": 1234}

class Stuff(Resource):
    def get(self):
        return flask.jsonify(STUFFS)


class ControlThread(threading.Thread):
    def __init__(self, http_server, stop_event):
        threading.Thread.__init__(self)
        self.stop_event = stop_event
        self.http_server = http_server
        self.running = False

    def run(self):
        try:
            while not self.stop_event.is_set():
                if not self.running:
                    self.http_server.start()
                    self.running = True
                sleep(0.001)
        except (KeyboardInterrupt, SystemExit):
            pass
        self.http_server.stop()


class StuffMock:
    def __init__(self, port, name=None):
        if name is None:
            name = __name__
        self.app = flask.Flask(name)
        self.api = Api(self.app)
        self.api.add_resource(Stuff, "/stuff/")

        self.stop_event = threading.Event()
        self.http_server = pywsgi.WSGIServer(('', port), self.app)

        self.serving_thread = ControlThread(self.http_server,
                                            self.stop_event)
        self.serving_thread.daemon = True

    def start(self):
        self.serving_thread.start()

    def stop(self):
        self.stop_event.set()
        self.serving_thread.join()


def main():
    mocker = StuffMock(8099)
    mocker.start()
    try:
        while True:
            sleep(0.01)
    except (KeyboardInterrupt, SystemExit):
        mocker.stop()
        sys.exit()

if __name__ == "__main__":
    main()

在上面的while循环中没有sleep()调用,没有任何解决。这是一个更简洁的用法来演示:

import time

from stuff_mock import StuffMock

mocker = StuffMock(8099)
mocker.start()

while True:
    user_text = input("let's do some work on the main thread: ")
    # will only resolve the GET request after user input
    # (i.e. when the main thread executes this sleep call)
    time.sleep(0.1)
    if user_text == "q":
        break
mocker.stop()

gevent threading模块的工作方式似乎不同于核心模块。有人对引擎盖下发生的事情有任何提示或想法吗?

1 个答案:

答案 0 :(得分:0)

发现,如果我将threading的{​​{1}}切换为multiprocessing的{​​{1}},一切都会按预期进行,并且我可以启动任意数量的嘲笑者而无需封锁。