后台线程记录到服务器在Flask应用程序中发送事件流

2024-05-20 01:07:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试构建一个Flask应用程序,它在后台运行一些任务。这个任务(worker)使用标准的logging模块记录正在发生的事情。我想使用服务器发送的事件将日志消息直接推送到web浏览器,但我无法让gevent广播它们。在

在下面的代码片段中,worker被正确地启动,SSEHandler.emit方法被调用,但是notify函数在我执行gevent.spawn之后似乎没有执行。在

在主.py在

import gevent
from gevent.wsgi import WSGIServer
from gevent.queue import Queue

from flask import Flask, Response

import time
import logging
import threading
from worker import Worker

class SSEHandler(logging.Handler):

    def __init__(self):
        logging.Handler.__init__(self)        
        self.subscriptions = []

    def emit(self, record):
        try:
            msg = self.format(record)
            print "sending", msg
            def notify(subs, msg):
                print "broadcasting!"
                for sub in subs[:]:
                    sub.put(msg)

            gevent.spawn(notify, self.subscriptions, msg)

        except (keyboardInterrupt, SystemExit):
            raise
        except:
            self.handleError(record)

    def subscribe(self):
        print "subscribed"
        q = Queue()
        self.subscriptions.append(q)
        try:
            while True:
                result = q.get()
                yield "data: %s\n\n"%result
        except GeneratorExit: # Or maybe use flask signals
            subscriptions.remove(q)



app = Flask(__name__)
handler = SSEHandler()
handler.setLevel(logging.DEBUG)
worker = None

# Client code consumes like this.
@app.route("/")
def index():
    debug_template = """
     <html>
       <head>
       </head>
       <body>
         <h1>Server sent events</h1>
         <div id="event"></div>
         <script type="text/javascript">

         var eventOutputContainer = document.getElementById("event");
         var evtSrc = new EventSource("/subscribe");

         evtSrc.onmessage = function(e) {
             console.log(e.data);
             eventOutputContainer.innerHTML = e.data;
         };

         </script>
       </body>
     </html>
    """
    return(debug_template)


@app.route("/subscribe")
def subscribe():
    return Response(handler.subscribe(), mimetype="text/event-stream")

@app.route("/start")
def start():
    def run():
        global worker
        global handler
        worker = Worker(handler)
        worker.go()

    threading.Thread(target=run).start()
    return "Going"

if __name__ == "__main__":
    app.debug = True
    server = WSGIServer(("", 5000), app)
    server.serve_forever()

在工人.py在

^{pr2}$

Tags: fromimportselfappflaskloggingdefsubscriptions