if __name__ == `__main__`
Transcription
if __name__ == `__main__`
Formation Python Traitement et visualisation de données scientifiques Jour 1 – Le langage Fernando NIÑO Legos/IRD Janvier 22-30 2009 Jour 1 Formation Python Python - Le Langage Introduction Présentation Python vs Les autres Python vs Perl Travailler avec Python Le Langage 2 © 2009 Fernando NIÑO Les langage Python • Orienté objet – facilite la décomposition et la réutilisation • Syntaxe claire – Pas de raccourcis « magiques » incompréhensibles, chers aux utilisateurs Perl (i.e. $<, $_, ...). • Facile à appréhender – Ca, on verra... • Trois utilisations type: – script – programme à part entière – de la colle 3 © 2009 Fernando NIÑO Python vs. les autres Langage Nombre d’instructions p.r. à C C 1 C++ 2.5 Fortran 2.5 Java 2.5 MS Visual Basic 4.5 Perl 6 Python 6 Smalltalk 6 Expressivité des langages (Code complete , Steve McConnell.) © 2009 Fernando NIÑO 4 Ce qu’on retient • Python, c’est chic ! • Trois modes: – script (remplace bash) – programmation (remplace C) – de la colle (permet de donner un visage unifié à un amas de code) 5 © 2009 Fernando NIÑO Jour 1 – Le langage Formation Python Python - Le Langage Présentation Installation Les versions Travailler avec Python Les modules Python 3.0 Prise en main PYTHONPATH Le Langage 6 © 2009 Fernando NIÑO Travailler avec Python • Beaucoup de modules disponibles – sur le web – sur CheeseShop: http://pypi.python.org • Mode script – mode « production » quand on a un programme qui marche – mode « batch » classique (csh, bash, awk,....) • Mode interactif – Facile à déboguer : avantages des langages de script – pas de phase de compilation/éxecution – on peut tester en ligne de commande directement – exploration du langage / des données 7 © 2009 Fernando NIÑO Installation de Python • Enthought Python Distribution est installé – http://www.enthought.com/products/epd.htm • Les versions: – – – – – – – Python (un alias vers...) Python 2.4 (30/12/2004) Python 2.5 (2.5.4 le 23/12/2008) Python 2.6 (1/10/2008) Python 3.0 (3/12/2008) Win32 Python – adapté pour Windows IronPython (v1: 09/2006; v2: 12/2008) - .NET framework • Les modules – si python pur: python setup.py install – ou easy_install <module> Index) # Cherche PyPI (Package 8 © 2009 Fernando NIÑO Python 3.0 - Version incompatible • print devient une fonction, – from __future__ import print_function • Unification des types texte vers UNICODE. • Type bytes and bytearray; • Elimination de compatibilité ancienne: – – – – old-style classes integer-truncating division (1/2=0 ==> 1/2=0.5 & 1//2=0 string exceptions implicit relative imports. • Outil de conversion 2to3 – http://docs.python.org/3.0/whatsnew/3.0.html 9 © 2009 Fernando NIÑO Prise en main python • Trouvez l’interpreteur Python EPD with Py2.5 (4.0.30002 ) -- http:// www.enthought.com/epd Python 2.5.2 |EPD with Py2.5 4.0.30002 | (r252:60911, Oct 15 2008, 16:58:38) [GCC 4.0.1 (Apple Computer, Inc. build 5370)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> • Faites quelque chose ! >>> print "Je fais quelque chose" Je fais quelque chose >>> • ctrl-D pour sortir 10 © 2009 Fernando NIÑO Installation des modules Python • En pratique: pour python interactif il existe IPython (ipython.scipy.org) • Mais....c’est un module. Installons-le: cd ipython-0.7.2 python setup.py install --prefix=d:\python – ou python setup.py install --home=/home/moi • Par défaut, les modules sont installés dans l’arborescence de l’installation python utilisée: /usr/lib/python2.5/site-packages • En windows, l’installateur pose la question... 11 © 2009 Fernando NIÑO Installation mpmath • Installation standard d’un paquetage: cd mpmath python setup.py install • Test: ipython -pylab import mpmath from mpmath import sin, cos, exp mpmath.cplot(lambda z: mpmath.exp(1/z), [-2, 2], [-2, 2]) mpmath.plot([cos, sin], [-4, 4]) mpmath.cplot(sin,[-5, 5], [-5,5]) 12 © 2009 Fernando NIÑO mpmath test • On peut taper tout le code ou ipython import mpmathtest puis, editez le fichier en changeant la ligne commentée import mpmathtest comportement ? Appréciez fichier .pyc help reload 13 © 2009 Fernando NIÑO PYTHONPATH • Les scripts python utilisent en général des modules python (pour ne pas réinventer la roue). – Un module est un objet chargé par l’interpréteur Python à partir d’un fichier texte qui regroupe des variables, classes et fonctions. En général, c’est un fichier .py • Comment se fait la recherche des modules ? – Dans le répertoire courant – Installé a posteriori : vérifie la variable PYTHONPATH – Python Standard Library (PSL) : fournit avec l’installation Python • PSL: – une installation « administrateur » se fait à l’intérieur de l’installation Python /usr/lib/python2.5/site-packages 14 © 2009 Fernando NIÑO Vérification de l’environnement • Les chemins de recherche de Python >>> import sys >>> sys.path ['', '/System/Library/Frameworks/Python.framework/ Versions/2.3/lib/python23.zip', ...,'/System/ Library/Frameworks/Python.framework/Versions/2.3/ Extras/lib/python'] >>> exit 'Use Ctrl-D (i.e. EOF) to exit.' >>> ^D 15 © 2009 Fernando NIÑO Documentation python • Sur *nix: pydoc -p 7464 http://localhost:7464/ • Sur Windows: chercher d:\Python\Tools\Scripts\pydocgui 16 © 2009 Fernando NIÑO Ce qu’on retient • On utilise Python 2.5 car c’est le plus stable: 2.6 est une version de transition, mais Enthought ne le fournit pas encore • La version 2.6 est de transition vers Python 3.0 • Python 3.0 est incompatible avec 2.x : il faut attendre 1-3 ans à que les librairies scientifiques soient compatibles. • PYTHONPATH et sys.path sont très importants • python setup.py install • import xxxx permet d’utiliser xxxx.fonction 17 © 2009 Fernando NIÑO Jour 1 Formation Python Python - Le Langage Présentation Travailler avec Python Les bases du langage Structures de données Contrôle du flux d'exécution Gestion des fichiers Le Langage Encapsulation POO Dérivation Réutilisation Gestion des erreurs Exceptions Logger 18 © 2009 Fernando NIÑO Le langage • C’est un langage dynamique: – toutes les instructions sont exécutées au fur et à mesure, y compris les déclarations. import sys # Module d’accès au systeme Instruction print sys.path Commentaire monchemin=’/sw/lib/’ sys.path.append(monchemin) print sys.path – on peut modifier le chemin de recherche de modules, comme avec PYTHONPATH. Variable • C’est un langage où l’indentation est significative import sys print sys.path #---> ERREUR de syntaxe 19 © 2009 Fernando NIÑO L’indentation • L’indentation est celle de l’utilisateur: n espaces d’indentation. – C’est bien: ce qu’on voit est ce qu’il éxecute (pas de problème d’accolade fermée trop tôt comme en C...) for(i=0; i < n; i++) { for (j=0; j < n; j++) x=x*j; y=y*i+j; } piège for i in range(0,n): for j in range(0,n): x=x*j y=y*i+j 20 © 2009 Fernando NIÑO L’indentation (2) • Le problème: – quand il y a plusieurs personnes qui éditent un programme – quand on mélange les éditeurs (configuration de largeur de TAB différentes) – ...mais seulement si on utilise des tabulations • La solution: pas de tabulations !!!!!! – chaque editeur à sa solution (setq indent-tabs-mode nil) (setq-default tab-width 4) set tabstop=4 set expandtab # ;; dans EMACS Dans .vimrc 21 © 2009 Fernando NIÑO L’encodage • Le problème: – lorsqu’on a un fichier quelconque, on ne sait pas comment interpréter son contenu: – binaire ? – big endian / little endian ? – ASCII/ EBCDIC/Unicode ??? – il faut toujours des métadonnées • Par défaut, l’interpreteur Python veut son code en ASCII (encodage.py) (UTF-8 pour Py3k). • Si l’on veut autre chose, il faut utiliser l’entete: #!/usr/bin/env python # -*- coding: iso-8859-15 -*... Première ou deuxième ligne obligatoirement 22 © 2009 Fernando NIÑO Références • Dans ce qui suit (syntaxe du langage), les références utilisées sont – Programmation Python Tarez Ziadé, Ed. Eyrolles 2006 – Learning Python (3eme Ed) Mark Lutz Ed. O’Reilly 2007 - Python Scripting for Compuational Science Hans-Peter Langtangen, Springer 2008 23 © 2009 Fernando NIÑO Les littéraux • Alphanumériques – Chaînes simples: print “Ceci est une chaîne simple, Python gère Unicode à partir de la version 2.4” – Chaînes triplées print ”””Voici les trois paires de guillemets qui permettent d’écrire plusieurs lignes sans avoir a concatener les chaînes””” – Chaînes Unicode print u”Ont un prefixe U ou u” – Chaînes “brutes” (ou raw) print r'Eliminent l\'interpretation de backslash\n' Eliminent l\'interpretation de backslash\n print 'Eliminent l\'interpretation de backslash\n' Eliminent l'interpretation de backslash 24 © 2009 Fernando NIÑO Texte et Python 3.0 • Dans Python3.0 il y a deux types de données: – texte : type str – données : type bytes • C’est tout ! Tout est en unicode; le melange de str et bytes donnce TypeError • Bonne simplification, mais le code ancien en souffre. • L’encodage de la source est par défaut UTF-8 25 © 2009 Fernando NIÑO Les littéraux • Numériques – entiers simples ou longs: conversion automatique à partir de Python 2.4: In [34]: In [35]: Out[35]: In [36]: In [37]: Out[37]: In [38]: Out[38]: In [39]: In [40]: Out[40]: i=1000 type(i) <type 'int'> i=i*i*i*i*i i 1000000000000000L type(i) <type 'long'> i=1000 type(i) <type 'int'> 26 © 2009 Fernando NIÑO Les entiers en Python 3.0 • Correction d’ambiguités: x/y = ??? – x=1 – y=2 – x/y = 0 – x=1 – y=2.0 – x/y = 0.5 • Dans Python 2.x: – 1/2 = 0 • Dans Python 3.0 – 1/2 = 0.5 – 1//2=0 27 © 2009 Fernando NIÑO (Parenthèse: les types) • Python est un langage faiblement typé – Donc, le type d’une variable dépend de son contenu i=10 # i est un entier i=’voici’ # i est une chaîne de caractères • Pour avoir des informations sur un objet: – Son type type(i) – De quoi est-il capable (méthodes applicables) ? dir(i) • Avec ipython ?i • Le syndrome du canard (“duck-typing”) – si ça marche comme un canard et fait coing-coing, c’est un canard. 28 © 2009 Fernando NIÑO Les littéraux • Numériques – virgule flottante (comme d’habitude...) x=0.001 y=1.2E-9 – nombres complexes notation génie électrique: u=5j # pour ne pas confondre avec le courant v=3 + 4.5j • Exercice: – avec python faites type(u), type(v), type(x), u+v, dir(u+v) – avec dir, quelles fonctions remarque-t-on ? – avec ipython faites la même chose et en plus: ?u 29 © 2009 Fernando NIÑO Première approche de IPython • Avec ? ou ?? vous obtenez des renseignements sur un objet • Avec tabulation vous complétez les mots import sys sys.<TAB> sys.pa<TAB> • Un bon mécanisme de historique (ctrl-n, ctrl-p, hist, hist -n) 30 © 2009 Fernando NIÑO Ce qu’on retient • L’indentation est significative • On indique l’encodage au début #!/usr/bin/env python # encoding: utf-8 • Langage faiblement typé: une variable peut changer de type en cours de route • Le syndrome du canard – si ça marche comme un canard et fait coing-coing, c’est un canard. • ipython – variable? # donne des informations – var<TAB> # complète – %pdb # Variable magique invoque le debogueur 31 © 2009 Fernando NIÑO Formation Python Python - Le Langage Présentation Travailler avec Python Les bases du langage Structures de données Contrôle du flux d'exécution Gestion des fichiers Le Langage Encapsulation POO Dérivation Réutilisation Gestion des erreurs Exceptions Logger 32 © 2009 Fernando NIÑO Les types standard • Valeur unique None # Absence de valeur (faux en calcul booléen) • Nombres entiers int long bool • Virgule flottante – toujours double précision (code C sous-jacent) • Decimal (librairie standard >= 2.4) – representation exacte – interaction entiers et decimal uniquement import decimal dir(decimal) # peu de fonctions (pas de trigo.) 33 © 2009 Fernando NIÑO Les types standard • Les séquences – collection finie d’éléments ordonnés – accessibles par indexation i=sequence[n] – indexation négative: à partir du dernier – tranches: index min et max et pas sous-seq=sequence[min:max] # ou [debut::pas] – Primitives de séquences: len(), min(), max(),sum() • Exercice: – utilisant range et premiers entiers xrange calculez la somme des 57 34 © 2009 Fernando NIÑO Solution In [34]: seq=range(0,100) In [35]: print sum(seq[0:58]) 1653 In [36] : sum(xrange(58)) 1653 – Vérification: somme(N)=N(N+1)/2 In [36]: print 57*58/2 1653 35 © 2009 Fernando NIÑO Les chaînes de formatage • Pour ceux qui connaissent C, c’est pareil ... • Pour ceux qui ne connaissent pas.... – On remplace un indicateur de format %x par la valeur indiqué. In [1]: nom='Butterfly' In [2]: print "Bonjour madame %s" % nom Bonjour madame Butterfly – Si plusieurs indicateurs de format, on utilise des tuples In [4]: x = 3.45 In [5]: print 'Bonjour madame %s, votre avoir est de %.2f EUR' % (nom,x) Bonjour madame Butterfly, votre avoir est de 3.45 EUR 36 © 2009 Fernando NIÑO Les chaînes de formatage • Les indicateurs les plus utilisés: %s %f %e # pour les strings # pour les virgule flottante # virgule flottante notation scientifique • Largeur.Precision – Comme dans fortran, pour les valeurs à virgule flottante on peut avoir une largeur et une précision d’affichage In [6]: x=3.45435 In [7]: print '%08.2f' % x 00003.45 37 © 2009 Fernando NIÑO Tuples • Ce sont des séquences qui ont des éléments hétérogènes • ils ne peuvent pas être modifiés – donc, copie si modification nécessaire In [20]: tuple=('un',1,'deux',2) In [21]: tuple[2]='3' --------------------------------exceptions.TypeError Traceback (most recent call last) 38 © 2009 Fernando NIÑO Listes • La seule séquence modifiable est la liste: Comme le tuple, mais se créé avec des [ ] liste=[] liste = range(0,100) # vide # déjà vu • Opérations interessantes: liste.append(element) liste.extend(liste2) liste.insert(position,element) liste.remove(element) liste.pop(position) liste.index(element) liste.count(element) liste.sort() liste.reverse() 39 © 2009 Fernando NIÑO Listes • La seule séquence modifiable est la liste: Comme le tuple, mais se créé avec des [ ] liste=[] liste = range(0,100) # vide # déjà vu • Opérations interessantes: Syntaxe ‘.’ de la POO: équivalent à liste.append(element) append(liste,element) liste.extend(liste2) liste.insert(position,element) liste.remove(element) liste.pop(position) liste.index(element) liste.count(element) liste.sort() liste.reverse() © 2009 Fernando NIÑO 39 Exercice • Créer une liste de nombres comme ceci: – 0 à 10 – 50 à 80 – 90 à 100 • obtenir une sous-liste avec tous les nombres pairs • les présenter du plus grand au plus petit 40 © 2009 Fernando NIÑO Solution liste=range(0,10) # ou =list(xrange(0,10)) liste.extend(range(50,80)) liste.extend(range(90,100)) liste len(liste) # Nombres pairs pairs=liste[::2] # Que se passe-t-il si l’on fait liste[::2].reverse() #ou si l’on fait pairs_inverse=pairs.reverse() 41 © 2009 Fernando NIÑO Les dictionnaires • Dictionnaires, mappings ou hash • associations de clés et valeurs In [23]: dict={'a':’Sara’, 'b':’Mathilde’, 'c':None } In [24]: dict Out[24]: {'a': ‘Sara’, 'c': None, 'b': ‘Mathilde’} – Remarquez que l’ordre est quelconque • Pour le parcourir In [25]: Out[25]: In [26]: Out[26]: In [27]: Out[27]: dict.keys() ['a', 'c', 'b'] dict.values() [1, None, 2] dict['b'] 2 42 © 2009 Fernando NIÑO Les dictionnaires • Opérations courantes – Insertions dict={} # Sans cela, ERREUR !! dict['b']=’Eric’ dict dict['b']=3 dict – Test dict.has_key('b') dict.has_key('a') – Parcours (en Python 3.0 ce ne sont plus de listes !) dict.items() dict.keys() dict.values() 43 © 2009 Fernando NIÑO Dictionnaires - exemples • Exemple : traitement d’une liste de fichiers – nous avons une liste de noms de fichiers avec répétitions – il faut les traiter seulement une fois. liste=['un','deux','trois','deux','un'] traites={} for fichier in liste: if traites.has_key(fichier): pass else: print "Fichier %s traite" % fichier traites[fichier]=True 44 © 2009 Fernando NIÑO Les blocs, les variables • Sont identifiés par l’indentation et commencent par un ‘:’ for i in range(0,5) : print “je suis dans un bloc” print “j’imprime %d” % i • Les variables sont des chaîne de caractères alphanumériques: Jesuisunevariable=1 JESUIS_une-variable=2 BREF_rien_d’anormal=3 # Erreur:‘-’ est un opérateur # Erreur: l’apostrophe... 45 © 2009 Fernando NIÑO Ce qu’on retient • Listes: [ a,b,c] opérations – append() – slicing • Tuples: (a,b,c) immuables: utilisés pour param. • Dictionnaires: { a:1, b:2, c:3 } associations – has_key() – values() – keys() • Blocs: delimités par deux-points ‘:’ for line in f.readlines(): print line 46 © 2009 Fernando NIÑO Formation Python Python - Le Langage Présentation Travailler avec Python Les bases du langage Structures de données Contrôle du flux d'exécution Gestion des fichiers Le Langage Encapsulation POO Dérivation Réutilisation Gestion des erreurs Exceptions Logger 47 © 2009 Fernando NIÑO Les boucles for (encore) • On a déjà vu les boucles for for i in liste: print i # Même syntaxe que bash • Il existe des clauses break et continue for i in listenum: if (i > 0): continue print “i est negatif” if (i == 0): break for i in range(0,6): print i else: print "fin" 48 © 2009 Fernando NIÑO Les conditionnels • On l’a vu...cela s’appelle if if i > 3: print “plus grand que 3” elif i > 10: print “plus grand que 10” else: print “plus petit que 3” 49 © 2009 Fernando NIÑO Les boucles while • Classiques while i < 4: print i else: print “c’est fini” – la clause else est exécutée à la fin de la boucle (sauf si break) – continue existe aussi, comme pour le for 50 © 2009 Fernando NIÑO Structure d’un programme • La structure d’un programme est en général: – déclaration des librairies utilisées – définition des fonctions utilisateur – programme principal import sys def maroutine(param1,param2): param1=sys.path sys.path.append(param2) x=None maroutine(x,'/home/fnino/python2.3') sys.path 51 © 2009 Fernando NIÑO Gabarit d’un script simple #!/usr/bin/env python # encoding: utf-8 """ untitled.py : gabarit simple Created by Fernando NIÑO on 2009-01-19. """ import sys import os def main(): pass if __name__ == '__main__': main() 52 © 2009 Fernando NIÑO Import • Python est un langage dynamique • import est une commande comme une autre ! • On peut donc la faire conditionnelle: if il_la_faut == True : from malibrairie import * else: pass # Ne fait rien, mais python est content ! • • • • import : l’inclut dans l’environnement d’exécution mais tout est bien rangé: namespaces pour l’utiliser il faut la qualifier: sys.path Pour l’éviter il existe from 53 © 2009 Fernando NIÑO Le programme principal • Comme un script quelconque, il exécute au fur et à mesure qu’il trouve des instructions: – – – – import est une instruction def aussi s’il trouve des instructions, on y va ! mais, on peut savoir si un programme est principal ou non: if __name__ == ‘__main__’: print “je suis un programme principal” – cela s’utiliser pour tester des sous-programmes 54 © 2009 Fernando NIÑO Ce qu’on retient • Les habituels – – – – – for if while break continue • L’organisation de l’espace de nommage (namespaces): – import – module.fonction 55 © 2009 Fernando NIÑO Formation Python Python - Le Langage Présentation Travailler avec Python Les bases du langage Structures de données Contrôle du flux d'exécution Gestion des fichiers Le Langage Encapsulation POO Dérivation Réutilisation Gestion des erreurs Exceptions Logger 56 © 2009 Fernando NIÑO Gestion des fichiers • La base: l’objet fichier: fournit par open f = open(‘toto’,’r’) for line in f.readlines(): print line f.close() • Détail: les chemins: windows n’est pas *nix import os.path ici=os.path.realpath(os.curdir) fich=os.path.join(ici,’nouveaufich.txt’) if os.path.exists(fich) and os.path.isfile(fich): print “Le fichier existe déjà” 57 © 2009 Fernando NIÑO Expressions rationelles (regulières) • Ce sont des “motifs” des recherche • Un sujet à part entière... mais relativement simple pour des choses simples: m=re.match ("ab","cab") # Exact m=re.search ("ab","cab") # Sous-ensemble • Quantificateurs: . et .* • Limites: ^, $ 58 © 2009 Fernando NIÑO Examples des regexp 'abcdefftp://toto.org/fich.zip/ghijklmnopq' r1=’^.*ftp’ r2=’ftp.*$’ r3=’^.*$’ r4=’ftp.*?zip’ • Example: chercher la chaîne “ftp://xxxx.zip” regex = re.compile('ftp://.*?\.zip') for m in re.finditer(regex,line): res=m.group() # Non-greedy 59 © 2009 Fernando NIÑO Exercice: Chercher “ftp://... .zip” • Dans le fichier “modis” afficher toutes les addresses de fichiers zip, en enlevant le “.zip” • Aide: utiliser re.sub 60 © 2009 Fernando NIÑO Solution: parsemessages.py def main(argv=None): if argv is None: argv = sys.argv if len(argv) != 2: print help_message nomf = argv[1] f=open(nomf,'r') regex = re.compile('ftp://.*?\.zip') # Non-greedy zipre = re.compile('\.zip') for line in f.readlines(): for m in re.finditer(regex,line): res=m.group() print re.sub(zipre,'/',res) f.close() 61 © 2009 Fernando NIÑO Exemple: lister des fichiers • Lister l’arborescence de fichiers: – implique accéder au listing au système de fichiers – utilise la bibliothèque standard python import fnmatch, os.path – documentation print fnmatch.__doc__ print os.path.walk.__doc__ – ou sur ipython fnmatch? os.path.walk ? – ou encore pydoc /usr/lib64/python2.3/pydoc.py -p 34567 62 © 2009 Fernando NIÑO Exemple (exListeRep.py) import fnmatch, os def find(pattern, startdir=os.curdir): matches = [] os.path.walk(startdir, findvisitor, (matches, pattern)) return matches def findvisitor((matches, pattern), thisdir, nameshere): for name in nameshere: if fnmatch.fnmatch(name, pattern): fullpath = os.path.join(thisdir, name) matches.append(fullpath) if __name__ == '__main__': import sys namepattern, startdir = sys.argv[1], sys.argv[2] for name in find(namepattern, startdir): print name © 2009 Fernando NIÑO 63 Exemple (exListeRep.py) import fnmatch, os def find(pattern, startdir=os.curdir): matches = [] os.path.walk(startdir, findvisitor, (matches, pattern)) return matches def findvisitor((matches, pattern), thisdir, nameshere): for name in nameshere: if fnmatch.fnmatch(name, pattern): fullpath = os.path.join(thisdir, name) matches.append(fullpath) if __name__ == '__main__': import sys namepattern, startdir = sys.argv[1], sys.argv[2] for name in find(namepattern, startdir): print name © 2009 Fernando NIÑO 63 Exemple (exListeRep.py) import fnmatch, os def find(pattern, startdir=os.curdir): matches = [] os.path.walk(startdir, findvisitor, (matches, pattern)) return matches def findvisitor((matches, pattern), thisdir, nameshere): for name in nameshere: if fnmatch.fnmatch(name, pattern): fullpath = os.path.join(thisdir, name) matches.append(fullpath) if __name__ == '__main__': import sys namepattern, startdir = sys.argv[1], sys.argv[2] for name in find(namepattern, startdir): print name © 2009 Fernando NIÑO 63 Exemple (exListeRep.py) import fnmatch, os def find(pattern, startdir=os.curdir): matches = [] os.path.walk(startdir, findvisitor, (matches, pattern)) return matches def findvisitor((matches, pattern), thisdir, nameshere): for name in nameshere: if fnmatch.fnmatch(name, pattern): fullpath = os.path.join(thisdir, name) matches.append(fullpath) if __name__ == '__main__': import sys namepattern, startdir = sys.argv[1], sys.argv[2] for name in find(namepattern, startdir): print name © 2009 Fernando NIÑO 63 Exemple (exListeRep.py) import fnmatch, os def find(pattern, startdir=os.curdir): matches = [] os.path.walk(startdir, findvisitor, (matches, pattern)) return matches def findvisitor((matches, pattern), thisdir, nameshere): for name in nameshere: if fnmatch.fnmatch(name, pattern): fullpath = os.path.join(thisdir, name) matches.append(fullpath) if __name__ == '__main__': import sys namepattern, startdir = sys.argv[1], sys.argv[2] for name in find(namepattern, startdir): print name © 2009 Fernando NIÑO 63 Exemple (exListeRep.py) import fnmatch, os def find(pattern, startdir=os.curdir): matches = [] os.path.walk(startdir, findvisitor, (matches, pattern)) return matches def findvisitor((matches, pattern), thisdir, nameshere): for name in nameshere: if fnmatch.fnmatch(name, pattern): fullpath = os.path.join(thisdir, name) matches.append(fullpath) if __name__ == '__main__': import sys namepattern, startdir = sys.argv[1], sys.argv[2] for name in find(namepattern, startdir): print name © 2009 Fernando NIÑO 63 Exemple (exListeRep.py) import fnmatch, os def find(pattern, startdir=os.curdir): matches = [] os.path.walk(startdir, findvisitor, (matches, pattern)) return matches def findvisitor((matches, pattern), thisdir, nameshere): for name in nameshere: if fnmatch.fnmatch(name, pattern): fullpath = os.path.join(thisdir, name) matches.append(fullpath) if __name__ == '__main__': import sys namepattern, startdir = sys.argv[1], sys.argv[2] for name in find(namepattern, startdir): print name © 2009 Fernando NIÑO 63 Exemple (exListeRep.py) import fnmatch, os def find(pattern, startdir=os.curdir): matches = [] os.path.walk(startdir, findvisitor, (matches, pattern)) return matches def findvisitor((matches, pattern), thisdir, nameshere): for name in nameshere: if fnmatch.fnmatch(name, pattern): fullpath = os.path.join(thisdir, name) matches.append(fullpath) if __name__ == '__main__': import sys namepattern, startdir = sys.argv[1], sys.argv[2] for name in find(namepattern, startdir): print name © 2009 Fernando NIÑO 63 Exemple (exListeRep.py) import fnmatch, os def find(pattern, startdir=os.curdir): matches = [] os.path.walk(startdir, findvisitor, (matches, pattern)) return matches def findvisitor((matches, pattern), thisdir, nameshere): for name in nameshere: if fnmatch.fnmatch(name, pattern): fullpath = os.path.join(thisdir, name) matches.append(fullpath) if __name__ == '__main__': import sys namepattern, startdir = sys.argv[1], sys.argv[2] for name in find(namepattern, startdir): print name © 2009 Fernando NIÑO 63 Exemple (exListeRep.py) import fnmatch, os def find(pattern, startdir=os.curdir): matches = [] os.path.walk(startdir, findvisitor, (matches, pattern)) return matches def findvisitor((matches, pattern), thisdir, nameshere): for name in nameshere: if fnmatch.fnmatch(name, pattern): fullpath = os.path.join(thisdir, name) matches.append(fullpath) if __name__ == '__main__': import sys namepattern, startdir = sys.argv[1], sys.argv[2] for name in find(namepattern, startdir): print name © 2009 Fernando NIÑO 63 Exemple (exListeRep.py) import fnmatch, os def find(pattern, startdir=os.curdir): matches = [] os.path.walk(startdir, findvisitor, (matches, pattern)) return matches def findvisitor((matches, pattern), thisdir, nameshere): for name in nameshere: if fnmatch.fnmatch(name, pattern): fullpath = os.path.join(thisdir, name) matches.append(fullpath) if __name__ == '__main__': import sys namepattern, startdir = sys.argv[1], sys.argv[2] for name in find(namepattern, startdir): print name © 2009 Fernando NIÑO 63 Exemple (exListeRep.py) import fnmatch, os def find(pattern, startdir=os.curdir): matches = [] os.path.walk(startdir, findvisitor, (matches, pattern)) return matches def findvisitor((matches, pattern), thisdir, nameshere): for name in nameshere: if fnmatch.fnmatch(name, pattern): fullpath = os.path.join(thisdir, name) matches.append(fullpath) if __name__ == '__main__': import sys namepattern, startdir = sys.argv[1], sys.argv[2] for name in find(namepattern, startdir): print name © 2009 Fernando NIÑO 63 Exemple (exListeRep.py) import fnmatch, os def find(pattern, startdir=os.curdir): matches = [] os.path.walk(startdir, findvisitor, (matches, pattern)) return matches def findvisitor((matches, pattern), thisdir, nameshere): for name in nameshere: if fnmatch.fnmatch(name, pattern): fullpath = os.path.join(thisdir, name) matches.append(fullpath) if __name__ == '__main__': import sys namepattern, startdir = sys.argv[1], sys.argv[2] for name in find(namepattern, startdir): print name © 2009 Fernando NIÑO 63 Exemple (2) • • • • sys.argv os.path.join os.path.walk fnmatch.fnmatch • Exercice: – faire que le résultat affiche la taille du fichier (trouvez la fonction à utiliser !) si un troisième arg. est taille python exListeRep.py ‘.*rc’ ~ alpha – ou python exListeRep.py ‘.*rc’ ~ taille 64 © 2009 Fernando NIÑO Solution (exListeRep2.py) import fnmatch, os if __name__ == '__main__': from sys import argv namepattern, startdir,trois = argv[1], argv[2],argv[3] matches=find(namepattern, startdir) if trois == 'alpha' : for name in matches: print name elif trois == 'taille': for name in matches: print "%s : %d" % (name,os.path.getsize(name)) else: print "Troisieme argument inconnu" 65 © 2009 Fernando NIÑO Exercice • La même chose, mais en faisant le tri par nom if __name__ == '__main__': from sys import argv namepattern, startdir,trois = argv[1], argv [2],argv[3] matches=find(namepattern, startdir) if trois == 'alpha' : matches.sort() for name in matches: print name elif trois == 'taille': for name in matches: print "%s : %d" % (name,os.path.getsize (name)) else: print "Troisieme argument inconnu" 66 © 2009 Fernando NIÑO Exercice • Idem, mais par taille 67 © 2009 Fernando NIÑO Solution (exListeRep4.py) • On crée une structure de données (nom, taille) ... elif trois == 'taille': fichiers=[] for name in matches: fichiers.append([name,os.path.getsize (name)]) fichiers.sort(lambda x,y: -cmp(x[1],y[1])) for nom in fichiers: print "%s : %d" % (nom[0],nom[1]) 68 © 2009 Fernando NIÑO Gestion de fichiers • On a vu comment parcourir une arborescence • Ouverture, écriture et modification de fichiers ? – syntaxe proche du C`` fichier=open(nomfichier,’r’) listeTout=fichier.readlines() fichier.close() – avec ipython faites fichier.<TAB> • Exercice: lisez votre fichier .bashrc en utilisant readlines et affichez-le sur l’écran (pensez aux lignes blanches...) 69 © 2009 Fernando NIÑO Fichiers texte • readlines() vs readline() – est pratique mais consomme de la mémoire. fichier=open('.bashrc','r') for ligne in fichier.readlines(): print ligne fichier.close() – Pour un gros fichier, il vaut mieux lire ligne par ligne fichier=open('.bashrc','r') ligne = fichier.readline() while ligne: if ligne.endswith('\n'): ligne=ligne[:-1] print ligne ligne = fichier.readline() fichier.close() 70 © 2009 Fernando NIÑO Iterateurs • Le comportement de readline() vs readlines() est typique de l’approche des itérateurs: – au lieu de créer une liste en mémoire à parcourir, on créé une fonction qui, à chaque appel, renvoie l’élément suivant. – range(10) : créé une liste de 0 à 9 – xrange(10) : créé un itérateur qui à chaque appel donne l’élément suivant le dernier. • Exercise : tester range et xrange avec ipython. 71 © 2009 Fernando NIÑO Remplacement de texte • Remplacer une chaîne par une autre dans un fichier import os, sys nargs = len(sys.argv) if not 3 <= nargs <= 5: print "usage: %s search_text replace_text [infile [outfile]]" % \ os.path.basename(sys.argv[0]) else: <<la suite>> 72 © 2009 Fernando NIÑO Remplacement de texte • <<la suite >> (searchreplace.py) stext = sys.argv[1] rtext = sys.argv[2] input_file = sys.stdin output_file = sys.stdout if nargs > 3: input_file = open(sys.argv[3]) if nargs > 4: output_file = open(sys.argv[4], 'w') for s in input_file: output_file.write(s.replace(stext, rtext)) if nargs > 4: output_file.close() input_file.close() 73 © 2009 Fernando NIÑO Exercice • Encapsulez la fonctionnalité searchreplace pour qu’elle agisse sur un ensemble de fichiers d’un repertoire: searchreplacedir.py search_text replace_text file_pattern startdir newfile_extension 74 © 2009 Fernando NIÑO Solution (searchreplacedir.py) def searchreplace(stext,rtext,inputname, outputname): input_file = open(inputname) output_file = open(outputname, 'w') for s in input_file: output_file.write(s.replace(stext, rtext)) output_file.close() input_file.close() if __name__ == '__main__': nargs = len(sys.argv) if nargs != 6: print "usage: %s search_text replace_text file_pattern startdir newfile_extension" % \ os.path.basename(sys.argv[0]) else: stext, rtext, namepattern, startdir, newext = \ sys.argv[1], sys.argv[2],sys.argv[3], sys.argv[4],sys.argv[5] for name in find(namepattern, startdir): newname="%s.%s" % (name,newext) print "Traitement de %s ==> %s" % (name,newname) searchreplace(stext,rtext,name,newname) 75 © 2009 Fernando NIÑO Solution (searchreplacedir.py) def searchreplace(stext,rtext,inputname, outputname): input_file = open(inputname) output_file = open(outputname, 'w') for s in input_file: output_file.write(s.replace(stext, rtext)) output_file.close() input_file.close() if __name__ == '__main__': nargs = len(sys.argv) if nargs != 6: print "usage: %s search_text replace_text file_pattern startdir newfile_extension" % \ os.path.basename(sys.argv[0]) else: stext, rtext, namepattern, startdir, newext = \ sys.argv[1], sys.argv[2],sys.argv[3], sys.argv[4],sys.argv[5] for name in find(namepattern, startdir): newname="%s.%s" % (name,newext) print "Traitement de %s ==> %s" % (name,newname) searchreplace(stext,rtext,name,newname) 75 © 2009 Fernando NIÑO Solution (searchreplacedir.py) def searchreplace(stext,rtext,inputname, outputname): input_file = open(inputname) output_file = open(outputname, 'w') for s in input_file: output_file.write(s.replace(stext, rtext)) output_file.close() input_file.close() if __name__ == '__main__': nargs = len(sys.argv) if nargs != 6: print "usage: %s search_text replace_text file_pattern startdir newfile_extension" % \ os.path.basename(sys.argv[0]) else: stext, rtext, namepattern, startdir, newext = \ sys.argv[1], sys.argv[2],sys.argv[3], sys.argv[4],sys.argv[5] for name in find(namepattern, startdir): newname="%s.%s" % (name,newext) print "Traitement de %s ==> %s" % (name,newname) searchreplace(stext,rtext,name,newname) 75 © 2009 Fernando NIÑO Solution (searchreplacedir.py) def searchreplace(stext,rtext,inputname, outputname): input_file = open(inputname) output_file = open(outputname, 'w') for s in input_file: output_file.write(s.replace(stext, rtext)) output_file.close() input_file.close() if __name__ == '__main__': nargs = len(sys.argv) if nargs != 6: print "usage: %s search_text replace_text file_pattern startdir newfile_extension" % \ os.path.basename(sys.argv[0]) else: stext, rtext, namepattern, startdir, newext = \ sys.argv[1], sys.argv[2],sys.argv[3], sys.argv[4],sys.argv[5] for name in find(namepattern, startdir): newname="%s.%s" % (name,newext) print "Traitement de %s ==> %s" % (name,newname) searchreplace(stext,rtext,name,newname) 75 © 2009 Fernando NIÑO Solution (searchreplacedir.py) def searchreplace(stext,rtext,inputname, outputname): input_file = open(inputname) output_file = open(outputname, 'w') for s in input_file: output_file.write(s.replace(stext, rtext)) output_file.close() input_file.close() if __name__ == '__main__': nargs = len(sys.argv) if nargs != 6: print "usage: %s search_text replace_text file_pattern startdir newfile_extension" % \ os.path.basename(sys.argv[0]) else: stext, rtext, namepattern, startdir, newext = \ sys.argv[1], sys.argv[2],sys.argv[3], sys.argv[4],sys.argv[5] for name in find(namepattern, startdir): newname="%s.%s" % (name,newext) print "Traitement de %s ==> %s" % (name,newname) searchreplace(stext,rtext,name,newname) 75 © 2009 Fernando NIÑO Solution (searchreplacedir.py) def searchreplace(stext,rtext,inputname, outputname): input_file = open(inputname) output_file = open(outputname, 'w') for s in input_file: output_file.write(s.replace(stext, rtext)) output_file.close() input_file.close() if __name__ == '__main__': nargs = len(sys.argv) if nargs != 6: print "usage: %s search_text replace_text file_pattern startdir newfile_extension" % \ os.path.basename(sys.argv[0]) else: stext, rtext, namepattern, startdir, newext = \ sys.argv[1], sys.argv[2],sys.argv[3], sys.argv[4],sys.argv[5] for name in find(namepattern, startdir): newname="%s.%s" % (name,newext) print "Traitement de %s ==> %s" % (name,newname) searchreplace(stext,rtext,name,newname) 75 © 2009 Fernando NIÑO Solution (searchreplacedir.py) def searchreplace(stext,rtext,inputname, outputname): input_file = open(inputname) output_file = open(outputname, 'w') for s in input_file: output_file.write(s.replace(stext, rtext)) output_file.close() input_file.close() if __name__ == '__main__': nargs = len(sys.argv) if nargs != 6: print "usage: %s search_text replace_text file_pattern startdir newfile_extension" % \ os.path.basename(sys.argv[0]) else: stext, rtext, namepattern, startdir, newext = \ sys.argv[1], sys.argv[2],sys.argv[3], sys.argv[4],sys.argv[5] for name in find(namepattern, startdir): newname="%s.%s" % (name,newext) print "Traitement de %s ==> %s" % (name,newname) searchreplace(stext,rtext,name,newname) 75 © 2009 Fernando NIÑO Jour 1 – Le langage Formation Python Python - Environnement Communication avec d'autres programmes Environnement Bonnes Pratiques 76 © 2009 Fernando NIÑO Communication inter-programmes • L’approche la plus simple os.system(“n’importe quelle commande”) – exécutée dans un shell standard – Exemple import os for i in range(0,500): os.system("mkdir rep%d" % i) • Dans tous les cas, il vaut mieux utiliser les interfaces natives Python (tar, compression...) import os for i in range(0,500): os.mkdir("rep%d" % i) 77 © 2009 Fernando NIÑO Communication par pipes • Utile quand un programme lit et l’autre écrit import os f = os.popen('gnuplot', 'w') print >>f, "set yrange[-300:+300]" for n in range(300): print >>f, "plot %i*cos(x)+%i*log(x+10)" % (n, 150-n) f.flush() f.close() 78 © 2009 Fernando NIÑO Communication par pipes (2) • Pour lire une sortie standard (pas de stderr !) listing = getCommandOutput2('ls -1 2>/dev/null') • Une façon de lire le résultat def getCommandOutput2(command): child = os.popen(command) data = child.read() err = child.close() if err: raise RuntimeError, '%r failed with exit code %d' % (command, err) 79 © 2009 Fernando NIÑO Communication par pipes (3) • Un peu long... voir getCommandOutput.py • Utilisation from getCommandOutput import * output=getCommandOutput("ls") print "Sortie = %s" % output try: output=getCommandOutput("ljs") print "Sortie = %s" % output except RuntimeError, error: print str(error) 80 © 2009 Fernando NIÑO Jour 1 – Le langage Formation Python Python - Environnement Communication avec d'autres programmes Bonnes Pratiques Programmation dirigée par les tests Documentation LEO Environnement 81 © 2009 Fernando NIÑO Programmation dirigée par les tests • L’avantage d’un langage dynamique est que l’on peut tester au fur et à mesure : même la syntaxe d’une seule ligne, sans avoir à compiler • On peut donc raccourcir le cycle codage <-> test pour déceler des erreurs le plus tôt possible. Codage incremental. • Donc... Tests Unitaires • Et exécution des tests unitaires le plus souvent possible (vérification de non-regression). 82 © 2009 Fernando NIÑO Tests unitaires • Cas simple: assertions assert(mafonction(3.5) == 1) • La face cachée: if __debug__: if not expression: raise AssertionError • Optimisation desactive __debug__: python -O # à l’invocation 83 © 2009 Fernando NIÑO Bonne pratique • Utilisez des assertions quand c’est possible • Créer des modules de la forme import mod1, mod2.. class MaClasse: def.. def... if __name__ == ‘__main__’: # Je commence des tests unitaires du module mc=MaClasse() assert(mc.fonction1(2.3) == 4) liste=mc.fonction2(‘test’) assert(len(liste) == 5) 84 © 2009 Fernando NIÑO Bonne pratique • Utilisation python monmodule.py – exécute les tests import monmodule mc = monmodule.MaClasse() ... – ne les exécute pas • Alternatives, meilleures plus sophistiquées – UNITTEST http://pyunit.sourceforge.net/ (livré en standard) – DOCTEST (livré en standard aussi) 85 © 2009 Fernando NIÑO Documentation • Il y a une documentation automatique des modules et des fonctions. Il suffit de la renseigner sous forme d’un string après la définition du module ou fonction: class Base: """Celle-ci est la classe de base et s’utilise comme il se doit """ pass – accessible avec Base.__doc__ • L’utilitaire pydoc s’utilise pour cela pydoc -p 3456 86 © 2009 Fernando NIÑO Programmation littéraire • Inventé par D. Knuth à partir de son système TeX et un compilateur Pascal (WEB system). Aujourd’hui, CWEB (TeX/C) et NOWEB et d’autres ont la même philosophie: – Un programme doit être écrit pour les humains, non pour une machine – donc, l’explication du fonctionnement du programme doit être le programme lui-même • Le principe: une seule source, après traitement génère – la documentation (avec weave) – le code compilable (avec tangle) 87 © 2009 Fernando NIÑO Programmation littéraire (2) • L’avantage de la méthode: – le code et les commentaires sont toujours synchronisés (si le mécanisme de génération de sources/compilation est automatique..) – En réfléchissant davantage, il y a moins de bogues. • L’inconvenient – c’est dur d’écrire des commentaires et encore plus de le faire avec pertinence. 88 © 2009 Fernando NIÑO Exemple noweb % Copyright 1991 by Norman Ramsey. All rights reserved. % See file COPYRIGHT for more information. % l2h substitution nw <tt>noweb</tt> % some insanity is needed to avoid getting a double square bracket % l2h substitution [ <b>[</b><b>[</b> % l2h substitution ] <b>]</b><b>]</b> \def\nw{{\tt noweb}} \def\[{\ifhmode\ \fi$[\mkern-2mu[$} \def\]{$]\mkern-2mu]$} \title{Printing Primes: An example of \nw} \section{Printing Primes: An example of \nw} The following program is essentially the program that appears in Reference~\cite{knuth:literate}, the first article on literate programming, but rendered using \nw. An important differents is the {\tt WEB} has macros, but \nw\ does not. 89 © 2009 Fernando NIÑO Example noweb (2) \section{The output phase} <<other constants of the program>>= rr = 50; cc = 4; ww = 10; <<variables of the program>>= `page_number: integer; `page_offset: integer; `row_offset: integer; c: 0..cc; @ <<print table [[p]]>>= begin page_number := 1; page_offset := 1; while page_offset <= m do begin <<output a page of answers>>; page_number := page_number + 1; page_offset := page_poffset + rr * cc; end; end 90 © 2009 Fernando NIÑO LEO • Bien que noweb, CWEB & compagnie soient très intéressants, il est vrai qu’il est pas toujours facile de suivre la documentation et le code au même temps. • Une alternative: Literate Programming Editor with Outlines – On organise de l’information comme on veut, en mode “Plan” – On génère du code à partir de là (comme avec WEB) et ce de façon automatique (à chaque “save” on génère le code associé). – Résultat: le code est plus accessible, avec une granularité variable (haut niveau, bas niveau). 91 © 2009 Fernando NIÑO LEO 92 105 © 2009 Fernando NIÑO Codage sous LEO • Pas évident au départ • Le codage se fait comme ceci: def fonction(param1, param2): <<initialisation fonction>> for i in sequence: <<traiter sequence>> – où “initialisation fonction” et “traiter séquence” sont définis par la suite (ou même avant) dans d’autres noeuds LEO (puisque l’ensemble est un arbre) • Mot-clé sur le ouèbe: edreamleo 93 © 2009 Fernando NIÑO