Debugging Django: Using Flickzeug

It came to my attention that some people haven't realized you can use the excellent Pocoo creation known as Flickzeug with a Django project.

Flickzeug lets you find memory leaks, generate profiling data, look at that same data and is pretty awesome in general.

Step one is to make a new manage.py. Obviously, you won't be able to use that same name in a Django project, as Django already uses it. Choose on of your liking. I myself don't use Django's manage.py and so replace it.

from werkzeug import script

if __name__ == "__main__":
    script.run()

The above is a bare-bones skeleton of making your own management script using the Werkzeug helper system.

At this point, you'll need to run a Django project as a mere mortal WSGI application. Fortunately, this is relatively simple.

from werkzeug import script
from django.core.handlers.wsgi import WSGIHandler

application = WSGIHandler()

if __name__ == "__main__":
    script.run()

An issue with this, however, is that Django requires you to set up your environment before importing anything non-trivial from within Django. This is one of the... "design choices" that convinced me of the backwardness of Django, but I digress.

So, to take this into account, we have to set the Django settings module environment variable first, and also make sure our project is importable.

import sys
import os
from werkzeug import script
from django.core.handlers.wsgi import WSGIHandler

sys.path.insert(0, os.path.dirname(__file__))
os.environ["DJANGO_SETTINGS_MODULE"] = "foo.settings"

application = WSGIHandler()

if __name__ == "__main__":
    script.run()

There, now that we have our application, we can make a simple Werkzeug runserver — which, by the way, is much more light-weight and nicer to work with than Django's.

To do this, we define a variable called action_runserver, as Werkzeug's script module looks for action_* variable names.

import sys
import os
from werkzeug import script
from django.core.handlers.wsgi import WSGIHandler

sys.path.insert(0, os.path.dirname(__file__))
os.environ["DJANGO_SETTINGS_MODULE"] = "foo.settings"

application = WSGIHandler()

action_runserver = script.make_runserver(lambda: application,
    use_reloader=True, use_debugger=True)

if __name__ == "__main__":
    script.run()

There, we've got our first management command. Try it out! python new-manage.py runserver should do the trick. Pass -h for help.

On to the Flickzeug part then. Flickzeug works as a WSGI middleware, that is to say, you wrap a WSGI application in Flickzeug, and the application gains the functionality desired.

import sys
import os
from werkzeug import script
from django.core.handlers.wsgi import WSGIHandler

sys.path.insert(0, os.path.dirname(__file__))
os.environ["DJANGO_SETTINGS_MODULE"] = "foo.settings"

application = WSGIHandler()

def make_leakfinder():
    from flickzeug import LeakFinder
    filter = lambda v: (not v.startswith("foo.")
                    and not v.startswith("bar."))
    return LeakFinder(application, filter=filter)

action_runserver = script.make_runserver(lambda: application,
    use_reloader=True, use_debugger=True)
action_runserver_leakfinder = script.make_runserver(make_leakfinder,
    use_reloader=True, use_debugger=True)

if __name__ == "__main__":
    script.run()

So what we did was pass a different callable to make_runserver, which returns a Flickzeug-wrapped version of our application instead.

The Flickzeug LeakFinder optionally takes a filter argument, which I find very useful indeed to filter out the noise made by Django and any other third-party component you mightn't necessarily be interested in.

The same approach can be used for any other part of Flickzeug, or indeed any other WSGI middleware you might want to use.

Also, now that you have the skeleton for making a Werkzeug-based management script, you should probably look into the werkzeug.script module: http://werkzeug.pocoo.org/documentation/0.5.1/script.html


Comments
Posted by: Pradeep Gowda §

A typo:
from django.core.handlers.wsgi import WSGIhandler
should read
from django.core.handlers.wsgi import WSGIHandler
[uppercase H in WSGIHandler]

2010-01-08 @ 02:35:42
URL: http://pradeepgowda.com
Posted by: §

Thanks for spotting that, Pradeep.

2010-01-08 @ 11:51:26
Posted by: Bernhard §

Nice I'm working currently on Debugging Django: Using Flickzeug so this helps me.

2011-03-29 @ 15:15:45
URL: http://jagdmode.com

Comment the entry:

Name: (required, possibly pseudonym)
Remember me (cookie)

E-mail: (not required, never published, solely for me to reply to you in person)

URL:

Comment:

RSS 2.0