The Artima Developer Community
Sponsored Link

Python Buzz Forum
WSGI songlist application: the repoze.bfg take

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Carlos de la Guardia

Posts: 219
Nickname: cguardia
Registered: Jan, 2006

Carlos de la Guardia is an independent web developer in Mexico
WSGI songlist application: the repoze.bfg take Posted: Jan 15, 2009 5:11 AM
Reply to this message Reply

This post originated from an RSS feed registered with Python Buzz by Carlos de la Guardia.
Original Post: WSGI songlist application: the repoze.bfg take
Feed Title: I blog therefore I am
Feed URL: http://blog.delaguardia.com.mx/feed.atom
Feed Description: A space to put my thoughts into writing.
Latest Python Buzz Posts
Latest Python Buzz Posts by Carlos de la Guardia
Latest Posts From I blog therefore I am

Advertisement

Eric Florenzano started an interesting comparison exercise when he showed how easy it is to create simple and fast web applications using pure WSGI.

The main idea was that this kind of application can be a lot faster than fully featured web frameworks can produce, so for machine to machine communication you have a lot to gain by dumping the web framework and using pure WSGI.

After his posting, it was fun to see a good number of web framework advocates post about how the application could be built using their framework and what advantages over pure WSGI it offered. You can see examples of the very simple songlist application that Eric described developed using CherryPY, Restish, Werkzeug and Grok. It's very educational.

I am a little late to the party, but I would like to show how repoze.bfg can do this. repoze.bfg is inspired by Zope and uses its libraries heavily, but does not require you to know anything about that. I think it's a nice little framework and fun to work with, so that's why I decided to do the songlist application with it. By the way, it would be cool to see Django and Pylons examples as well. Any takers?

On to the repoze,bfg application. First, we create a project:

paster create -t bfg_starter songlist

Next, we replace models.py with this code:

from collections import defaultdict

class SongList(object):
def __init__(self): self.songs = defaultdict(int)
root = SongList()
def get_root(environ): return root

And views.py has this content:

from webob import Response
from webob.exc import HTTPMethodNotAllowed

def view_songlist(context, request): res = ','.join(['%s=%s' % (k, v) for k, v in context.songs.iteritems()]) return Response(res)
def clear_songlist(context, request): context.songs.clear() return Response('OK')
def view_song(context, request): song = request.subpath[0] return Response(str(context.songs[song]))
def update_song(context, request): song = request.subpath[0] context.songs[song] += 1 return Response(str(context.songs[song]))
def method_not_allowed(context, request): return HTTPMethodNotAllowed()

Now, if you have that very common ailment know as XML allergy, you will surely hate the part where we connect views with models, but please, don't stop reading yet:

<configure xmlns="http://namespaces.repoze.org/bfg">

  <include package="repoze.bfg.includes" />

  <view
     for="*"
     view=".views.method_not_allowed"
     />

  <view
     for="*"
     request_type="repoze.bfg.interfaces.IGETRequest"
     view=".views.view_songlist"
     />

  <view
     for="*"
     request_type="repoze.bfg.interfaces.IDELETERequest"
     view=".views.clear_songlist"
     />

  <view
     for="*"
     view=".views.view_song"
     request_type="repoze.bfg.interfaces.IGETRequest"
     name="song"
     />

  <view
     for="*"
     view=".views.update_song"
     request_type="repoze.bfg.interfaces.IPOSTRequest"
     name="song"
     /&gt:

</configure>

Yes, repoze.bfg uses Zope's XML configuration language, ZCML. We actually like it, but what would you expect from long time Zope users? We freely admit our minds may be warped.

If you can live with that, you'll see it's not that painful, but if you get truly sick by looking at XML or simply like to hear yourself say 'convention over configuration' every now an then, the repoze.bfg.convention package can keep you away from ZCML. Just have someone edit the ZCML in your project to add these lines:

<include file="meta.zcml" package="repoze.bfg.convention">
  <convention package="." />
</include>

There, now you don't have to even acknowledge the .zcml file is in your project. Just change views.py to look like this:

from webob import Response
from webob.exc import HTTPMethodNotAllowed

from repoze.bfg.interfaces import IGETRequest, IPOSTRequest, IDELETERequest from repoze.bfg.convention import bfg_view
@bfg_view(request_type=IGETRequest) def view_songlist(context, request): res = ','.join(['%s=%s' % (k, v) for k, v in context.songs.iteritems()]) return Response(res)
@bfg_view(request_type=IDELETERequest) def clear_songlist(context, request): context.songs.clear() return Response('OK')
@bfg_view(request_type=IGETRequest, name='song') def view_song(context, request): song = request.subpath[0] return Response(str(context.songs[song]))
@bfg_view(request_type=IPOSTRequest, name='song') def update_song(context, request): song = request.subpath[0] context.songs[song] += 1 return Response(str(context.songs[song]))
@bfg_view() def method_not_allowed(context, request): return HTTPMethodNotAllowed()

See? Decorators to the rescue. Now you wouldn't even suspect the framework was inspired by Zope, but a lot of cool features and libraries taken from Zope are there in case you feel adventurous one day.

One of the key points made by Eric in his songlist post is that pure WSGI applications are fast. Using Spawning, for example, his simple app gets 1230 requests per second on my 1.86 Mhz Intel Core 2 Duo.

Many of the framework songlist posts make the point that with the framework you get a lot of power while losing around half the speed, which is a good trade-off in my opinion. Here's the repoze.bfg benchmark, also using Spawning:

cguardia@hal9000:~$ ab -n 10000 http://localhost:6540/song/1
This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright 2006 The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient) ... Finished 10000 requests
Server Software: Server Hostname: localhost Server Port: 6540
Document Path: /song/1 Document Length: 1 bytes
Concurrency Level: 1 Time taken for tests: 13.857300 seconds Complete requests: 10000 Failed requests: 0 Write errors: 0 Total transferred: 1160000 bytes HTML transferred: 10000 bytes Requests per second: 721.64 [#/sec] (mean) Time per request: 1.386 [ms] (mean) Time per request: 1.386 [ms] (mean, across all concurrent requests) Transfer rate: 81.69 [Kbytes/sec] received

721 requests per second, not too bad. Incidentally, I used Spawning because that was what the majority of benchmarks used in these posts, but I found the paste http server that repoze.bfg uses as default to be much faster. Using that on my machine, pure WSGI gave me 1780 requests per second and repoze.bfg 1060.

Well, I enjoyed making this post. I like to see different Python web frameworks showing how they do things and learning from each other. It's being said a lot this days, but it really is a great time to be a Python web developer.


Read: WSGI songlist application: the repoze.bfg take

Topic: Cultural Imperialism, Technology, and OLPC Previous Topic   Next Topic Topic: Modern Web Design, I Renounce Thee!

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use