6. Programmation
Karrigell propose plusieurs styles de programmation :
Ces différents styles sont décrits dans la documentation ; ils partagent tous les mêmes
principes pour accéder à l'environnement HTTP et aux variables de formulaires
Vous pouvez aussi ajouter la prise en charge d'autres types de scripts : si vous
voulez gérer les scripts qui ont l'extension .foo , vous devez écrire un
module appelé mod_foo . Voir l'exemple de mod_tmpl.py pour
gérer le système de template Cheetah
6.1 Accès à l'environnement HTTP
L'accès à l'environnement HTTP est fourni par des variables globales disponibles dans l'espace de
noms du script :
HEADERS est un dictionnaire avec les en-têtes HTTP : la clé est le nom de l'en-
tête, la valeur est la valeur de l'en-tête. Par exemple HEADERS["accept-language"]
donne la valeur de l'en-tête accept-language
RESPONSE est un dictionnaire dans lequel on peut définir des valeurs pour l'en-tête
de réponse qui sera envoyé au serveur. Ce dictionnaire ne tient pas compte de la casse des clés :
RESPONSE['Content-type'] et RESPONSE['CONTENT-type'] donnent le même résultat
AUTH_USER et AUTH_PASSWORD sont des valeurs utilisées pour l'authentification
COOKIE est une instance de SimpleCookie (dans le module Cookie ) qui
stocke les cookies envoyés par le navigateur web avec la requête HTTP
SET_COOKIE est un objet SimpleCookie qui se comporte comme un dictionnaire,
et auquel on peut affecter des valeurs qui seront stockées par le navigateur sous forme de cookies
- Pour une utilation plus avancée,
REQUEST_HANDLER représente l'instance courante
de RequestHandler (gestionnaire de requête). Il expose des attributs tels que
client_address , un couple constitué de l'adresse IP et du port du client. Voyez la
documentation de BaseHTTPServer et de SimpleHTTPServer dans la
distribution standard de Python
THIS est une instance de la classe Script (dans Template.py) représentant le script
courant
6.2 Champs de formulaires
La variable QUERY est un dictionnaire qui représente la chaîne de requête si le script
est appelé par la méthode HTTP GET , ou les champs d'un formulaire soumis par la méthode
HTTP POST . Les clés de QUERY sont les noms des champs, et les valeurs sont
soit la valeur du champ sous forme de chaîne, soit une liste contenant les valeurs si le nom du
champ se termine par [] (s'il vient d'un champ de formulaire <SELECT
MULTIPLE> par exemple)
Supposons que vous ayez un formulaire HTML comme celui-ci :
<form action="monScript.py">
Spam <input name="spam">
<br><select multiple name="animal[]">
<option value="chien">Chien
<option value="chat">Chat
<option value="grenouille">Grenouille
</select>
<br><input type="submit" value="Ok">
</form>
Dans monScript.py vous afficherez les valeurs d'entrée avec :
print "<br>Spam est ",QUERY["spam"]
if QUERY.has_key("animal"):
print "<br>Animal est",str(QUERY["animal"])
L'accès à ces données est disponible sous forme d'un raccourci, constitué du caractère de
soulignement _ suivi du nom du champ. Ainsi, le code ci-dessus pourrait s'écrire plus
simplement :
print "<br>Spam est ",_spam
if QUERY.has_key("animal"):
print "<br>Animal est",str(_animal)
Ce caractère de soulignement est introduit pour limiter les risques de conflits avec des noms
réservés de Python ou avec des noms de module fréquemment employés
6.3 Sous-chemin
La façon normale de passer des paramètres à un script est d'utiliser la query string
dans l'url, ou des données dans une requête POST. Une autre possibilité est de passer
des paramètres comme une partie de l'url, comme dans
http://host/path/script.py/foo/bar ; ici les paramètres du script sont
foo et bar
Dans le script vous pouvez accéder aux paramètres sous forme de liste ; c'est un
attribut de THIS, THIS.subpath :
print "Les paramètres sont %s" %THIS.subpath
Un problème avec ces url est que si vous voulez utiliser Include(), ou écrire un
lien ou insérer une image ou un JavaScript avec une url relative, l'url doit être
différente selon que le script a été appelé sans paramètres ou avec un nombre
quelconque de paramètres
Par exemple si vous écrivez cette url relative dans le script :
print '<IMG SRC="images/pic.png">'
et que vous appelez le script par http://host/path/script.py/foo/bar ,
le navigateur calculera l'url absolue http://host/path/script.py/foo/images/pic.png ,
et exécutera le même script avec les paramètres foo,images,pic.png - ce
n'est pas ce que vous voulez !
Donc si vous avez l'intention de passer des paramètres dans un sous-chemin, vous devez
écrire l'url relative de la façon suivante :
print '<IMG SRC="%simages/pic.png">' %THIS.up
où THIS.up est une chaîne de caractères avec autant de
'../' que de nombre de paramètres
6.4 Téléchargement de fichier
Pour télécharger un fichier depuis le client vers le serveur, la balise input doit avoir
le type "file". Par exemple, le formulaire HTML sera de la forme suivante :
<FORM ENCTYPE="multipart/form-data" ACTION="fileUpload.py" METHOD=POST>
Fichier à charger: <INPUT NAME="monfichier" TYPE="file">
<INPUT TYPE="submit" VALUE="Envoyer">
</FORM>
Le script qui doit traiter le téléchargment utilisera la variable
QUERY['myfile'] ou _myfile , qui est une instance de la
classe FieldStorage dans le module intégré cgi . Cet
objet a deux attributs utiles :
filename : le nom du fichier
file : un objet de type fichier depuis lequel on peut lire le contenu
du fichier
Par exemple si vous voulez stocker le fichier dans le système de fichiers du
serveur, en conservant le nom du fichier d'origine :
import os
f = _monfichier.file # objet de type fichier
nom_dest = os.path.basename(_monfichier.filename)
out = open(nom_dest,'wb')
# copier le fichier
import shutil
shutil.copyfileobj(f,out)
out.close()
6.5 Exceptions
Dans les scripts Python on peut lever des exceptions spéciales qui sont gérées par Karrigell
SCRIPT_END
A utiliser pour cesser d'envoyer des données de sortie au navigateur sans avoir à aller jusqu'à
la fin du fichier. Ceci peut être utile si vous êtes en train de déboguer un script et que vous
vouliez arrêter son exécution à un endroit dans votre script pour voir l'état de certaines variables
maVar=10
...
print maVar
raise SCRIPT_END
... (reste du code - ne sera pas exécuté)
SCRIPT_ERROR
Faites raise SCRIPT_ERROR,msg pour arrêter l'exécution du script et écrire le message
HTTP_ERROR
raise HTTP_ERROR,(codeErreur,messageErreur) a pour effet d'envoyer un message
d'erreur HTTP avec les codes et message d'erreur spécifiés
HTTP_REDIRECTION
raise HTTP_REDIRECTION,uri fait que Karrigell redirigera la requête vers l'URI
indiquée
6.6 HTMLStream
HTMLStream est une classe du module HIP qui rend l'affichage de données plus
facile qu'avec une suite de print . C'est la même idée que
HTML Inside Python mais implémentée différemment
Créez une instance de cette classe :
import HIP
H = HIP.HTMLStream()
Ensuite utilisez "+" et "-" pour envoyer des données sur la sortie standard : avec "+"
la representation en chaîne de caractère de la donnée est imprimée ; avec "-", la fonction
cgi.escape est exécutée sur cette chaîne
dico={"un":"unan","deux":"daou","trois":"tri"}
H + dico - type(dico)
revient au même que :
dico={"un":"unan","deux":"daou","trois":"tri"}
print str(dico),cgi.escape(type(dico))
6.6 Gestion des erreurs et débogueur
Si une erreur survient quand on appelle une URL, une trace est affichée dans le navigateur
L'information fournie consiste en :
- l'url appelée
- une table relative au script dans lequel l'erreur s'est produite : il se peut que ce ne soit pas
celui dont le nom correspond à l'URL, si l'erreur est survenue dans un script inclus par la fonction
Include(). La table montre le nom du script, le nom de l'exception, le numéro et le texte de la
ligne dans le script erronné
- la trace Python brute
- un bouton "debug"
Par exemple :
Error in /demo/errors/ErrorInIncludedTest1.py
/demo/errors/ErrorInIncludedTest1.py
includes /demo/errors/ErrorInIncludedTest2.py
Script /demo/errors/ErrorInIncludedTest1.py NameError: name 'bonjour' is not defined
Line 1
print 'Script 1' |
Traceback (most recent call last):
File "C:\cygwin\home\Karrigell\Template.py", line 153, in render
exec self.pythonCode() in ns
File "<string>", line 1, in ?
NameError: name 'bonjour' is not defined
Avec ce bouton "Debug" on accède à plus d'informations au sujet de l'erreur :
- le code source, avec syntaxe colorée et la ligne où s'est produite l'erreur mise
en évidence
- une vue de l'environnement, dans laquelle on peut naviguer pour trouver la valeur
des variables, le code source des fonctions et méthodes, etc
Aperçu :
|