[??WSGI|Web Server Gateway Interface??|http://www.wsgi.org/], est spécification ([PEP 3333|http://www.python.org/dev/peps/pep-3333/]) définissant une « interface » commune entre des serveurs et des applications Web écrite en [Python|http://www.python.org/].

Les serveurs WSGI permettent de se « passer » d’un serveur, tels que Apache, NGinx, Lighttpd, … Ils fonctionnent de manière  »standalone ». On peut bien entendu les coupler à ces serveurs Web, mais il faudra les  »proxyfier ».

Pour comprendre un minimum le contenu de cet article, il faut avoir quelques notions concernant le langage Python, et Mercurial.

!!!Création d’un dépôt

Dans cette partie, nous allons voir comment mettre en place (sans rentrer dans les détails) un dépôt pour un projet.

///olivier@bornem:~ $ mkdir -p ~/projet/.hg ; cd ~/projet
olivier@bornem:~ $ touch .hg/hgrc
///

La seconde ligne crée le fichier de configuration (vide pour l’instant), nécessaire au bon fonctionnement de Mercurial. Nous allons voir comment le remplir
[hgrc(5)|http://www.selenic.com/mercurial/hgrc.5.html] :

///olivier@bornem:~/projet $ cat >> .hg/hgrc
[ui]
username = Olivier Duchateau
verbose = True
^C
///

Nous allons déposer des fichiers (ils correspondront à notre premier projet).

///olivier@bornem:~/projet $ cp /etc/hosts .
olivier@bornem:~/projet $ cp /etc/fstab .
olivier@bornem:~/projet $ cp /etc/shells .
olivier@bornem:~/projet $ hg add
ajout de fstab
ajout de hosts
ajout de shells
olivier@bornem:~/projet $
olivier@bornem:~/projet $ hg commit
///

La dernière ligne permet « d’enregistrer » l’historique du projet. Vous pouvez modifier l’un ou l’ensemble des fichiers, il faudra dans tous les cas, mettre à jour l’historique avec la commande @@hg commit@@.

Maintenant, nous pouvons mettre en place notre application WSGI, et la faire « tourner » à l’aide de quelques serveurs.

!!!L’arborescence de notre application Web

On quitte le répertoire de notre projet, pour aller dans celui du serveur Web.

///olivier@bornem:~ $ mkdir ~/htdocs ; cd ~/htdocs
olivier@bornem:~/htdocs $ cat > hgwebdir.cfg
[web]
contact = Olivier Duchateau
description = Mes fichiers de configuration (ordinateur : bornem)
adress = 127.0.0.1

[paths]
bornem-config = /home/olivier/projet
olivier@bornem:~/htdocs $
///

Vous pouvez voir ci-dessus, le contenu du fichier de configuration (@@hgwebdir.cfg@@) de notre dépôt Mercurial.

Le script Python, de notre application (@@hgweb.py@@), qui utilise le module __hgweb__.

///#! /usr/bin/env python
# -*- coding: iso-8859-15 -*-
#

import os

# Le chemin vers le fichier de configuration du dépôt
_basedir = os.path.abspath(os.path.dirname(__file__))
hg_dir = os.path.join(_basedir, « hgwebdir.cfg »)

del os

from mercurial.hgweb.hgwebdir_mod import hgwebdir
app = hgwebdir(hg_dir)
///

Le fichier @@hgweb.py@@ est situé dans le dossier @@htdocs/@@.

!![Gunicorn|http://gunicorn.org/|en|Green Unicorn]

Gunicorn, est bien sûr un serveur WSGI écrit en Python. Nous allons l’utiliser sans  »framework ».

Il se lance à partir de la ligne de [commande|http://gunicorn.org/run.html#gunicorn]. Cependant, on peut créer un fichier de configuration. C’est ce que nous allons mettre en place.

///#! /usr/bin/env python
# -*- coding: iso-8859-15 -*-

import multiprocessing

bind = « 127.0.0.1:5050 »
workers = multiprocessing.cpu_count() * 2 + 1
pidfile = « /tmp/gunicorn.pid »
///

__Explication :__
* La page Web sera accessible à partir de l’adresse @@127.0.0.1:5050@@ (notez bien le port)
* le numéro du processus sera stocké dans le fichier @@/tmp/gunicorn.pid@@
* le nombre de processus est défini par la variable @@workers@@, (choix du [nombre| http://gunicorn.org/design.html#how-many-workers])

Pour lancer notre application :

///olivier@bornem:~/htdocs $ gunicorn -c ~/gunicorn.py hgweb:app
2011-11-05 19:37:37 [32209] [INFO] Starting gunicorn 0.13.4
2011-11-05 19:37:37 [32209] [INFO] Listening at: http://127.0.0.1:5050 (32209)
2011-11-05 19:37:37 [32209] [INFO] Using worker: sync
2011-11-05 19:37:37 [32211] [INFO] Booting worker with pid: 32211
2011-11-05 19:37:37 [32212] [INFO] Booting worker with pid: 32212
2011-11-05 19:37:38 [32213] [INFO] Booting worker with pid: 32213

///

Pour admirer le résultat, il faut faire pointer votre navigateur à l’adresse @@127.0.0.1:5050@@.

La dernière partie de la ligne de commande, n’est sans doute pas très claire.

En fait, Gunicorn, utilise la même « syntaxe » que Python, lors de l’importation des modules. @@__hgweb__@@ est le nom du module (fichier @@hgweb.py@@), quant à @@__app__@@ est la référence à notre application.

Si l’on souhaite lancer Gunicorn en dehors du dossier @@htdocs/@@, il faudra créer un fichier @@__init__.py@@ à l’intérieur de celui-ci.

La commande devient donc :

///olivier@bornem:~ $ gunicorn -c gunicorn.py htdocs.hgweb:app///

!![wsgiref|http://docs.python.org/library/wsgiref.html]

Il s’agit d’un module présent nativement dans la bibliothèque standard de Python. Il implémente les spécifications WSGI.

Pour l’utiliser, il faut « importer » le module @@[wsgiref.simple_server|http://docs.python.org/library/wsgiref.html#module-wsgiref.simple_server]@@.

Ci-dessous, un exemple pour lancer l’interface Web de notre dépôt Mercurial.

///#! /usr/bin/env python
# -*- coding: iso-8859-15 -*-

import wsgiref.simple_server
#import wsgiref.simple_server

import Documents.hgweb

if __name__ == « __main__ »:
wsgi = wsgiref.simple_server.make_server(« 127.0.0.1 », 5050,
Documents.hgweb.app)
soc_tcp = wsgi.socket.getsockname()
print « t* Running on http://%s:%s » % (soc_tcp[0], soc_tcp[1])
wsgi.serve_forever()
///

!![gevent|http://www.gevent.org/|en|A coroutine-based network library for Python]

Nous allons utiliser le module __wsgi__. Dans cet exemple le fichier @@__init__.py@@ est indispensable.

Ci dessous le fichier (@@runserver.wsgi@@), qui nous permettra de lancer notre application Web.

///#! /usr/bin/env python
# -*- coding: iso-8859-15 -*-
#

import sys
try:
from gevent.wsgi import WSGIServer
except ImportError, e:
print « Le module ‘gevent’ est manquant ! »
sys.exit()

import htdocs.hgweb

if __name__ == « __main__ »:
WSGIServer((« 127.0.0.1″, 5050),
application=htdocs.hgweb.app,
log=None).serve_forever()
///

L’application se lance de cette façon.

///olivier@bornem:~ $ python runserver.wsgi///

!![Werkzeug|http://werkzeug.pocoo.org/|en|The Python WSGI utility library]

Il s’agit d’un couteau suisse pour tout ce qui concerne les applications WSGI, il est utilisé notamment dans les  »frameworks », [Flask|http://flask.pocoo.org/], et [tipfy|http://www.tipfy.org/].

Le fichier (@@runserver.wsgi@@) ressemble à ça :

///#! /usr/bin/env python
# -*- coding: iso-8859-15 -*-
#

import multiprocessing
import sys
try:
import werkzeug.serving
except ImportError, e:
print « Le module ‘werkzeug’ est absent ! »

import htdocs.hgweb

if __name__ == « __main__ »:
werkzeug.serving.run_simple(« 127.0.0.1 », 5050,
htdocs.hgweb.app,
use_reloader=True,
processes=multiprocessing.cpu_count() * 2 + 1)///

L’application se lance comme ceci :

///olivier@bornem:~ $ python runserver.wsgi///

Nous n’avons pas fait le tour des serveurs WSGI, mais nous avons vu un aperçu comment les utiliser pour afficher des pages Web dynamique en Python.