Пересмешивание REST API с помощью Flask_restful с использованием потоков - PullRequest
0 голосов
/ 05 июня 2019

Я пытаюсь смоделировать набор 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()

Без вызова sleep() в цикле while выше ничего не разрешается. Вот более краткое использование для демонстрации:

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 голосов
/ 05 июня 2019

Обнаружил, что если я отключу threading для multiprocessingthreading.Thread для multiprocessing.Process), все будет работать как положено, и я могу раскрутить произвольное количество насмешников без блокировки.

...