Sommaire
-
Divers
- Extraire des adresses email
- Recuperer une variable d'environnement
- Connaitre le chemin du répertoire dans lequel se trouve le script en cours
- Connaître le chemin du répertoire 'home' de l'utilisateur
- Une fonction qui renvoie plusieurs valeurs
- Obtenir la date en francais
- Passer des paramètres en nombre variables à une fonction sans se soucier de leur ordre
- Vérifier qu'une variable est bien d'un certain type
- Disposer d'un dictionnaire ou d'une liste ne levant pas d'exception en cas d'absence d'indice ou de clef
- Thread
- Test unitaire
- Utilisation de la bibliothèque cmd
- Filtre Bayesien
- Crypter du texte
- Hachage MD5 d'une chaine de caractères
- Hachage SHA d'une chaine de caractères
- Inclure de petits fichiers dans vos sources
- La machine virtuelle Python
Divers
Extraire des adresses email
Comment extraire les adresses email de n'importe quel fichier en 2 lignes de code !
http://sebsauvage.net/python/email_extractor.py
Il s'utilise de la façon suivante: python email_extractor.py < monfichier.html
Recuperer une variable d'environnement
Connaitre le chemin du répertoire dans lequel se trouve le script en cours
Ceci peut s'avérer utile, par exemple pour importer d'autres modules se trouvant dans ledit répertoire...
Attention: il semble que sous Windows XP, file contienne le chemin complet. Ce n'est pas le cas sous Linux !. La solution consistant à utiliser os.path.dirname(file) n'est donc pas portable.
Connaître le chemin du répertoire 'home' de l'utilisateur
Cette astuce fonctionne sous Linux, mais aussi sous MacOS X et Windows. Pratique pour sauvegarder un fichier de configuration (par exemple).
Une fonction qui renvoie plusieurs valeurs
En Python, il est très facile de faire une fonction qui renvoie plusieurs valeur en même temps.
>>> def mafonction(a): return (a+1,a*2,a*a) >>> print mafonction(3) (4, 6, 9)
(En effet, les tuple (4,6,9), listes et dictionnaires sont des types de base de Python : on peut donc les utiliser partout où vous auriez utilisé d'autres types de données (entiers, chaînes...)).
N'oubliez pas que vous avez la possibilité de faire de l'assignation multiple:
>>> (g,h,i) = mafonction(7) >>> print g 8 >>> print h 14 >>> print i 49 >>>
Obtenir la date en francais
Par défaut, pour garder la compatibilité avec la norme Posix, Python ne prend pas en compte les variables LANG sur unix ( http://www.python.org/doc/current/lib/module-locale.html ). Ce qui fait que la fonction strftime travaille par défaut en anglais. Il suffit donc de positionner la valeur des locales à la valeur par défaut avec setlocale.
>>> import time >>> time.strftime('%c') 'Sun Jun 27 21:50:11 2004' >>> import locale >>> locale.setlocale(locale.LC_ALL,'') 'fr_FR' >>> time.strftime('%c') 'dim 27 jun 2004 21:50:32 CEST'
Passer des paramètres en nombre variables à une fonction sans se soucier de leur ordre
le prototype d'une fonction est en réalité: function(args, *args, **kwargs) ou args est une liste classique de paramètres séparés par des ',', args est une variable de type list contenant la liste des paramètres et le plus intéressant se trouve dans kwargs qui est un dictionnaire (type dict) dont les clefs sont les paramètres, et leurs valeurs, les valeurs des paramètres. Ce qui permet de nombreuses possibilités d'utilisation des fonctions dans un cadre disont plus dynamique.
Vérifier qu'une variable est bien d'un certain type
Il existe le mot clef type qui permet de le savoir mais son utilisation est obsolète de par l'existence de la fonction isinstance(object, class) qui permet de savoir si l'objet "object" est une instance de la classe "class" et retourne True dans ce cas, False sinon.
Attention toutefois à ne pas utiliser isinstance() sans raison: Python est un langage à typage dynamique, et le plus souvent le type exact d'un objet est sans importance du moment que l'objet implémente bien l'interface attendue. Par exemple, une fonction originellement destinée à écrire dans un fichier (en utlisant la méthode write() de la classe file) peut fonctionner aussi bien avec n'importe quel objet implémentant la méthode write() (in StringIO par exemple). Tester si l'objet passé est effectivement une instance de la classe file limiterait inutilement les utilisations possibles de cette fonction.
Disposer d'un dictionnaire ou d'une liste ne levant pas d'exception en cas d'absence d'indice ou de clef
Il suffit de créér une classe qui héritera de dict ou de list qui réécrit la méthode getitem pour vérifier que l'item demandé fait bien partie de l'objet. ex:
idem pour une liste:
ensuite à l'utilisation il suffit d'instancier la classe désirée puis l'utiliser comme un dictionnaire ou une liste classique mis à part cette petite différence.
>>> l = Nlist() >>> print l [] >>> print l[3] >>> >>> d = Ndict() >>> print d {} >>> print l['toto'] >>>
Codes utilisants la librairie http://www.reportlab.com
BaseDocTemplate
Permet de générer des tableaux sur plusieurs pages avec gestion des entêtes...
Thread
Voici un exemple de thread avec dialogue par file de message
1 import threading
2 import time
3 import Queue
4
5 bal = Queue.Queue (100)
6 test = 10
7 class myThread(threading.Thread):
8 def __init__(self, name=None):
9 threading.Thread.__init__(self, target=self.run, name=name, args=() )
10 self.start()
11
12 def run(self):
13 for i in range(test):
14 print self.getName(), i
15 bal.put ("Msg %d from %s"%(i,self.getName()))
16 time.sleep (0.2)
17
18
19 def main ():
20 t1 = myThread("Thread(1)")
21 t2 = myThread("Thread(2)")
22
23 for i in range (test*2):
24 msg = bal.get ()
25 print "Reception message :", msg
26
27 if __name__=="__main__":
28 main ()
Test unitaire
Exemple de test unitaire d'une fonction de division
1 import unittest
2
3 def divide (value1, value2):
4 return value1 / value2
5
6 class DivisionValue(unittest.TestCase):
7 values = ( ( 1., 1., 1.),
8 ( 3., 2., 1.5) )
9 def testDivide (self):
10 """ Test division correcte """
11 for value1, value2, result in self.values:
12 res = divide(value1, value2)
13 self.assertEqual (res, result)
14
15 def testTypeError (self):
16 """ Test mauvais type """
17 self.assertRaises (TypeError, divide, 1, "2")
18
19 def testZeroDivisionError (self):
20 """ Test division par zéro """
21 self.assertRaises (ZeroDivisionError, divide, 1., 0.)
22
23
24 if __name__ == "__main__":
25 unittest.main()
Utilisation de la bibliothèque cmd
Le principe est simple: vous définissez des méthodes commançant par do_ comme do_hello_world. Dans l'interpréteur, vous pouvez appeler ces fonctions par le nom de la méthode mais sans le do_. Après le code se trouve un exemple de session.
1 #!/usr/bin/env python
2 import cmd
3 import os
4
5 class SimpleCmdInterpretor(cmd.Cmd):
6
7 def __init__(self):
8 self.prompt = ">?>"
9 self.intro = """This is a very simple command line Interpreter.
10 Type ? for help.
11 Type ! for Python subshell."""
12
13 def emptyline(self):
14 print "Type 'exit' to terminate the session or type ? for help."
15
16 def default(self, line):
17 print "*** Unknown Syntax : %s (type help for a list of valid command"%line
18
19 def do_shell(self, arg):
20 """\nLaunches the Python Interpreter.\n"""
21 os.system("python")
22
23 def do_exit(self, arg):
24 """\nTerminates the session.\n"""
25 return -1
26
27 ## vos méthodes personnelles:
28
29 def do_hello_world(self, arg):
30 """\nPrints Hello 'arg'"""
31 print 'Hello %s' % arg
32
33 def _test():
34 my_cmd = SimpleCmdInterpretor()
35 my_cmd.cmdloop()
36
37 if __name__ == "__main__":
38 _test()
Exemple de session:
[oli@argyro]~/dev/python/gui/cmd/basic -> python cmd_interpretor.py This is a small command line Interpreter. Type ? for help. Type ! for Python subshell. >?>help Documented commands (type help <topic>): ======================================== exit hello_world shell Undocumented commands: ====================== help >?>help hello_world Prints Hello 'arg' >?>hello_world Toto Hello Toto >?>exit [oli@argyro]~/dev/python/gui/cmd/basic ->
Filtre Bayesien
Les filtres Baysesiens permettent de classifier des données. Par exemple, ils sont de plus en plus utilisés pour filtrer le spam (emails publicitaires).
Reverend est un filtre baysien écrit en 100% Python et opensource.
Prenons un exemple: reconnaître la langue d'un texte.
Tout d'abord, entraînons notre filtre bayesien sur quelques phrases:
1 from reverend.thomas import Bayes
2 guesser = Bayes()
3 guesser.train('french','La souris est rentrée dans son trou.')
4 guesser.train('english','my tailor is rich.')
5 guesser.train('french','Je ne sais pas si je viendrai demain.')
6 guesser.train('english','I do not plan to update my website soon.')
Et maintenant, laissons-le deviner:
>>> print guesser.guess('Jumping out of cliffs it not a good idea.') [('english', 0.99990000000000001), ('french', 9.9999999999988987e-005)]
Le filtre bayesien dit "C'est anglais avec une probabilité de 99,99%."
Faisons un autre essai:
>>> print guesser.guess('Demain il fera très probablement chaud.') [('french', 0.99990000000000001), ('english', 9.9999999999988987e-005)]
ça dit: "C'est français avec une probabilité de 99,99%."
Pas mal, non ?
Vous pouvez même l'entraîner sur d'autres langues en même temps. Ou même l'entraîner à classifier n'importe quel type de texte selon vos critères.
Crypter du texte
Il est très facile de faire un algorithme de cryptage en python comme suit:
et pour décrypter:
Hachage MD5 d'une chaine de caractères
Pour conserver un mot de passe, ou pour garder une trace d'un fichier, il peut être utile de générer une signature numérique en MD5.
Hachage SHA d'une chaine de caractères
De même que le hachage en MD5, l'algorithme SHA produit une signature plus longue et plus sécurisé. De plus ce code utilise une variable aléatoire stockée en clair qui permet d'obtenir des signatures différentes pour une même chaine.
Inclure de petits fichiers dans vos sources
Ils parfois utile d'embarquer de petits fichiers binaires à l'intérieur de ses sources.
Prenons un fichier (monimage.gif), et convertissons-là en base64 (et accessoirement, nous le compressons avec zlib):
On récupère le texte créé par ce programme, et on peut l'inclure directement dans le source de votre programme:
1 import base64,zlib
2 monfichier = zlib.decompress(base64.decodestring("""
3 eJxz93SzsExUZlBn2MzA8P///zNnzvz79+/IgUMTJ05cu2aNaBmDzhIGHj7u58+fO11ksLO3Kyou
4 ikqIEvLkcYyxV/zJwsgABDogAmQGA8t/gROejlpLMuau+j+1QdQxk20xwzqhslmHH5/xC94Q58ST
5 72nRllBw7cUDHZYbL8VtLOYbP/b6LhXB7tAcfPCpHA/fSvcJb1jZWB9c2/3XLmQ+03mZBBP+GOak
6 /AAZGXPL1BJe39jqjoqEAhFr1fBi1dao9g4Ovjo+lh6GFDVWJqbisLKoCq5p1X5s/Jw9IenrFvUz
7 +mRXTeviY+4p2sKUflA1cjkX37TKWYwFzRpFYeqTs2fOqEuwXsfgOeGCfmZ57MP4WSpaZ0vSJy97
8 WPeY5ca8F1sYI5f5r2bjec+67nmaTcarm7+Z0hgY2Z7++fpCzHmBQCrPF94dAi/jj1oZt8R4qxsy
9 6liJX/UVyLjwoHFxFK/VMWbN90rNrLKMGQ7iQSc7mXgTkpwPXVp0mlWz/JVC4NK0s0zcDWkcFxxF
10 mrvdlBdOnBySvtNvq8SBFZo8rF2MvAIMoZoPmZrZPj2buEDr2isXi0V8egpelyUvbXNc7yVQkKgS
11 sM7g0KOr7kq3WRIkitSuRj1VXbSk8v4zh8fljqtOhyobP91izvh0c2hwqKz3jPaHhvMMXVQspYq8
12 aiV9ivkmHri5u2NH8fvPpVWuK65I3OMUX+f4Lee+3Hmfux96Vq5RVqxTN38YeK3wRbVz5v06FSYG
13 awWFgMzkktKiVIXkotTEktQUhaRKheDUpMTikszUPIVgx9AwR3dXBZvi1KTixNKyxPRUhcQSBSRe
14 Sn6JQl5qiZ2CrkJGSUmBlb4+QlIPKKGgAADBbgMp"""))
15
16 print "J'ai un fichier de %d octets." % len(monfichier)
Par exemple, si vous utilisez PIL (Python Imaging Library), vous pouvez charger directement cette image pour l'utiliser:
La machine virtuelle Python
Python - tout comme Java ou Microsoft .Net (C#) - possède une machine virtuelle.
C'est à dire que les programmes Python sont transformé dans un langage machine (appelé bytecode) spécifique à Python. Mais il n'existe aucun microprocesseur physique capable de comprendre ce langage machine ! (Au contraire du langage machine Intel x86 (Pentium)).
Python, Java et .Net possèdent donc chacun un programme qui simule un microprocesseur capable de comprendre leur langage machine respectif: c'est la machine virtuelle.
Le bytecode Python est différent de celui de Java, qui est différent de celui de .Net.
Un exemple
Créons un petit programme simple: sauvegardez le texte suivant dans le fichier monprogramme.py:
Cette fonction prend un nombre en entrée, l'affiche, puis le multiplie par 3. Si le résultat est inférieur à 50, elle ajoute 77. Puis elle renvoie le résultat.
On va ensuite "compiler" le programme et l'utiliser:
C:\>python Python 2.3.4 (#53, May 25 2004, 21:17:02) [MSC v.1200 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import monprogramme >>> print monprogramme.mafonction(5) J'ai 5 92 >>>
Le fait de taper import monprogramme va compiler le programme et créer le fichier monprogramme.pyc.
On peut ensuite désassembler:
>>> import dis >>> print dis.dis(monprogramme.mafonction) 2 0 LOAD_CONST 1 ("J'ai") 3 PRINT_ITEM 4 LOAD_FAST 0 (a) 7 PRINT_ITEM 8 PRINT_NEWLINE 3 9 LOAD_FAST 0 (a) 12 LOAD_CONST 2 (3) 15 BINARY_MULTIPLY 16 STORE_FAST 1 (b) 4 19 LOAD_FAST 1 (b) 22 LOAD_CONST 3 (50) 25 COMPARE_OP 0 (<) 28 JUMP_IF_FALSE 14 (to 45) 31 POP_TOP 5 32 LOAD_FAST 1 (b) 35 LOAD_CONST 4 (77) 38 BINARY_ADD 39 STORE_FAST 1 (b) 42 JUMP_FORWARD 1 (to 46) >> 45 POP_TOP 6 >> 46 LOAD_FAST 1 (b) 49 RETURN_VALUE 50 LOAD_CONST 0 (None) 53 RETURN_VALUE None >>>
La colonne de gauche indique la ligne correspondante dans le code source (dans monprogramme.py).
Si on prend la ligne 3 du programme (b = a * 3), on peut retrouver l'opération:
LOAD_FAST 0 : charge sur la pile la valeur de la case mémoire dont l'adresse est stockée à l'adresse 0 (qui est a)
LOAD_CONST 2 : charge la constante stockée à l'adresse 2 (qui est la valeur 3)
BINARY_MULTIPLY : effectue la multiplication des 2 valeur qui sont en haut de la pile (a*3)
STORE_FAST 1 : Stock cette valeur (1 est l'adresse à laquelle se trouve le pointeur vers b)
Vous pourrez également y retrouver les autres opération (affichage avec PRINT_ITEM, le if réalisé avec COMPARE_OP et JUMP_IF_FALSE, etc.) La liste des opératiosn est disponibles dans la documentation de Python : http://www.python.org/doc/current/lib/bytecodes.html
Chaque fois que vous importez un module, Python va créer le .pyc (bytecode) correspondant pour ne pas avoir à re-lire le code source à chaque fois. Si vous supprimez le .pyc, Python le re-crééera automatiquement dès que vous importerez à nouveau le module. Si vous modifiez le code source .py correspondant, Python détectera automatiquement ce changement dès que vous ré-importerez le module, et re-créera le .pyc.
Un fichier .pyc peut être exécuté directement, même si vous n'avez pas le .py correspondant.
Ce mécanisme permet à Python de compiler uniquement à la demande, et de garder le code pre-compilé pour la fois suivante afin d'aller plus vite.