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 is the co-founder of BeyondFog, Inc which makes Strider Brilliant Continuous Deployment. Strider is a hosted Continuous Integration & Deployment service for Node.JS and Python.

blog comments powered by Disqus