1. Problem

Usually the response from a handler function is returned as a string, which means that the whole response has to be constructed in memory. If you want to return a very large file, however, this will consume a lot of memory.

2. Solution

Instead of returning a string, a handler can also return an instance of the quixote.http_response.Stream class, wrapping it around an iterable that returns chunks of the large object.

from quixote.http_response import Stream

def generate_data ():
    "Generate a large amount of data"
    while (...):
        yield chunk

def data_output (request):
    # Set the MIME type to whatever is suitable
    request.response_set_content_type('application/octet-stream')
    return Stream(generate_data())

For the common case of streaming output from a file, the quixote.util modules contains a FileStream class that takes a file object:

def large_file (request):
    filename = "/usr/share/qxapp/large-file.pdf'
    size = os.path.getsize(filename)
    request.response.set_content_type('application/pdf')
    input = open(filename, 'rb')
    return util.FileStream(input, size)

The size argument is optional and is used to set the Content-Length HTTP header; you should provide it whenever possible.

3. Discussion

Note that not all Quixote publishers support streaming. Most notably, for Quixote <= 1.0b1 the quixote.server.twisted_http module simply converts the contents of the stream into an in-memory string.


CategoryCookbook