TP1 : représenter des données info-719, Pierre Hyvernat 13/10/2009 ------------------------------------------------------------------------ Consignes Liens utiles 1. Préliminaires 1.1. Lire (et écrire) dans un fichier 1.2. Inspecter, nettoyer et transformer une chaîne de caractères 2. Faire des diagrammes 2.1. Diagramme en bâtons tout simple 2.2. Boites à moustaches ------------------------------------------------------------------------ Consignes ========= Pour ce TP comme pour les suivants, la pièce la plus importante sera un fichier tp1-nom-prenom.py contenant votre programme. Le seul fait que votre programme fonctionne ne suffit pas pour avoir une bonne note. Les points suivants seront pris en compte : 1. l'architecture de votre programme (code découpé en fonctions etc.), 2. la lisibilité de votre programme (choix pertinent pour les noms de variables etc.), 3. la présence de commentaires aux endroits appropriés, 4. la présence de documentation pour vos fonctions. Certaines questions appellent à une réponse que vous pouvez mettre en commentaire dans votre fichier tp0-nom-prenom.py. Si vous le souhaitez vraiment, vous pouvez aussi m'envoyer un rapport de TP. Le format de ce rapport sera au choix, mais par ordre de préférence : - dans le corps de votre programme en commentaire - au format texte (mais avec un minimum de mise en page) - au format pdf - au format OpenOffice (.odt) - au format Word (beurk) Attention : les points suivants ne rapportent rien, mais ne pas les respecter pourra retrancher jusqu'à 10 points sur la note finale : - chaque fichier devra comporter un commentaire au début avec vos nom, prénom, filière et numéro du TP. - une exécution du programme principal « à vide » ne devra pas provoquer d'erreur. Liens utiles ============ - le wiki du cours (http://www.lama.univ-savoie.fr/wiki/index.php/INFO719) - la page du langage Python (http://www.python.org) - la documentation des bibliothèques standards (http://docs.python.org/library/index.html) - la documentation de la bibliothèque "Python Imaging Library" (http://www.pythonware.com/library/pil/handbook/index.htm) - PIL et les images (http://www.lama.univ-savoie.fr/~hyvernat/Enseignement/0910/info719/tp0.xhtml#toc3) (TP 0) ============================================================================= 1. Préliminaires ================= 1.1. Lire (et écrire) dans un fichier ====================================== Pour accéder à un fichier du disque dur, Python offre une fonction open(). Cette fonction renvoie une valeur d'un type spécifique : file. Par exemple, f = open('./mon_fichier.txt') assigne le fichier mon_fichier.txt du répertoire courant à la variable f. Par defaut, on ne peut pas écrire dans le fichier. Si on souhaite le modifier et le lire, il faut utiliser f = open('./mon_fichier.txt', 'r+') Dans les 2 cas, la fonction open() échoue si le fichier n'existe pas. D'autre possibilités pour ouvrir un fichier : - 'w+' pour remplacer un fichier. Si le fichier n'existe pas, le crée, sinon, écrase l'ancien fichier. - 'a' pour rajouter des lignes à un fichier existant - ... Quand f contient un fichier, la variable f vient avec de nombreuses fonctions. (On dit que f est un objet et que les fonctions sont des méthodes...) Par exemple : - f.close() pour fermer le fichier, - f.read() pour lire le contenu d'un fichier dans une chaîne de caractères. Si on donne un argument entier à la fonction, en récupère au plus ce nombre d'octets, - f.readline() pour lire une seule ligne du fichier (avec le saut de ligne correspondant), - f.readlines() pour lire toutes les lignes (on récupère une liste de chaînes de caractères), - f.write(str) pour ajouter une chaîne de caractères au fichier. (Il faut que le fichier soit ouvert avec les droit d'écriture.) Par exemple, voici une procédure qui renverse l'ordre des lignes dans un fichier : def renverse(nom): """Lit le fichier 'nom' et crée un fichier 'nom-renverse' qui contient les mêmes lignes que 'nom', mais en partant de la fin. Ne fonctionne pas si le fichier n'existe pas, et écrase le fichier 'nom-renverse' s'il existe""" fichier_initial = open(nom) # ouverture en lecture fichier_renv = open(nom+'-renverse', 'w+') # ouverture en écriture lignes = fichier_initial.readlines() fichier_initial.close() t = len(lignes) for i in range(t): fichier_renv.write(lignes[t-i-1]) fichier_renv.close() Pour rendre ce programme vraiment fonctionnel, il faudrait gérer les erreurs (le fichier nom n'existe pas, le fichier nom-renverse existe déjà, ...) 1.2. Inspecter, nettoyer et transformer une chaîne de caractères ================================================================== Il est assez fréquent que l'on récupère une chaîne de caractères (tapée au clavier, lue dans un fichier etc.) Il faut alors la transformer pour la rendre utile au programme : enlever les espaces supplémentaires, mettre tout en minuscule, ... Python possède de nombreuses fonctions pour ce genre de tâches. Comme les valeurs de type file, les chaînes de caractères sont livrées clé en main avec de nombreuses fonctions. (Les chaînes de caractères sont en fait des objets avec des méthodes.) Si s est une chaîne : - s.strip() nous donne la chaîne s, mais sans les caractères blancs (espaces, tabulations, sauts de ligne) du début et de la fin. On peut enlever d'autres caractères en donnant un argument à la fonction. - s.upper() nous donne la chaîne s en majuscules, s.lower() nous la donne en minuscules. - s.split() pour séparer une chaîne en une liste de mots. (Cette fonction utilise les caractères blancs pour trouver les séparations...) Pour transformer une valeur en chaîne de caractères, il suffit en général d'utiliser la fonction str(). De la même manière, pour transformer une chaîne en nombre entier, il suffit d'utiliser la fonction int(). (Bien entendu, si la chaîne contient des lettres, la conversion ne pourra pas se faire...) QUESTION ######## Écrivez une fonction qui recopie un fichier texte dans un autre, mais en mettant le premier mot de chaque ligne majuscules. def maj(nom): """Recopie le fichier 'nom' en 'nom-maj' en mettant la première lettre de chaque ligne en majuscule.""" ... ... ------------------------- Facultatif Écrivez une fonction qui recopie un fichier texte dans un autre, mais en mettant le numéro de ligne devant chaque ligne : def num_lignes(nom): """Recopie le fichier 'nom' en 'nom-lignes' en rajoutant les numéros de lignes""" ... ... 2. Faire des diagrammes ======================= Le but de cet exercice est de produire un diagramme en bâtons pour des données présentes dans un fichier. Vous aurez donc besoin des fonctions (juste la fonction rectangle() en fait) du tp0 pour dessiner des rectangles... 2.1. Diagramme en bâtons tout simple ===================================== QUESTION ######## Écrivez une fonction batons qui fait la chose suivante : def batons(fichier_donnees, fichier_image, largeur, hauteur, marge=10, coul=(255,0,0), fond=(255,255,255)): """Lit les données (nombres entiers) contenus dans le fichier 'fichier_donnees' et produit un diagramme en bâtons dans le fichier 'fichier_image.png'. Les données sont "en vrac" dans le fichier : sur plusieurs lignes, séparées par un ou plusieurs espaces, ... Le paramètre 'marge' permet de spécifier une marge autour de chaque bâton, les paramètres 'coul' et 'fond' permettent de spécifier les couleur des bâtons et du fond de l'image.""" ... ... Remarque -------- Pour cette question, la fonction map pourra vous servir. Cette fonction prend 2 arguments : une fonction et un tableau. Elle renvoie un tableau qui contient les résultats de la fonction sur chacune des valeurs du tableau. Par exemple : >>> l1 = [1, 2, 3, 4] >>> def carre(x): return(x*x) >>> l2 = map(carre, l1) >>> print l1 [1, 2, 3, 4] >>> print l2 [1, 4, 9, 16] 2.2. Boites à moustaches ========================= Le but de cette question consiste à lire des données dans un fichier et de générer une boite à moustaches (http://fr.wikipedia.org/wiki/Boite_a_moustaches) les représentant. Le fichier contient les données organisées de la manière suivante : - chaque ligne qui commence par « # » (éventuellement avec des espaces avant) est ignorée, - les données sont reparties dans plusieurs ensembles (un ensemble pour chaque boite à moustaches), - chaque ensemble de données est constitué par des nombres flottants séparés par des espaces, des tabulations, ou des saut de ligne simples, - les ensembles sont séparés entre eux par au moins une ligne entièrement vide. Par exemple, le fichier suivant : 3.14 5 12.34 7 -12e-3 12 13 14 15 # les données suivantes ne sont pas marrantes 1.000 1.001 1.002 1.003 1.004 1.005 1.006 1.007 1.008 1.009 # et c'est tout. contient trois ensembles de données : - 3.14, 5, 12.34, 7, -0.012 - 12, 13, 14, 15 - 1.000, 1.001, 1.002, 1.003, 1.004, 1.005, 1.006, 1.007, 1.008, 1.009 QUESTION ######## Écrivez une fonction quartiles : def quartiles(donnees): """calcule les 3 quartiles de la liste de nombres 'donnees'. La valeur de retour est un triplet (q1,q2,q3) où q1 est le premier quartile, q2 la valeur médiane et q3 le troisième quartile.""" ... ... Remarque -------- Pour cette fonction, vous pouvez utiliser la méthode sort() qui permet de trier un tableau de valeur. Si t est un tableau, alors t.sort() a pour effet de trier le tableau t par ordre croissant. QUESTION ######## Écrivez une fonction ensemble_suivant : def ensemble_suivant(fichier): """Cette fonction renvoie le prochain ensemble de données du fichier 'fichier' sous forme d'un tableau de flottants. L'argument est un fichier (obtenu par exemple avec un "open").""" ... ... Remarque -------- Rappel : si t est un tableau, vous pouvez rajouter des valeurs à la fin avec la méthode extend : >>> t = [1, 2, 3, 4] >>> t.extend([42, 666]) >>> print t [1, 2, 3, 4, 42, 666] QUESTION ######## En utilisant ces deux fonctions, programmez la fonction boites_a_moustache. Cette fonction prendra au moins 2 arguments : - le nom du fichier de données, - le nom du fichier image que l'on veut générer (sans l'extension .png). Vous pouvez ajouter des arguments (optionnels ou obligatoires) pour - couleurs, - tailles de l'image ou des boites, - types de boites, - légende (avec la bibliothèque ImageDraw et la méthode txt()), - possibilité d'avoir une boite à moustache pour l'ensemble de toutes les données, - ... Veillez à documenter ce que vous faites. Remarque : vous pouvez créer des fonctions supplémentaires pour certaines taches.