Thursday, May 15, 2008

python on web - getting started : building your first app

I would be focusing here on the following tasks.

  • install pylons.

  • create a helloworld app using pylons.

  • install genshi.

  • change template engine.

  • deploy on apache using mod_wsgi.

Install Pylons

Run the following:

$ easy_install Pylons==
$ easy_install -f Pylons==

More details at

Create helloworld app

$ paster create -t pylons helloworld

A directory helloworld with the following structure is created

jayant@jayantbox:~/myprogs/python/helloworld$ ls -lh
total 44K
drwxr-xr-x 4 jayant jayant 4.0K 2008-04-25 17:47 data
-rwxr-xr-x 1 jayant jayant 1.5K 2008-05-15 10:41 development.ini
drwxr-xr-x 2 jayant jayant 4.0K 2008-04-25 17:47 docs
drwxr-xr-x 2 jayant jayant 4.0K 2008-04-25 17:47 ez_setup
drwxr-xr-x 9 jayant jayant 4.0K 2008-05-14 19:52 helloworld
drwxr-xr-x 2 jayant jayant 4.0K 2008-04-25 17:47 helloworld.egg-info
-rwxr-xr-x 1 jayant jayant 79 2008-04-25 17:47
-rwxr-xr-x 1 jayant jayant 463 2008-04-25 17:47 README.txt
-rwxr-xr-x 1 jayant jayant 1.2K 2008-04-25 17:47 setup.cfg
-rwxr-xr-x 1 jayant jayant 865 2008-04-25 17:47
-rwxr-xr-x 1 jayant jayant 507 2008-04-25 17:47 test.ini

To run the app, from within the helloworld directory do

jayant@jayantbox:~/myprogs/python/helloworld$ paster serve --reload development.ini
Starting subprocess with file monitor
Starting server in PID 15555.
serving on view at

Create a test.html in the <path_to_helloworld>helloworld/helloworld/public directory

Hello World!!

And point your browser to to see the "Hello World!!" page.

Now lets create a controller and try printing info through a template.

jayant@jayantbox:~/myprogs/python/helloworld$ paster controller hello
Creating /home/jayant/myprogs/python/helloworld/helloworld/controllers/
Creating /home/jayant/myprogs/python/helloworld/helloworld/tests/functional/

Edit the <path_to_helloworld>/helloworld/helloworld/controllers/ file and put in some python code

import logging

from helloworld.lib.base import *

log = logging.getLogger(__name__)

class HelloController(BaseController):

    def index(self):
        # Return a rendered template
        # return render('/some/template.mako')
        # or, Return a response
        return 'Hello World'
    def serverinfo(self):
        import cgi
        import pprint
        c.pretty_environ = cgi.escape(pprint.pformat(request.environ)) = 'Jayant Kumar'
        return render('serverinfo.mako')

Now create a template serverinfo.mako in <path_to_helloworld>/helloworld/helloworld/templates

Server info for ${}

The URL you called: ${h.url_for()}

<p>Hi there ${ or c.full_name or "Joe Smith"}</p>

The name you set: ${}

<p>The WSGI environ:<br>

Edit the <path_to_helloworld>/helloworld/helloworld/config/ file and check if the following code there in the "CUSTOM ROUTES" section

map.connect('', controller='hello', action='index')
map.connect('*url', controller='template', action='view')

This means that an empty URL is matched to the index action of the hello controller. Otherwise, the route mapper looks for URLs in the form controller/action/id, but if action or controller are not specified the request is routed to the view action of the templates controller (created by the Pylons template). This raises a 404 error by default

Now go to http://localhost:5000/hello/hello and http://localhost:5000/hello/serverinfo and check out the output.

Installing genshi and switching the template engine

$ easy_install Genshi

To enable genshi in your project edit the <path_to_helloworld>/helloworld/helloworld/config/ file and change the template engine from mako to genshi

    config.init_app(global_conf, app_conf, package='helloworld',
        template_engine='genshi', paths=paths)

Now create a new template in <path_to_helloworld>/helloworld/helloworld/templates, say serverinfo.html and put in the following code

<html xmlns=""

<p>Hi there ${}</p>

The name you set: ${}

<p>The WSGI environ:<br/>
<div py:content="c.pretty_environ">Pretty Environ</div>

And change your <path_to_helloworld>/helloworld/helloworld/controllers/ to render the new template

        return render('serverinfo')

And check the output at http://localhost:5000/hello/hello and http://localhost:5000/hello/serverinfo

Deploy using mod_wsgi

For those who have not yet configured mod_wsgi, you can get mod_wsgi from

Simply untar it and do a

./configure --with-apxs=/path/to/apache/bin/apxs
sudo make install

Bingo and you have the file in your apache/modules directory

Change the httpd.conf and add the following

LoadModule wsgi_module modules/

to load the wsgi module and then deploy the hello world application

WSGIDaemonProcess hello thread=25
WSGIScriptAlias /hello "/path/to/apache/anydirectory/hello.wsgi
<Location /hello>
        WSGIProcessGroup hello
        WSGIReloadMechanism Process

This says that the application helloworld would run as a separate process with 25 threads. And since we have also enabled process reload mechanism available with mod_wsgi-2.0, all that is needed to restart/reload the application is to touch/change the wsgi script modification time.

Wait a minute, we did not create the hello.wsgi script. Create a directory in /path/to/apache or anywhere where apache has read access and where you want to keep your application startup scripts. So what i did was.

$ mkdir /path/to/apache/wsgi

And create a hello.wsgi inside it

cd /path/to/apache/wsgi
vim hello.wsgi

Add the following code here

import os, sys

from paste.deploy import loadapp

application = loadapp('config:/path/to/python/application/helloworld/development.ini')

And we are done. Please note that the /path/to/python/application should be readable and executable by apache. Or you can do (very unsafe - not recommended on production servers)

chmod -R a+rx /path

Now simply restart apache and point your browser to


To see the output.


No comments: