Flask + gevent:未处理Process实例中的日志记录事件

时间:2014-06-22 02:22:03

标签: python flask multiprocessing gevent

我想在我的应用程序中实现服务器端事件。我正在使用带有gevent后端的Flask。我主要遵循官方snippet,有两个重要的区别:

  1. 触发事件的函数作为单独的进程(multiprocessing.Process的实例)生成,而不是gevent.spawn。它发送"内部"事件
  2. 事件触发是通过记录完成的,QueueHandler来自logutils
  3. 这是一个最小的例子:

    from flask import Flask, Response
    import time
    import logging
    from gevent.wsgi import WSGIServer
    from gevent.queue import Queue
    import multiprocessing as mp
    from logutils.queue import QueueHandler
    
    app = Flask(__name__)
    logger = logging.getLogger('events')
    logger.setLevel(logging.INFO)
    
    @app.route("/publish")
    def publish():
        logger = logging.getLogger('events')
        def notify():
            time.sleep(1)
            logger.info('inner')
    
        logger.info('outer')
        p = mp.Process(target=notify)
        p.start()
        return "OK"
    
    @app.route("/subscribe")
    def subscribe():
        def gen():
            logger = logging.getLogger("events")
            q = Queue()
            handler = QueueHandler(q)
            logger.addHandler(handler)
    
            while True:
                result = q.get().message
                yield result
    
        return Response(gen(), mimetype="text/event-stream")
    
    if __name__ == "__main__":
        root = logging.getLogger()
        root.addHandler(logging.StreamHandler())
        root.setLevel(logging.INFO)
    
        app.debug = True
        server = WSGIServer(("", 5000), app)
        server.serve_forever()
    

    问题是,StreamHandler同时捕获"内部"和"外部"事件并将它们记录到stdout。另一方面,QueueHandler仅推动"外部"事件到队列,所以它无法捕捉"内部"事件,起源于其他过程。

    现在,如果我使用multiprocessing.Queue代替gevent.queue,那么" / subscribe"路线块。如果我将标准werkzeug服务器(带有线程)与multiprocessing.Queue结合使用,则上面的代码按预期工作。

    发生了什么以及如何解决这个问题?

0 个答案:

没有答案