Outils pour utilisateurs

Outils du site


mini_calculatrice_cgi

Un serveur web en moins de 5 minutes, accompagné d'une mini calculatrice CGI en ligne !!!

Un serveur web-CGI en moins de 5 minutes

Vous n'avez pas de serveur web installé dans votre réseau local, mais si vos besoins sont locaux et limités (pas de php ni mysql, …) vous pouvez en installer un très facilement, grâce à Python.

1- vous choisissez un répertoire dans lequel sera placé votre site. Par exemple c:\cheminsite pour Windows et /cheminsite pour Linux (avec le droit d'écrire dedans!).

2- vous placez votre site dans ce répertoire, avec au minimum un fichier index.html, par exemple:

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
</head>
<body>
<p>Vous avez le bonjour de Tyrtamos!!!</p>
</body>
</html>

Si vous avez besoin du CGI, vous ajoutez un répertoire cgi-bin dans lequel vous placez vos scripts CGI.

3- vous ouvrez une console (cmd pour Windows, shell pour Linux), vous vous placez dans le répertoire racine de votre site (avec la commande “cd”), et vous faites (version Python >=2.4):

python -m CGIHTTPServer

Avec une version de Python inférieure à 2.4, l'option -m n'existe pas, et il faut donc appeler CGIHTTPServer.py avec son chemin complet.

Il y a une réponse:

Serving HTTP on 0.0.0.0 port 8000 ...

Et c'est tout: vous avez votre serveur web-CGI.

Vous noterez qu'il doit être appelé avec le port 8000 et non 80 (=port web par défaut), ce qui permet l'installation sur une machine qui a déjà un serveur web (apache par exemple).

On peut appeler le site par:

http://127.0.0.1:8000
http://localhost:8000

ou, si vous avez une adresse ip locale fixe:

http://192.168.0.99:8000

ou, si vous avez un nom de domaine déclaré dans votre fichier hosts (ou un serveur de nom local!):

http://votremachine.lan:8000

Et pour démarrez un script CGI, pour prendre l'exemple de la calculatrice CGI ci-dessous:

http://192.168.0.99:8000/cgi-bin/calculcgi.py

A part pour localhost, toutes ces adresses fonctionnent dans un réseau local d'une machine à l'autre.

Il devrait être possible de modifier le port 8000 pour mettre le port 80, mais il faut intervenir dans les bibliothèques Python, ce qui va trop loin pour l'instant.

Une mini-calculatrice scientifique CGI en ligne

A titre d'application concrête du serveur ci-dessus, je vous propose une calculatrice en ligne au sein de votre réseau local.

Vous l'appelez, par exemple, calculcgi.py, vous la placez dans le répertoire cgi-bin de votre serveur.

Sous linux, il y a 2 particularités:

  • le code doit avoir des fins de ligne de type “UNIX” (\n),
  • le fichier calculcgi.py doit être exécutable.

Si vous avez un hébergeur de site web qui accepte les scripts CGI Python, vous pourriez le mettre sur ce site, et donc en libre service pour tout le web!

Quelques particularités de cette calculatrice CGI:

  • on communique avec cette calculatrice par n'importe quel navigateur web.
  • chacun de ses calculs est limité dans le temps (ici, 10 secondes), afin qu'un calcul trop long ne vous oblige à “tuer” le serveur.
  • arrêter le calcul dans eval() a nécessité l'utilisation de sys.settrace, habituellement utilisé pour le debugging (j'ai mis longtemps à trouver cette solution…).
  • l'expression à calculer est donnée dans un formulaire html. Et la réponse sous forme de page web vous présente aussi le formulaire pour le calcul suivant.
  • cette calculatrice est facile à étendre par des modules supplémentaires, et un module est fourni à titre d'exemple: calculsup.py qui contient le calcul de la factoriel de n (fonction fact(n))

Vous n'avez pas beaucoup d'adaptation à faire:

  • l'adresse de votre calculatrice (ici, adresse=“http://192.168.0.99:8000/cgi-bin/calculcgi.py”)
  • le temps maxi de calcul en secondes au delà duquel la calculatrice s'arrêtera toute seule avec un message d'erreur (ici, dureemaxcalcul=10)

Le code est copieusement auto-documenté:

#!/usr/bin/python
# -*- coding: utf-8 -*-
 
# importation nécessaire pour les divisions entières aient un résultat décimal
from __future__ import division
 
# indispensable pour l'exécution en tant que script cgi
print "Content-type: text/html\n\n"
# pour Linux: il faut que les fins de ligne de cette page soient "UNIX" ('\n')
 
# importations "système" nécessaires
import cgi
from sys import path, exc_info, settrace
import threading
import time
 
# importations seulement nécessaires aux calculs
from math import *
 
# importations optionnelles de modules de calcul supplémentaires
path.append('./')
from calculsup import *
 
##############################################################################
# déclaration des variables globales
 
# Nécessaire pour limiter la longueur des calculs (ici, 10 secondes)
dureemaxcalcul=10
 
# adresse de la calculatrice à adapter à votre contexte
adresse="http://192.168.0.99:8000/cgi-bin/calculcgi.py"
 
# partie html pour présentation des résultats dans un navigateur web
codehtml1 = """
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//FR" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Calculatrice scientifique en ligne</title>
<meta name="description" content="Calculatrice scientifique en ligne" />
<meta name="keywords" content="calcul, calculatrice, scientifique" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="author" lang="fr" content="Tyrtamos" />
<meta name="language" content="French" />
</head>
<body>
<p><font size="6">Calculatrice scientifique en ligne</font></p>
<form name="form1" method="post" action="
"""
 
codehtml2 = """
">
    <p><b>Nouvelle expression :</b></p>
    <p><input type="text" name="saisie" id="saisie" size="88"> &nbsp;&nbsp;<input type="submit" name="bouton" id="bouton" value="Calculer"></p>
</form>
<p>&nbsp;</p>
<p><b>Expression calcul&eacute;e = </b>
"""
 
codehtml3 = """
</p>
<p><b>R&eacute;sultat = &nbsp;</b><span style="background-color:yellow;">
"""
 
codehtml4 = """
</span></p>
</body>
</html>
"""
 
##############################################################################
# Définition de la classe "Calcul" dans un thread (=processus "leger")
#
class Calcul(threading.Thread):
    """Thread de calcul permettant le calcul de l'expression en tâche de fond"""
 
    def __init__(self,expr):
        """Initialise le thread ainsi que les variables de l'instance"""
        threading.Thread.__init__(self)
        # stocke l'expression à calculer dans une variable d'instance
        self.expression = expr
        # créé la variable d'instance qui pourra porter l'ordre d'arrêter le calcul
        self.arretcalcul = False
        # créé la variable d'instance qui portera le résultat du calcul
        self.resultat = ""
 
    def run(self):
        """Lance le calcul en tâche de fond et sauvegarde le résultat"""
        try:
            # lance le traçage pour permettre l'arrêt anticipée du calcul
            settrace(self.tracecalcul)
            # calcul de l'expression
            self.resultat = "%s" % eval(self.expression)
            # arrêt du traçage
            settrace(None)
        except:
            # arrêt du traçage en cas d'exception déclenchée
            settrace(None)
            # enregistrement de l'erreur de calcul détectée s'il y en a une
            self.resultat = "erreur: %s" % exc_info()[1]
 
    def tracecalcul(self, frame, event, arg):
        """Fonction de trace nécessaire pour permettre l'arrêt anticipé d'eval()"""
        if event=='line':
            if self.arretcalcul:
                raise ValueError ("arrêt calcul trop long")
        return self.tracecalcul
 
    def stopcalcul(self):
        """Fonction déclenchant l'arrêt du calcul en cours"""
        self.arretcalcul = True
 
    def donneresultat(self):
        return self.resultat
 
##############################################################################
# Traitement de la requête reçue par le réseau
#
if __name__ == "__main__":
    # initialisation du temps de départ
    debutcalcul=time.time()
    # Récupération d'une éventuelle requête transmise (GET ou POST)
    recup=cgi.FieldStorage()
    if recup.has_key("saisie"):
        # =il y a eu effectivement réception d'une requête (GET ou POST)
        requete=recup["saisie"].value
        if requete=="":
            # la requête reçue est vide: on renvoie la page web avec les zones vides
            reponse=""
            duree=""
        else:
            # on lance le calcul de la requête en tâche de fond (thread démon)
            calc=Calcul(requete)
            calc.setDaemon(True)
            calc.start()
            while calc.isAlive():
                # vérif qu'on ne dépasse pas le temps maxi de calcul
                if (time.time()-debutcalcul)>dureemaxcalcul:
                    # si oui, on demande l'arrêt anticipé du calcul trop long
                    calc.stopcalcul()
                # tempo pour laisser la priorité au calcul
                time.sleep(0.5)
            # lecture du résultat du calcul ou de l'erreur ou du dépassement de temps
            reponse = calc.donneresultat()
    else:
        # si rien n'a été transmis, renvoie la page web avec les zones vides pour calcul suivant
        requete=""
        reponse=""
        duree=""
    # renvoie au client web la page html donnant le résultat du calcul ou le message d'erreur
    print codehtml1 + adresse + codehtml2 + requete + codehtml3 + reponse + codehtml4

Et pour le module de calcul supplémentaire calculsup.py:

#!/usr/bin/python
# -*- coding: utf-8 -*-
 
# importation nécessaire pour les divisions entières aient un résultat décimal
from __future__ import division
 
###############################################################################
# Factorielle de n
# - version volontairement non récursive (la pile de python est limitée à environ 1000)
def fact(n):
    """fact(n): calcule la factorielle de n (entier >= 0)"""
    # Vérification de la donnée
    if not(type(n)==int or type(n)==long) or n<0:
        raise ValueError ("erreur fact(n): n doit être un nombre entier positif ou nul")
    # Calcul
    x=1
    for i in xrange(2,n+1):
        x*=i
    return x

Amusez-vous bien!

mini_calculatrice_cgi.txt · Dernière modification: 2008/04/12 08:51 de tyrtamos

Outils de la page