You can create a special file-like object that feeds the generator that streams out to the client. Here is a quick & dirty implementation using a queue:
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
This is nothing more than a pub-sub type queue. The read()
method will block until there is something written in another thread.
Now you can stream a response using a generator. The following example shows a generator that takes the serialization function as an argument. The serialization function is executed in a background thread and receives the file-like object as an argument.
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
I hope this helps!