![](/img/trans.png)
[英]Exception gevent.hub.LoopExit: LoopExit('This operation would block forever',)
[英]gevent.hub.LoopExit exception on flask SSE example
我正在尝试运行从http://flask.pocoo.org/snippets/116/复制的以下示例:
# author: oskar.blom@gmail.com
#
# Make sure your gevent version is >= 1.0
import gevent
from gevent.wsgi import WSGIServer
from gevent.queue import Queue
from flask import Flask, Response
import time
# SSE "protocol" is described here: http://mzl.la/UPFyxY
class ServerSentEvent(object):
def __init__(self, data):
self.data = data
self.event = None
self.id = None
self.desc_map = {
self.data : "data",
self.event : "event",
self.id : "id"
}
def encode(self):
if not self.data:
return ""
lines = ["%s: %s" % (v, k)
for k, v in self.desc_map.iteritems() if k]
return "%s\n\n" % "\n".join(lines)
app = Flask(__name__)
subscriptions = []
# 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("/debug")
def debug():
return "Currently %d subscriptions" % len(subscriptions)
@app.route("/publish")
def publish():
#Dummy data - pick up from request for real data
def notify():
msg = str(time.time())
for sub in subscriptions[:]:
sub.put(msg)
gevent.spawn(notify)
return "OK"
@app.route("/subscribe")
def subscribe():
def gen():
q = Queue()
subscriptions.append(q)
try:
while True:
result = q.get()
ev = ServerSentEvent(str(result))
yield ev.encode()
except GeneratorExit: # Or maybe use flask signals
subscriptions.remove(q)
return Response(gen(), mimetype="text/event-stream")
if __name__ == "__main__":
app.debug = True
server = WSGIServer(("", 5000), app)
server.serve_forever()
# Then visit http://localhost:5000 to subscribe
# and send messages by visiting http://localhost:5000/publish
我运行了env FLASK_APP=stream.py flask run
服务器,服务器正常启动。 但是,当我如上所述尝试使用Web浏览器连接到服务器时,出现以下错误:
127.0.0.1 - - [27/May/2018 21:37:49] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [27/May/2018 21:37:49] "GET /subscribe HTTP/1.1" 500 -
Error on request:
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/werkzeug/serving.py", line 209, in run_wsgi
execute(self.server.app)
File "/usr/lib/python2.7/site-packages/werkzeug/serving.py", line 199, in execute
for data in application_iter:
File "/usr/lib/python2.7/site-packages/werkzeug/wsgi.py", line 704, in __next__
return self._next()
File "/usr/lib/python2.7/site-packages/werkzeug/wrappers.py", line 81, in _iter_encoded
for item in iterable:
File "/home/dov/git/learning/flask/stream/stream.py", line 88, in gen
result = q.get()
File "/usr/lib64/python2.7/site-packages/gevent/queue.py", line 283, in get
return self.__get_or_peek(self._get, block, timeout)
File "/usr/lib64/python2.7/site-packages/gevent/queue.py", line 260, in __get_or_peek
result = waiter.get()
File "/usr/lib64/python2.7/site-packages/gevent/hub.py", line 898, in get
return self.hub.switch()
File "/usr/lib64/python2.7/site-packages/gevent/hub.py", line 630, in switch
return RawGreenlet.switch(self)
LoopExit: ('This operation would block forever', <Hub at 0x7f434fb2daf0 epoll default pending=0>)
什么地方出了错? 是否需要提前将publish
例程声明为greenlet? 我缺少什么(以及pocoo代码段)?
我找到了一个解决方案,它与用于提供上述代码段的Web服务器有关。 flask run
提供的服务器不起作用。 到目前为止,我发现可以为上述应用程序提供服务的唯一服务器是gunicorn,如下所示:
gunicorn sse:app --worker-class gevent --bind 127.0.0.1:5000
这很棒! (不幸的是,它只能解决一半的问题,因为我想在Windows上运行服务器,但不支持gunicorn。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.