Programmation Lisp
Programmation Python/L'interface CGI
Description.
L'interface CGI (pour ') est un composant de la plupart des logiciels serveurs de pages web. Il s'agit d'une passerelle qui leur permet de communiquer avec d'autres logiciels tournant sur le même ordinateur. Avec CGI, vous pouvez écrire des scripts dans différents langages ("Perl", "C", "Tcl", "PHP", ' ...).
Plutôt que de limiter le web à des documents écrits à l'avance, CGI permet de générer des pages web sur le champ, en fonction des données que fournit l'internaute par l'intermédiaire de son logiciel de navigation ou de données stockées sur le serveur que le script peut également modifier, par exemple en utilisant une base de données. Vous pouvez utiliser les scripts CGI pour créer une large palette d'applications : des services d'inscription en ligne, des outils de recherche dans des bases de données, des instruments de sondage d'opinions, des jeux, etc.
L'apprentissage de la programmation CGI peut faire l'objet de manuels entiers. Dans cet ouvrage d'initiation, nous vous expliquerons seulement quelques principes de base, afin de vous faire comprendre, par comparaison, l'énorme avantage que présentent les modules serveurs d'applications spécialisés tels que ', ' ou "", pour le programmeur désireux de développer un site web interactif.
Installation.
Par défaut, lire un fichier .py en HTTP renvoie son contenu. Pour que le serveur compile et exécute le code source, il faut que la configuration suivante figure dans sa configuration, ou bien que les scripts soient placés dans un répertoire contenant un fichier nommé ".htaccess", avec les lignes :
 AddHandler cgi-script .py
 Options +ExecCGI
Exemples.
Le module codice_1 sert aux éventuels débogages :
print "Content-type: text/html; charset=utf-8\n\n"
print "<html><head><title>Répertoire local</title></head><body>"
import cgitb
cgitb.enable()
import os
print "Le fichier CGI se trouve dans :"
print os.path.dirname(__file__)
print "</body></html>"
L'utilisation d'un formulaire nécessite un codice_2. Pour une base de données MySQL c'est codice_3. Soit le fichier suivant "CGI_MySQL.py" utilisant les deux :
print "Content-type: text/html; charset=utf-8\n\n"
print "<html><head><title>CGI BDD</title></head><body>"
print "<h1>Extraction MySQL</h1>"
print "<ul>"
import cgitb
cgitb.enable()
import cgi, MySQLdb
formulaire = cgi.FieldStorage()
if formulaire.getvalue('nom') == None:
 print "<h2>Rechercher un nom</h2>"
 print 
 <form action="CGI_MySQL.py" method="post">
 <input type="text" name="nom" />
 <input type="submit"></form>
else:
 print "<h2>Résultat</h2>"
 print "Liste des correspondances pour " + formulaire.getvalue('nom') + " :"
 connection = MySQLdb.connect(user='login1', passwd='mdp1', db='base1')
 cursor = connection.cursor()
 cursor.execute("SELECT page_title FROM page WHERE nom ='"+formulaire.getvalue('nom')+"'")
 for row in cursor.fetchall():
 print "<li>%s</li>" % row[0]
 connection.close()
print "</ul>"
print "</body></html>"
Une interaction CGI rudimentaire.
Veuillez donc encoder le document HTML ci-dessous à l'aide d'un éditeur quelconque :
<HTML>
<HEAD><TITLE>Exercice avec Python</TITLE></HEAD>
<BODY>
<DIV ALIGN="center">
<IMG SRC="penguin.gif">
<H2>Page Web interactive</H2>
<P>Cette page est associée à un script Python</P>
<FORM ACTION="http://localhost/cgi-bin/input_query.py" METHOD="post">
<INPUT TYPE="submit" NAME="send" VALUE="Exécuter le script">
</FORM>
</DIV></BODY></HTML>
Vous savez certainement déjà que les balises initiales codice_4, codice_5, codice_6, codice_7, ainsi que les balises finales correspondantes, sont communes à tous les documents HTML. Nous ne détaillerons donc pas leur rôle ici.
La balise codice_8 utilisée à la ligne 5 sert habituellement à diviser un document HTML en sections distinctes. Nous l'utilisons ici pour définir une section dans laquelle tous les éléments seront centrés (horizontalement) sur la page.
À la ligne 6, nous insérons une petite image.
La ligne 7 définit une ligne de texte comme étant un titre de 2e importance.
La ligne 8 est un paragraphe ordinaire.
Les lignes 10 à 12 contiennent le code important (pour ce qui nous occupe ici). Les balises codice_8 définissent en effet un formulaire, c'est-à-dire une portion de page Web susceptible de contenir divers "widgets" à l'aide desquels l'internaute pourra exercer une certaine activité : champs d'entrée, boutons, cases à cocher, boutons radio, etc.
La balise codice_10 doit contenir deux indications essentielles : l"'action" à accomplir lorsque le formulaire sera expédié (il s'agit en fait de fournir ici l'adresse URL du logiciel à invoquer pour traiter les données transmises), et la "méthode" à utiliser pour transmettre l'information (en ce qui nous concerne, ce sera toujours la méthode codice_11).
Dans notre exemple, le logiciel que nous voulons invoquer est un script Python nommé codice_12 qui est situé dans un répertoire particulier du serveur d'intranet. Sur de nombreux serveurs, ce répertoire s'appelle souvent "cgi-bin", par pure convention. Nous supposerons ici que l'administrateur de votre intranet scolaire vous autorise à installer vos scripts Python dans le même répertoire que celui où vous placez vos pages web personnelles.
Vous devrez donc modifier la ligne 10 de notre exemple, en remplaçant le nom de domaine dans l'adresse "http://localhost/cgi-bin/input_query.py".
La ligne 11 contient la balise qui définit un "widget" de type « bouton d'envoi » (balise codice_13). Le texte qui doit apparaître sur le bouton est précisé par l'attribut codice_14. L'indication codice_15 est facultative dans le cas présent. Elle mentionne le nom du widget lui-même (au cas où le logiciel destinataire en aurait besoin).
Lorsque vous aurez terminé l'encodage de ce document, sauvegardez-le dans le répertoire que l'on vous a attribué spécifiquement pour y placer vos pages, sous un nom quelconque, mais de préférence avec l'extension codice_16 ou codice_17 (par exemple : codice_18).
Le script Python codice_12 est détaillé ci-dessous. Comme déjà signalé plus haut, vous pouvez installer ce script dans le même répertoire que votre document HTML initial :
print "Content-Type: text/html\n"
print """
<H3><FONT COLOR="Royal blue">
Page web produite par un script Python
</FONT></H3>
<FORM ACTION="print_result.py" METHOD="post">
<P>Veuillez entrer votre nom dans le champ ci-dessous, s.v.p. :</P>
<P><INPUT NAME="visiteur" SIZE=20 MAXLENGTH=20 TYPE="text"></P>
<P>Veuillez également me fournir une phrase quelconque :</P>
<TEXTAREA NAME="phrase" ROWS=2 COLS=50>Mississippi</TEXTAREA>
<P>J'utiliserai cette phrase pour établir un histogramme.</P>
<INPUT TYPE="submit" NAME="send" VALUE="Action">
</FORM>
Ce script ne fait rien d'autre que d'afficher une nouvelle page web, laquelle contient encore une fois un formulaire, mais celui-ci nettement plus élaboré que le précédent.
La première ligne est absolument nécessaire : elle indique à l'interface CGI qu'il faut lancer l'interpréteur Python pour pouvoir exécuter le script. La seconde ligne spécifie l'encodage du code source.
La ligne 4 est indispensable. Elle permet à l'interpréteur Python d'initialiser un véritable document HTML qui sera transmis au serveur web. Celui-ci pourra à son tour le réexpédier au logiciel navigateur de l'internaute, et celui-ci le verra donc s'afficher dans la fenêtre de navigation.
La suite est du pur code HTML, traité par Python comme une simple chaîne de caractères que l'on affiche à l'aide de l'instruction codice_20. Pour pouvoir y insérer tout ce que nous voulons, y compris les sauts à la ligne, les apostrophes, les guillemets, etc., nous délimitons cette chaîne de caractères à l'aide de « triples guillemets » (Rappelons également ici que les sauts à la ligne sont complètement ignorés en HTML : nous pouvons donc en utiliser autant que nous voulons pour « aérer » notre code et le rendre plus lisible).
Un formulaire HTML pour l'acquisition des données.
Analysons à présent le code HTML lui-même. Nous y trouvons essentiellement un nouveau formulaire, qui comporte plusieurs paragraphes, parmi lesquels on peut reconnaître quelques "widgets". La ligne 10 indique le nom du script CGI auquel les données du formulaire seront transmises : il s'agira bien évidemment d'un autre script Python.
À la ligne 12, on trouve la définition d'un "widget" de type « champ d'entrée » (Balise codice_21, avec codice_22). L'utilisateur est invité à y encoder son nom. Le paramètre codice_23 définit une longueur maximale pour la chaîne de caractères qui sera entrée ici (20 caractères, en l'occurrence). Le paramètre codice_24 définit la taille du champ tel qu'il doit apparaître à l'écran, et le paramètre codice_15 est le nom que nous choisissons pour la variable destinée à mémoriser la chaîne de caractères attendue.
Un second champ d'entrée un peu différent est défini à la ligne 14 (balise codice_26). Il s'agit d'un réceptacle plus vaste, destiné à accueillir des textes de plusieurs lignes. (Ce champ est automatiquement pourvu d'ascenseurs si le texte à insérer se révèle trop volumineux). Ses paramètres codice_27 et codice_28 sont assez explicites. Entre les balises initiale et finale, on peut insérer un texte par défaut (codice_29 dans notre exemple).
Comme dans l'exemple précédent, la ligne 16 contient la définition du bouton qu'il faudra actionner pour transmettre les données au script CGI destinataire, lequel est décrit ci-après.
Un script CGI pour le traitement des données.
Le mécanisme utilisé à l'intérieur d'un script CGI pour réceptionner les données transmises par un formulaire HTML est fort simple, comme vous pouvez l'analyser dans l'exemple ci-dessous : 
import cgi # Module d'interface avec le serveur web
form = cgi.FieldStorage() # Réception de la requête utilisateur :
 # il s'agit d'une sorte de dictionnaire
if form.has_key("phrase"): # La clé n'existera pas si le champ
 text = form["phrase"].value # correspondant est resté vide
else:
 text ="*** le champ phrase était vide ! ***"
if form.has_key("visiteur"): # La clé n'existera pas si le champ
 nomv = form["visiteur"].value # correspondant est resté vide
else:
 nomv ="mais vous ne m'avez pas indiqué votre nom"
print "Content-Type: text/html\n"
print """
<H3>Merci, %s !</H3>
<H4>La phrase que vous m'avez fournie était : </H4>
<H3><FONT Color="red"> %s </FONT></H3>""" % (nomv, text)
for c in text:
 histogr[c] = histogr.get(c, 0) +1
liste = histogr.items() # conversion en une liste de tuples
liste.sort() # tri de la liste
print "<H4>Fréquence de chaque caractère dans la phrase :</H4>"
for c, f in liste:
 print 'le caractère <B>"%s"</B> apparaît %s fois <BR>' % (c, f)
Les lignes 4 et 5 sont les plus importantes :
Le module "cgi" importé à la ligne 4 assure la connexion du script Python avec l'interface CGI , laquelle permet de dialoguer avec le serveur web.
À la ligne 5, la fonction codice_30 de ce module renvoie un objet qui contient l'ensemble des données transmises par le formulaire HTML. Nous plaçons cet objet, lequel est assez semblable à un dictionnaire classique, dans la variable codice_31.
Par rapport à un véritable dictionnaire, l'objet placé dans form présente la différence essentielle qu'il faudra lui appliquer la méthode codice_32 pour en extraire les données. Les autres méthodes applicables aux dictionnaires, telles la méthode codice_33, par exemple, peuvent être utilisées de la manière habituelle.
Une caractéristique importante de l'objet dictionnaire retourné par FieldStorage() est qu"'il ne possédera aucune clé pour les champs laissés vides" dans le formulaire HTML correspondant.
Dans notre exemple, le formulaire comporte deux champs d'entrée, auxquels nous avons associé les noms codice_34 et codice_35. Si ces champs ont effectivement été complétés par l'utilisateur, nous trouverons leurs contenus dans l'objet dictionnaire, aux index « visiteur » et « phrase ». Par contre, si l'un ou l'autre de ces champs n'a pas été complété, l'index correspondant n'existera tout simplement pas. Avant toute forme de traitement de valeurs, il est donc indispensable de s'assurer de la présence de chacun des index attendus, et c'est ce que nous faisons aux lignes 7 à 15.
Le reste du script est assez classique.