python - Flask:通过写入客户端来流式传输数据?

标签 python flask werkzeug

我有将数据序列化为类文件对象的现有代码:

def some_serialization_function(file):
    file.write(...)

在Flask中,我希望能够将序列化后的数据直接发送给客户端, 无需先将其缓冲在内存中。

我查看了 werkzeug 的 ResponseStreamMixin,但我认为它不能在没有缓冲的情况下工作:

class StreamResponse(flask.Response, werkzeug.wrappers.ResponseStreamMixin):
   pass

@app.route("/data")
def get_data():
   r = StreamResponse()
   some_serialization_function(r.stream) # everything is buffered into memory
   return r # buffered data is sent after return

我发现的所有流数据示例都是基于生成器的,它们以相反的方向工作(即数据是从生成器中“拉出”,而不是通过写入调用“推出”),所以我想知道,有没有办法在 Flask 中直接“写入”客户端?

编辑 - 更清楚一点:我正在寻找一种方法来提供由“some_serialization_function(...)”(我无法轻易更改)生成的数据,而没有让该函数写入所有内容的内存/IO 开销首先将数据写入缓冲区/文件。

(我怀疑临时文件最终会成为解决之道,因为与通过网络实际发送数据的开销相比,IO 开销并不显着。另外我主要关心的是内存开销)。

最佳答案

您可以创建一个特殊的类似文件的对象,该对象为流式传输到客户端的生成器提供数据。这是一个使用队列的快速而肮脏的实现:

from queue import Queue

class StreamWriter(object):
    def __init__(self):
        self.queue = Queue()

    def write(self, str):
        self.queue.put(str)

    def read(self):
        str = self.queue.get()
        self.queue.task_done()
        if str == '~':
            return None
        return str

    def close(self):
        self.write('~')  # indicate EOF

这只不过是一个发布-订阅类型的队列。 read() 方法将阻塞,直到在另一个线程中写入内容。

现在您可以使用生成器流式传输响应。以下示例显示了一个将序列化函数作为参数的生成器。序列化函数在后台线程中执行,并接收类文件对象作为参数。

def generate_response(serialize):
    file = StreamWriter()
    def serialize_task():
        serialize(file)
        file.close()
    threading.Thread(target=serialize_task).start()
    while True:
        chunk = file.read()
        if chunk is None:
            break
        yield chunk

希望对您有所帮助!

关于python - Flask:通过写入客户端来流式传输数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23484491/

相关文章:

caching - 服务器正在提供旧版本的静态文件,但经过修剪或填充以匹配新版本的长度

python - 如何理解flask的这段代码?

Python 数据帧 : Merge values of columns according to a specific condition

python - 在标记自定义迷你格式时正确考虑多个反斜杠

python - 从 Web Flask App 更新 GTK 菜单

twitter-bootstrap - Bootstrap Toggle 避免表单提交

python - 等待值然后停止服务器,在 'werkzeug.server.shutdown' 被弃用并删除之后

python - 无法使用 PySerial 接收回复,但 super 终端有效

python - 如何在 Django 模板中添加注释?

python - Flask 和 SQLAlchemy : No module named 'app' and NameError