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
A typo:
from django.core.handlers.wsgi import WSGIhandler
should read
from django.core.handlers.wsgi import WSGIHandler
[uppercase H in WSGIHandler]
Thanks for spotting that, Pradeep.
Nice I'm working currently on Debugging Django: Using Flickzeug so this helps me.
