Pylons tip #5 - Streaming static files

November 04, 2009 at 07:15 PM | categories: Technical, Python | View Comments |

Pylons makes it super easy to return data to a client. You just return a string from your controller method!

class HelloController(BaseController):

    def index(self):
        return 'Hello World!'

Very nice. However, what if you want to serve up a potentially quite large file to the client? Sure, you could read the file into memory, and then return the entire buffer, but that is not very efficient. If you have a multi-megabyte file, you end up wasting lots of memory. What you want to do, actually, is read a chunk of the file at a time, and then send that. So instead of reading the entire file into memory and returning it in a single go, you do lots of little chunks. Simple conceptually. How do you do this in Pylons? Thankfully you can do this with a Python generator. Instead of returning a buffer, you return a generator:
class ImageController(BaseController):

    def index(self, id):
        ''' Stream local image contents to client '''
        try:
            imgf = open("%s/%s" %(config['image_data_dir'],
                os.path.basename(id)), 'r')
        except IOError:
            abort(404)
        def stream_img():
            chunk = imgf.read(1024)
            while chunk:
                yield chunk
                chunk = imgf.read(1024)
            imgf.close()
        return stream_img()
This works quite nicely. Hope that helps!

Niall O'Higgins is an author and software developer. He wrote the O'Reilly book MongoDB and Python. He also develops Strider Open Source Continuous Deployment and offers full-stack consulting services at FrozenRidge.co.

blog comments powered by Disqus