python - 为什么我的生成器阻止 Flask 发送 SSE 响应?

标签 python flask generator

我正在尝试使用 Flask 来处理 SSE 请求,但我的客户端仅在我的生成器函数停止/连接关闭后才收到事件。

这是我能够制作的最简单的复制品来证明这一点:

#!/usr/bin/env python

from flask import Flask, Response
from time import sleep

def stream():
    n = 10
    while n > 0:
        yield "data: hi\n\n"
        sleep(0.5)
        n = n - 1

app = Flask(__name__)

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

app.run(debug=True, threaded=True)

这是我的测试客户端:

<!doctype html>
<html>
<head>
    <script>
        var source = new EventSource(
            "/events"
        );
        source.onmessage = function(event)
        {
            console.log(event);
        };
    </script>
</head>
<body>
</body>
</html>

stream() 生成器将生成十个事件,然后返回(我故意这样做是为了演示问题,理想情况下生成器将永远继续运行),此时连接将被断开。客户端页面在此之前不会记录任何内容,然后它会输出所有十个事件(如果我在stream() 中没有计数器变量,则该页面永远不会收到任何事件)。

我没有大量使用 Python 或 Flask,这让我非常困惑,我看不出我所做的事情与网络上的其他示例有何不同。非常感谢任何帮助。

最佳答案

有两件事可能会干扰:

  1. 您已将 debug 设置为 True,这会安装可能会中断流式传输的中间件(特别是 Werkzeug debugger )。

    来自Flask streaming patterns documentation :

    Note though that some WSGI middlewares might break streaming, so be careful there in debug environments with profilers and other things you might have enabled.

    但是,在使用 Flask 0.10.1 和 Werkzeug 0.9.4 的测试代码上使用 curl 或 Chrome 时,我看到 data: hi 响应正确地流式传输,无论 debug 标志设置如何。换句话说,您的代码可以在最新版本的 Flask 堆栈中正常工作。

  2. EventSource 流受 same-origin policy 的约束限制。如果您没有从同一主机和端口加载 HTML 页面,则对 Flask 服务器的请求将被拒绝。

    在 Flask 服务器中的单独路径中添加测试页面源对我来说很有效:

    @app.route('/')
    def index():
        return '''\
    <!doctype html>
    <html>
    <head>
        <script>
            var source = new EventSource(
                "/events"
            );
            source.onmessage = function(event)
            {
                console.log(event);
            };
        </script>
    </head>
    <body>
    </body>
    </html>
    '''
    

关于python - 为什么我的生成器阻止 Flask 发送 SSE 响应?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22233191/

相关文章:

Python CSV 读取器/写入器处理引号 : How can I wrap row fields in quotes?(获取三重引号作为输出)

python - 使用Flask通过浏览器加载txt文件并访问其数据进行处理

python - 使用嵌套生成器 pickle 对象

python - 没有名为 Flask (GAE) 的模块

sqlalchemy - Flask SQLAlchemy 显示调试查询

python - 如何使用具有多个输入的 keras 生成序列数据?

c - 素数生成器

python - 在 Pandas DataFrame 中格式化 Float64Index

python - 如何将 XML 转换为字典

python - 如何在 Flask 中处理来自浏览器的 put 请求?