我正在尝试构建一个Flask应用程序,它在后台运行一些任务。这个任务(worker)使用标准的logging
模块记录正在发生的事情。我想使用服务器发送的事件将日志消息直接推送到web浏览器,但我无法让gevent
广播它们。在
在下面的代码片段中,worker被正确地启动,SSEHandler.emit
方法被调用,但是notify
函数在我执行gevent.spawn
之后似乎没有执行。在
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()
问题是我用了普通的线程和睡眠来代替gevent。在改变它和/或应用一个猴子补丁后,一切都是完美的。在
相关问题 更多 >
编程相关推荐