簡體   English   中英

后台線程記錄到Flask應用中的服務器發送事件流

[英]Background thread logging to a Server Sent Event stream in a Flask app

我正在嘗試構建一個Flask應用程序,該應用程序在后台運行一些任務。 此任務(工作人員)使用標准的logging模塊記錄正在發生的事情。 我想使用Server Sent Events將日志消息直接推送到Web瀏覽器,但是我無法通過gevent廣播gevent

在以下代碼段中,該工作器已正確啟動,應調用SSEHandler.emit方法,但在執行gevent.spawn之后似乎未執行notify函數。

main.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()

worker.py

import logging
import time

class Worker:
    def __init__(self, handler):
        self.log = logging.getLogger('sselog.worker.Worker')
        self.log.setLevel(logging.DEBUG)
        self.log.addHandler(handler)

        self.log.info("Initialized")

    def go(self):
        i = 0
        while True:
            time.sleep(1)
            self.log.info("I'm working so hard %u", i)
            i+=1

好吧,問題是我使用普通線程和睡眠而不是gevent東西。 對其進行更改和/或應用猴子補丁后,一切都將正常運行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM