我有将数据序列化为类文件对象的现有代码:
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/