Langages de scripts, automatisation de commandes et
production de documents structurés :
5. La «nouvelle garde» : Python et Ruby
gilles.hunault "at" univ-angers.fr
Table des matières cliquable
1. Python : commandes en session interactive
2. Python : archivage incrémental de fichiers XML
3. Python : créer les fichiers dictionnaires d'un texte
5. Python/Tk : conversion pouce/cm
6. Ruby : commandes en session interactive
7. Ruby : archivage incrémental de fichiers XML
Il est possible d'afficher toutes les solutions via ?solutions=1.
1. Python : commandes en session interactive
Essayer en mode interactif avec python 3 de donner la ou les instructions qui répondent aux mêmes questions que pour Perl en mode interactif, exercice 4 de la série 3.
Solution : masquer la solution
Voici la solution avec Python 3 :
$gh> python3 Python 3.3.0 (default, Nov 13 2012, 10:37:00) [GCC 4.4.3] on linux Type "help", "copyright", "credits" or "license" for more information. >>> 16**4 65536 >>> 2012%128 # pas 2012^128 qui renvoie 1884 92 >>> hex(ord("A")) , int("FFF",16) , ord("a") , chr(98) ('0x41', 4095, 97, 'b') >>> cmd = "prog --fmt tex --nbdec 4 --fichier demo.rex" >>> import re >>> opt = re.search("--fmt (.*?) ",cmd) ; opt.group(1) 'tex' >>> phr = "A2837 12 18 37 25" >>> tm = phr.split(" ") >>> tm.pop(0) 'A2837' >>> " ".join(tm) '12 18 37 25' >>> f = 1 >>> for x in range(2,9) : ... f *= x ... # fin pour x ... >>> f 40320 >>> import datetime ; datetime.datetime.now() datetime.datetime(2012, 12, 1, 17, 58, 50, 252771) >>> v = "12 5 20 8 15" >>> s = 0 >>> tv = v.split(" ") >>> for lv in tv : ... s += int(lv) ... # fin pour lv ... >>> s /= len(tv) >>> s 12.0 >>> quit()
2. Python : archivage incrémental de fichiers XML
Implémenter une version Python de la sauvegarde incrémentale de fichiers XML comme pour l'exercice 7 de la série 2.
Solution : masquer la solution
Consulter le fichier archcd.py :
# -*- coding: iso-8859-15 -*- import os # pour os.path et os.system numarchive = 1 nomarchive = "lesxml" + ("%03d" % numarchive) + ".tar" while (os.path.isfile(nomarchive)) : numarchive += 1 nomarchive = "lesxml" + ("%03d" % numarchive) + ".tar" # fin de tant que specfic = "*.xml" cmd = "tar -cf " + nomarchive + " " + specfic os.system(cmd) print("[python] archivage des fichiers "+ specfic + "dans " + nomarchive + " terminée")
3. Python : créer les fichiers dictionnaires d'un texte
Essayer de réaliser l'exercice 3 de la série 2 (création des dictionnaires) en Python.
Solution : masquer la solution
Consulter le fichier dico.py :
# -*- coding: iso-8859-15 -*- import sys, os, codecs, re, string from textwrap import dedent # aide eventuelle if (len(sys.argv)==1) : aide = ''' dico.py ; creation des dictionnaires alphabetiques et frequentiels d'un texte syntaxe : python3 dico.py FICHIER exemple : python3 dico.py texte.txt les fichiers produits sont dico.tpm et dico.tpo dico.tpm : tri par mot croissant dico.tpo : tri par frequence decroissante puis par mot croissant an cas d'egalite ''' #print(aide.decode('iso-8859-1')) print(aide) sys.exit() # fin de si # si le fichier n'existe pas, on ne peut pas continuer fic = sys.argv[1] if (not os.path.isfile(fic)) : print("le fichier "+fic+" n'existe pas.\n") sys.exit() # fin de si # arrivé ici, le fichier existe exclude = set(string.punctuation) nbl = 0 nbm = 0 nbd = 0 tdm = {} fh = open(fic,'r') for lig in fh : nbl += 1 # on enlève la ponctuation # la ligne qui suit ne gere pas bien l'apostrophe # lig = ''.join(ch for ch in lig if ch not in exclude) lig = re.sub("[-.!;\']"," ",lig) lig = lig.strip() # on fait un tableau de mots tm = lig.split(" ") for mot in tm : if (not mot=="") : nbm = nbm + 1 if (not (mot in tdm)) : tdm[mot] = 1 nbd += 1 else : tdm[mot] += 1 # fin si # fin si # fin pour mot # fin de pour lig fh.close() print(" Analyse du fichier "+fic) print(" ",nbl," ligne(s) ",nbm," mot(s)"," et ",nbd," mots differents") # stockage alphabetique ; on en profite pour creer une structure # adaptee au tri frequentiel sachant que le tri en python est "stable" fn1 ="dico.tpm" fs1 = open(fn1,'w') lmo = [] for (k,v) in sorted(tdm.items()) : fs1.write("%-25s %6d\n" % (k,v) ) lmo.append((k,v)) # fin de pour k,v fs1.close() print("le fichier ",fn1," contient les mots par ordre alphabetique.") ; # stockage frequentiel fn2 ="dico.tpo" fs2 = open(fn2,'w') #for elt in lmo.sort() : #fs1.write("%-25s %6d\n" % (k,v) ) #print("%-25s %6d\n" % (k,v) ) # fin de pour k,v fs2.close() print("le fichier ",fn2," contient les mots par ordre decroissant d'occurrences.")
4. Python : à réindenter
Python est un des rares langages à imposer une indentation pour les blocs. Ainsi le programme malindent.py ci-dessous n'est pas exécutable. Réindenter pour qu'il s'exécute correctement. On devra obtenir comme résultat d'exécution du fichier correct le fichier bienindent_res.txt.
# mini mvc en python3 class Model: def get_post(self): return {"title":"A test","body":"An example.."} class View: def display(self,items): print('Title:' + items['title'] + '\n'+'Body:' + items['body']) class Controller: def __init__(self): self.model=Model() self.view=View() def main(self): post=self.model.get_post() self.view.display(post) mvc=Controller() mvc.main()Solution : masquer la solution
Consulter le fichier bienindent.py :
class Model : def get_post(self) : return {"title":"A test","body":"An example.."} class View : def display(self,items) : print('Title:' + items['title'] + '\n'+'Body:' + items['body']) class Controller : def __init__(self) : self.model=Model() self.view=View() def main(self) : post=self.model.get_post() self.view.display(post) mvc=Controller() mvc.main()
5. Python/Tk : conversion pouce/cm
Implémenter une version Python puis une version Python/Tk de la conversion pouce/cm définie dans l'exercice 9 de la série 3.
Solution : masquer la solution
La solution est dans la page applications transversales de ce cours. On laisse le soin à la lectrice et au lecteur de retrouver cette page.
6. Ruby : commandes en session interactive
Essayer en mode interactif avec irb de donner la ou les instructions qui répondent aux mêmes questions que pour Perl en mode interactif, exercice 4 de la série 3.
Solution : masquer la solution
$gh>irb irb(main):001:0> 16**4 => 65536 irb(main):002:0> 2012%128 => 92 irb(main):003:0> [ "A"[0].to_s(16) , "FFF".to_i(16) , "a"[0].to_s(10) , "%c" % 98 ] => ["41", 4095, "97", "b"] irb(main):004:0> cmd = "prog --fmt tex --nbdec 4 --fichier demo.rex" => "prog --fmt tex --nbdec 4 --fichier demo.rex" irb(main):005:0> cmd =~ /--fmt (.*?) / ; $1 => "tex" irb(main):006:0> phr = "A2837 12 18 37 25" => "A2837 12 18 37 25" irb(main):007:0> tab = phr.split(" ") => ["A2837", "12", "18", "37", "25"] irb(main):08:0> tab.delete_at(0) => "A2837" irb(main):09:0> tab.join(" ") => "12 18 37 25" irb(main):010:0> f = 1 => 1 irb(main):011:0> (2..8).each do |n| ; f *= n ; end ; f => 40320 irb(main):012:0> tv = "12 5 20 8 15".split(" ") => ["12", "5", "20", "8", "15"] irb(main):013:0> tv.each { |v| s += v.to_i } ; s => 60 irb(main):014:0> s /= tv.length => 12 irb(main):015:0> Time.now => Sat Dec 01 19:01:18 +0100 2012 irb(main):016:0> quit()
7. Ruby : archivage incrémental de fichiers XML
Implémenter une version Ruby de la sauvegarde incrémentale de fichiers XML comme pour l'exercice 7 de la série 2.
On profitera pour vérifier que l'exécution du script archcdtout.sh pour bash fournit bien le résultat escompté indiqué dans la solution.
Solution : masquer la solution
Consulter le fichier archcd.rb :
numarchive = 1 nomarchive = "lesxml" + sprintf("%03d",numarchive) + ".tar" while File.exists?(nomarchive) numarchive += 1 nomarchive = "lesxml" + sprintf("%03d",numarchive) + ".tar" end # fin tant que specfic = "*.xml" cmd = "tar -cf " + nomarchive + " " + specfic rc = IO.popen(cmd) print "[ruby] archivage des fichiers "+ specfic + "dans " + nomarchive + " OK.\n"Le script bash proposé archcdtout.sh efface toutes les archives lesxml*.tar puis exécute chacun des script d'archivage incrémental dans les différents langages.
# fichier archcdtout rm lesxml*.tar regina archcd.rex perl archcd.pl wish archcd.tcl php archcd.php python archcd.py ruby archcd.rbSi tout se passe bien, on doit obtenir (au cadrage et aux encodages près) :
[rex] archivage des fichiers *.xml dans lesxml001.tar OK [perl] archivage des fichiers *.xml dans lesxml002.tar terminée [tcl] archivage des fichiers *.xml dans lesxml003.tar terminée. [php] archivage des fichiers *.xml dans lesxml004.tar terminée [python] archivage des fichiers *.xml dans lesxml005.tar terminée [ruby] archivage des fichiers *.xml dans lesxml006.tar terminée.
8. Ruby : créer les fichiers dictionnaires d'un texte
Essayer de réaliser l'exercice 3 de la série 2 (création des dictionnaires) en Ruby.
Solution : masquer la solution
Consulter le fichier dico.rb :
# encoding: ISO-8859-15 # # (gH) -_- dico.rb ; TimeStamp (unix) : 20 Février 2015 vers 18:09 # aide éventuelle if ARGV.empty? then puts " syntaxe : ruby dico.rb FICHIER" puts " exemple : ruby dico.rb candide.txt" exit(-1) end # fin si # test si le fichier est présent nomfictxt = ARGV.first puts " lecture de #{nomfictxt} " if !File.exists?(nomfictxt) then puts " fichier #{nomfictxt} non vu. Stop." exit(-1) end # fin si # arrivé ici, on peut construire le dictionnaire nbl = 0 # nombre de lignes nbm = 0 # nombre de mots freqs = Hash.new(0) fictxt = File.open(nomfictxt, "r:ISO-8859-15") fictxt.each_line { |ligne| nbl = nbl + 1 # suppression de la ponctuation ligne.tr!("!?,;.'"," ") ligne.gsub!(/--/,"") # on découpe en mots ligne.downcase.split(/\s+/).each { |mot| freqs[mot] += 1 nbm += 1 } # fin pour chaque mot } # fin pour chaque ligne puts "#{nbm} mots vus sur #{nbl} lignes." # tri alphabétique et affichage puts "Dictionnaire alphabétique" puts "-------------------------" freqs.sort.each { |mot,cnt| puts sprintf("%-15s %5d",mot,cnt) } # fin pour chaque mot # tri par fréquence et affichage puts "Dictionnaire fréquentiel" puts "------------------------" freqs.sort_by{ |k, v| [-v,k] }.each { |mot,cnt| puts sprintf("%-15s %5d",mot,cnt) } # fin pour chaque mot
9. Ruby/Tk : conversion pouce/cm
Implémenter une version Ruby puis une version Ruby/Tk de la conversion pouce/cm définie dans l'exercice 9 de la série 3.
Solution : masquer la solution
La solution est dans la page applications transversales de ce cours. On laisse le soin à la lectrice et au lecteur de retrouver cette page.
Code-source php de cette page ; code javascript utilisé. Retour à la page principale du cours.
Retour à la page principale de (gH)