Moi aussi j'y avait pensé... mais peut être un an ou deux trop tard!
jeudi 29 octobre 2009
Regular expression en Python
Voici deux très bonnes références pour l'utilisation d'expression régulière en Python.
Les raw strings sont précédées d'un r et informe le compilateur que le caractère "\" dans la string n'initie pas une séquence d'échappement Python.
L'utilisation des raw strings dans les régulars expressions permet de s'émanciper d'une situation communément dénommée "The Back Slash Hell".
A voir également: la section string services de docs.python.org abordant les strings sous toutes leurs formes (StringIO, Codes, Regular expression, template, formattage, etc)
- Regular Expression HOWTO une introduction assez légère et pas trop longue
- Regular Expression ** un article nettement plus complet sur l'utilisation du module re.
Utiliser des raw string avec les regular expression
Pour facilité l'écriture des regular expressions, il est préférable d'utiliser les raw string de Python.Les raw strings sont précédées d'un r et informe le compilateur que le caractère "\" dans la string n'initie pas une séquence d'échappement Python.
# avec raw string if re.search(r'\tok', item)>0 # sans raw string if re.search('\\tok', item)>0Sans raw string, il est nécessaire de doubler le \ (ce qui donne \\) pour que Python interprète la séquence d'échappement \\ (soit \+\) comme un simple \ qu'il envoi alors au module d'expression régulière.
L'utilisation des raw strings dans les régulars expressions permet de s'émanciper d'une situation communément dénommée "The Back Slash Hell".
Plus d'information
Voir le site de documentation docs.python.orgA voir également: la section string services de docs.python.org abordant les strings sous toutes leurs formes (StringIO, Codes, Regular expression, template, formattage, etc)
Lecture de fichier et streaming d'objets en Python
Voici quelques notes et exemples rudimentaires de lecture de fichier texte.
Lecture séquentielle
Plus d'information sur la lecture de fichier dans cet article "Reading Text Files".
fichiers et séquences
Qui n'a pas un jour eu le besoin de charger le contenu d'un fichier dans une liste ou une séquence?
Voici un petit script permettant de charger le contenu d'un fichier dans une séquence en quelques lignes.
plus d'info sur la manipulation de fichier sur l'article "Introduction to Python: File I/O".
Pickling
Ou le "streaming d'objets" !
Apparemment, le pickling est une méthode permettant de transformer un object en sa représentation texte compacte afin d'en permettre facilement le transport (par reseau, fichier, etc).
Le module pickle contient la fonction "dumps" permettant de transformer un objet en sa représentation texte.
La fonction loads du module pickle permet quant a elle de recréer une instance de la classe.
Le streaming
Il est également possible d'écrire l'état d'un objet dans un fichier... voir l'exemple suivant:
Plus d'info voir l'article "Introduction to Python: File I/O".
Lecture séquentielle
>>> def readFile( sFilename ): file = open( sFilename ) while 1: line = file.readline() if not line: break print( line ) file.close() >>> readFile( 'c:\\dcu\\test.txt' )***
Plus d'information sur la lecture de fichier dans cet article "Reading Text Files".
fichiers et séquences
Qui n'a pas un jour eu le besoin de charger le contenu d'un fichier dans une liste ou une séquence?
Voici un petit script permettant de charger le contenu d'un fichier dans une séquence en quelques lignes.
>>> filename = 'c:/Source/MySoft/fileset2' >>> _file = open( filename, 'r' ) >>> fileset2 = _file.readlines() >>> _file.close() >>> fileset2 ['acl.pas\n', 'Action.pas\n', 'Address.pas\n', 'Check.pas\n', 'Template.pas\n', 'listStuff.pas\n', 'ruine.pas\n', 'Cassandre.pas\n', 'ptoleme.pas\n', 'Codes.pas\n', 'BCV.pas\n', 'DisplayModule.pas\n', 'DocumentTemplate.pas\n' ]
plus d'info sur la manipulation de fichier sur l'article "Introduction to Python: File I/O".
Pickling
Ou le "streaming d'objets" !
Apparemment, le pickling est une méthode permettant de transformer un object en sa représentation texte compacte afin d'en permettre facilement le transport (par reseau, fichier, etc).
Le module pickle contient la fonction "dumps" permettant de transformer un objet en sa représentation texte.
>>> pickled = pickle.dumps( Mike ) # Mike est un objet de type Student >>> print( pickled )Fournira le résultat suivant:
(i__main__ Student p0 (dp1 S'school' p2 S'UIUC' p3 sS'year' p4 S'Senior' p5 sS'name' p6 S'Mike' p7 sS'gpa' p8 F0.59999999999999998 sS'major' p9 S'CS' p10 sb.
La fonction loads du module pickle permet quant a elle de recréer une instance de la classe.
>>> # La création d'un nouvel objet depuis le pickle >>> Mike2 = pickle.loads(pickled)
Le streaming
Il est également possible d'écrire l'état d'un objet dans un fichier... voir l'exemple suivant:
>>> f = open( 'c:/pickle.dat', 'w' ) >>> P = pickle.Pickler( f ) >>> P.dump( Mike ) # Mike est un objet de type Student >>> f.close()
Plus d'info voir l'article "Introduction to Python: File I/O".
mercredi 28 octobre 2009
Embedded File System en Delphi
Les articles "Writing an embedded file system" et "GpStructuredStorage internals" de Primoz Gabrijelcic (créateur de GpTools et GpSynch) explique comment implémenter, à l'aide de Delphi, un système de fichier avec répertoires dans un seul fichier physique.
L'implémentation de GpStructuredStorage tire encore une fois parti des avantages offerts par l'implémentation d'interface. Le code utilisant GpStructuredStorage est d'une grande lisibilité.
L'utilisation de cette technique permet par exemple:
Télécharger les sources de GpStructuredStorage.
L'implémentation de GpStructuredStorage tire encore une fois parti des avantages offerts par l'implémentation d'interface. Le code utilisant GpStructuredStorage est d'une grande lisibilité.
L'utilisation de cette technique permet par exemple:
- De maintenir les nombreuses données de configurations d'un logiciel dans un seul fichier physique.
- D'organiser des fichiers de données les plus variés au sein d'un seul fichier physique.
- Mettre en place une pseudo base de donnée (basée sur un système de fichier).
Télécharger les sources de GpStructuredStorage.
mardi 27 octobre 2009
Data Liberation: Exportez et Importez vos données Google
C'est un peu par hasard que je croise le chemin de l'initiative Data Liberation de Google.
Data Libération fut initié en 2007 par quelques ingénieurs de Google et visait à permettre l'exportation et l'importation de données personnelles depuis et vers les services de Google.
C'est ainsi qu'il est possible d'exporter ses e-mail GMail, ses contacts, ses documents Google Doc, ses articles de Blog, App Engine, etc.
Data Liberation centralise toutes les informations nécessaires à ces processus d'importation et exportation.
Comme résultat de cette initiative, il est maintenant possible de convertir, zipper et exporter toute une série de documents Google Doc.
Pour plus d'information, voir l'article Liberate Your Google Docs with convert, Zip and Download du blog officiel de Google et le blog de Data Liberation.
Data Libération fut initié en 2007 par quelques ingénieurs de Google et visait à permettre l'exportation et l'importation de données personnelles depuis et vers les services de Google.
C'est ainsi qu'il est possible d'exporter ses e-mail GMail, ses contacts, ses documents Google Doc, ses articles de Blog, App Engine, etc.
Data Liberation centralise toutes les informations nécessaires à ces processus d'importation et exportation.
Comme résultat de cette initiative, il est maintenant possible de convertir, zipper et exporter toute une série de documents Google Doc.
Pour plus d'information, voir l'article Liberate Your Google Docs with convert, Zip and Download du blog officiel de Google et le blog de Data Liberation.
jeudi 22 octobre 2009
200 articles publiés
Commencé comme une simple curiosité, ce Blog est vite devenu mon indispensable carnet de notes.
C'est ainsi que j'ai finalement dépassé la barre des 200 publications avec mon dernier article "Comprehension list, itérateurs et générateurs (Yield) en python".
Entre ma vie professionnelle et mes centres d'intérêts (quasi uniquement professionnels) ce blog ne cesse de gonfler très régulièrement. C'est qu'en plus d'être prolifique (je crois), je prends également énormément de plaisir à partager mon savoir.
Et depuis la découverte du moteur de recherche personnalisé de Google, il m'est même devenu facile d'y retrouver mes propres informations.
Mon seul regret c'est que Blogger n'offre pas de fonctionnalités avancées pour l'écriture d'articles techniques.
Par exemple, l'ajout de code dans un article nécessite quelques manipulations en html. J'espère qu'un jour Google se décidera à ajouter un système de plug-in pour son éditeur html.
mercredi 21 octobre 2009
Comprehension list, itérateurs et générateurs (Yield) en python
List Comprehension
Les list comprehensions sont est une syntaxe particulière permettant de construire facilement et rapidement des listes.
La syntaxe est les suivantes:
Les itérateurs
L'iteration est un mecanisme permettant de passer en revue le contenu d'une liste en utilisant le principe d'iteration.
Un itérateur implemente la fonction next() qui retourne la prochaine valeur (ou l'exception StopIteration quand il n'y a plus d'élément).
Les itérateurs sont utilisés de façon transparente dans les syntaxes tel que "for item in sequence:".
Il est également possible d'obtenir un itérateur (implémentant la fonction next) en utilisant la primitive iter( anObjectExposingIteratorFunction ).
On appele ensuite la fonction next() de l'iterateur pour retrouver les différents élements.
L'exemple suivant est disponible dans le fichier testIterator.py .
Définir son propre itérateur
Il est possible de definir un iterateur pour ses propres classes.
Dans ce cas, il est nécessaire d'implémenter la fonction __iter__ retournant une référence vers un object implémentant la methode next().
NB: la fonction __iter__ peut être utilisée pour retourner une référence vers l'objet lui-même si ce dernier implémente la fonction next(). Ce sera le cas de l'exemple ci-dessous aussi disponible dans le fichier testIterator.py .
Les générateurs (Yield)
Yield est un mot clé permettant de retourner un contenu énumerable.
Dans le monde Python, la syntaxe utilisant le mot clé "yield" correspond au concept de "générateur" (generator).
L'interpréteur utilise le générateur qui mémorisera l'état de la fonction appelée. Comme précisé par Tarek Ziadé, "la directive yield constituant en quelque sorte un return avec point de sauvegarde de l'état des variables locales et de l'endroit où le code de la fonction à quitté." (Source: Programmation Python seconde Edt., Page 149, ISBN 9782-212-12483-5)
L'exemple suivant issu du script testIterator.py démontre l'usage du mot clé yield.
Le code précédent produissant le résultat ci-dessous.
Notez l'entrelas des appels entre les fonctions BuildYielded() et TestYielded()! Les générateurs sont plus particulièrement approprié lors de la manipulation de grands ensembles/set d'objets (voir l'exemple du point suivant concernant les générateurs et les listes de compréhension).
Finalement, il est également possible d'associer les générateurs et les compréhensions lists (décrit en début d'article). le résultat étant appelé un "Generator Expression"!
Pour créer une générateur sur base d'une compréhension list, l'on utilise la syntaxe suivante où les parenthèses remplacent les crochets.
Un cas typique de son utilisation serait l'exécution de l'expression de manipulation (expression-manupilation) que lorsque l'on extrait l'information du generateur. Cela peut devenir utile si le processus est grand consommateur de ressource (comme des accès DB).
A Contrario, toutes les expressions de manipulation sont exécutées immédiatement lors de la création d'une expression list.
Voici un exemple extrait du module GenVsExpList.py .
Le résultat démontre bien que dans le cas d'un generator expression, l'expression de transformation n'est appelée qu'au moment de l'extraction de la valeur!
Les list comprehensions sont est une syntaxe particulière permettant de construire facilement et rapidement des listes.
La syntaxe est les suivantes:
[ expression-manipulation for expression in sequence ]
[ expression-manipulation for expression in sequence if test]
>>> [word.upper() for word in "c est une phrase".split() ] ['C', 'EST', 'UNE', 'PHRASE'] # ou code equivalent mais plus long >>> myList = [] >>> for word in "c est une phrase".split(): ... myList.append( word.upper() ) ... >>> myList ['C', 'EST', 'UNE', 'PHRASE'] # Autre exemple de list comprehension >>> [ i * 3 for i in range(10) if i%2==0] [0, 6, 12, 18, 24]
Les itérateurs
L'iteration est un mecanisme permettant de passer en revue le contenu d'une liste en utilisant le principe d'iteration.
Un itérateur implemente la fonction next() qui retourne la prochaine valeur (ou l'exception StopIteration quand il n'y a plus d'élément).
Les itérateurs sont utilisés de façon transparente dans les syntaxes tel que "for item in sequence:".
Il est également possible d'obtenir un itérateur (implémentant la fonction next) en utilisant la primitive iter( anObjectExposingIteratorFunction ).
On appele ensuite la fonction next() de l'iterateur pour retrouver les différents élements.
L'exemple suivant est disponible dans le fichier testIterator.py .
>>> def UseIterator(): """ l exemple suivant démontre l'utilisation explicite d'un itérateur. Pour information, l'instruction for fait un usage implicite de L'itérateur """ mySequence = ['a', 'b', 5 ,7 ,9 ,'tz'] _iterator = iter( mySequence ) try: while True: _value = _iterator.next() print( _value ) except StopIteration: print( '--- End of iteration ---' ) >>> testIterator.UseIterator() a b 5 7 9 tz --- End of iteration ---
Définir son propre itérateur
Il est possible de definir un iterateur pour ses propres classes.
Dans ce cas, il est nécessaire d'implémenter la fonction __iter__ retournant une référence vers un object implémentant la methode next().
NB: la fonction __iter__ peut être utilisée pour retourner une référence vers l'objet lui-même si ce dernier implémente la fonction next(). Ce sera le cas de l'exemple ci-dessous aussi disponible dans le fichier testIterator.py .
import random def UseIterator(): mySequence = ['a', 'b', 5 ,7 ,9 ,'tz'] _iterator = iter( mySequence ) try: while True: _value = _iterator.next() print( _value ) except StopIteration: print( '--- End of iteration ---' ) class myIterableClass(object): """ class contenant une liste d'élément iterable. Attention: Ceci est un exemple pour faciliter la compréhension. Cette classe ne sais produire qu'un seul iterateur à la fois car elle implémente elle meme son propre itérateur et par conséquent l'index est reseter a chaque obtention de l'itérateur (via __iter__). La solution a ce problème est d'implémenter une classe d'iteration indépendante. """ _list = [] _index = 0 # cursor for iteration # Constructor def __init__( self ): # prepare a random list of items for i in range( 1, random.randint(1,25) ): self._list.append( 'Value %s is %s ' % (i, random.randint(1,1000) ) ) # Iterable primitive def __iter__( self ): self._index = 0; return self # Iteration function def next( self ): self._index += 1 if self._index-1 >= len( self._list ): raise StopIteration() return self._list[self._index-1] >>> # Utilisation de la classe iterable >>> # >>> obj = myIterableClass() >>> for theValue in obj: ... print( theValue ) ... Value 1 is 687 Value 2 is 3 Value 3 is 427 Value 4 is 954 >>> # Utilisation de la classe iterable >>> # via la declaration d'un iterateur >>> it = iter( obj ) >>> it.next() 'Value 1 is 687 ' >>> it.next() 'Value 2 is 3 ' >>> it.next() 'Value 3 is 427 ' >>> it.next() 'Value 4 is 954 ' >>> it.next()
Les générateurs (Yield)
Yield est un mot clé permettant de retourner un contenu énumerable.
Dans le monde Python, la syntaxe utilisant le mot clé "yield" correspond au concept de "générateur" (generator).
L'interpréteur utilise le générateur qui mémorisera l'état de la fonction appelée. Comme précisé par Tarek Ziadé, "la directive yield constituant en quelque sorte un return avec point de sauvegarde de l'état des variables locales et de l'endroit où le code de la fonction à quitté." (Source: Programmation Python seconde Edt., Page 149, ISBN 9782-212-12483-5)
L'exemple suivant issu du script testIterator.py démontre l'usage du mot clé yield.
class YieldedItem( object ): """ Classe de demonstration démontrant l'utilité du mot clé "yield". Voir les fonctions TestYielded et BuildYielded """ _value = -1 def __init__(self): self._value = random.randint(1,25) def __getValue( self ): return self._value value = property( __getValue, None, None ) def BuildYielded(): """ Cette fonction génère une série d'objects de type YieldedItem() et retourne les références à l'aide du mot clé "yield". Les objects ainsi crées seront énumerables """ for i in range( 10 ): print( 'BuildYielded(): Create YieldedItem() object #%s' % (i) ) yield YieldedItem() def TestYielded(): """ Cette fonction démontre l'utilité du mot clé "yield". En effet, la fonction BuildYielded() retourne une série d'objet à l'aide du mot clé "yield". Par conséquent, les différents objets sont stockés dans un générateur qui lui est énumérable. """ # Exemple démontrant l'usage du générateur print( 'La fonction BuildYielded() retourne un générateur.' ) print( 'Notez que la fonction BuildYielded() n\'est pas exécutée!') print( BuildYielded() ) # Exemple démontrant le caractère énumérable print( 'Le resultat de la fonction peut être facilement énuméré.' ) print( 'Notez l\'entrelas des appels entre TestYielded() et ' + 'BuildYielded()' ) for item in BuildYielded(): print( 'TestYielded(): Valeur stockée dans l\'objet #%s est %s' % (id(item),item.value) ) # Exemple stockant la référence du générateur print( ' ' ); print( 'Autre exemple en stockant la référence du générateur' ) gen = BuildYielded(); for item in gen: print( 'TestYielded(): Valeur stockée est %s' % ( item.value) )
Le code précédent produissant le résultat ci-dessous.
Notez l'entrelas des appels entre les fonctions BuildYielded() et TestYielded()! Les générateurs sont plus particulièrement approprié lors de la manipulation de grands ensembles/set d'objets (voir l'exemple du point suivant concernant les générateurs et les listes de compréhension).
>>> TestYielded() La fonction BuildYielded() retourne un générateur. Notez que la fonction BuildYielded() n'est pas exécutée! <generator object at 0x839086c> Le resultat de la fonction peut être facilement énuméré. Notez l'entrelas des appels entre TestYielded() et BuildYielded() BuildYielded(): Create YieldedItem() object #0 TestYielded(): Valeur stockée dans l'objet #137953772 est 4 BuildYielded(): Create YieldedItem() object #1 TestYielded(): Valeur stockée dans l'objet #137955468 est 6 BuildYielded(): Create YieldedItem() object #2 TestYielded(): Valeur stockée dans l'objet #137953772 est 7 BuildYielded(): Create YieldedItem() object #3 TestYielded(): Valeur stockée dans l'objet #137955468 est 9 BuildYielded(): Create YieldedItem() object #4 TestYielded(): Valeur stockée dans l'objet #137953772 est 8 BuildYielded(): Create YieldedItem() object #5 TestYielded(): Valeur stockée dans l'objet #137955468 est 20 BuildYielded(): Create YieldedItem() object #6 TestYielded(): Valeur stockée dans l'objet #137953772 est 11 BuildYielded(): Create YieldedItem() object #7 TestYielded(): Valeur stockée dans l'objet #137955468 est 18 BuildYielded(): Create YieldedItem() object #8 TestYielded(): Valeur stockée dans l'objet #137953772 est 1 BuildYielded(): Create YieldedItem() object #9 TestYielded(): Valeur stockée dans l'objet #137955468 est 20 Autre exemple en stockant la référence du générateur BuildYielded(): Create YieldedItem() object #0 TestYielded(): Valeur stockée est 3 BuildYielded(): Create YieldedItem() object #1 TestYielded(): Valeur stockée est 18 BuildYielded(): Create YieldedItem() object #2 TestYielded(): Valeur stockée est 19 BuildYielded(): Create YieldedItem() object #3 TestYielded(): Valeur stockée est 9 BuildYielded(): Create YieldedItem() object #4 TestYielded(): Valeur stockée est 15 BuildYielded(): Create YieldedItem() object #5 TestYielded(): Valeur stockée est 3 BuildYielded(): Create YieldedItem() object #6 TestYielded(): Valeur stockée est 4 BuildYielded(): Create YieldedItem() object #7 TestYielded(): Valeur stockée est 22 BuildYielded(): Create YieldedItem() object #8 TestYielded(): Valeur stockée est 6 BuildYielded(): Create YieldedItem() object #9 TestYielded(): Valeur stockée est 9Les générateurs et comprehension list
Finalement, il est également possible d'associer les générateurs et les compréhensions lists (décrit en début d'article). le résultat étant appelé un "Generator Expression"!
Pour créer une générateur sur base d'une compréhension list, l'on utilise la syntaxe suivante où les parenthèses remplacent les crochets.
aGenerator = ( expression-manipulation for expression in sequence if test)
Un cas typique de son utilisation serait l'exécution de l'expression de manipulation (expression-manupilation) que lorsque l'on extrait l'information du generateur. Cela peut devenir utile si le processus est grand consommateur de ressource (comme des accès DB).
A Contrario, toutes les expressions de manipulation sont exécutées immédiatement lors de la création d'une expression list.
Voici un exemple extrait du module GenVsExpList.py .
""" Ce module d'exemple sert a mettre en évidence la différence de fonctionnement entre un Generator et une Comprehension List """ def transformIntForGen( iValue ): """Cette fonction de transformation est appelée pour transformer les valeurs d'un générateur d'expression. Grace à la trace, il est possible de déterminer le mode de fonctionnement.""" print( '%s: pour la value %s' % ( 'transforme for Generator', iValue) ) return 100-iValue def transformIntForCompList( iValue ): """Cette fonction de transformation est appelée pour transformer les valeurs d'une comprehension list. Grace à la trace, il est possible de déterminer le mode de fonctionnement.""" print( '%s: pour la value %s' % ( 'transform ComprehensionList', iValue) ) return 100-iValue def compareGenVsCompList(): """Fonction de comparaison d'execution de generateur et comprehension list""" print( '--- Comprehension List execution ---' ) print( '1) prepare comprehension list' ) _list = [ transformIntForCompList(i) for i in range(25) if i%3==0 ] print( '2) display comprehension list content' ) for index in range( len(_list) ): print( 'Comprehension List value #%s : %s' % ( index, _list[index]) ) print( '--- Generator expression execution ---' ) print( '1) prepare generator' ) _gen = ( transformIntForGen(i) for i in range(25) if i%3==0 ) print( '2) display generator expression content' ) # Dans le cas d'un générayeur, il faut malheureusement # gérer l'index soit même. _idx = 0 for item in _gen: print( 'Generator expression value #%s : %s' % ( _idx, item) ) _idx += 1
Le résultat démontre bien que dans le cas d'un generator expression, l'expression de transformation n'est appelée qu'au moment de l'extraction de la valeur!
>>> compareGenVsCompList() --- Comprehension List execution --- 1) prepare comprehension list transform ComprehensionList: pour la value 0 transform ComprehensionList: pour la value 3 transform ComprehensionList: pour la value 6 transform ComprehensionList: pour la value 9 transform ComprehensionList: pour la value 12 transform ComprehensionList: pour la value 15 transform ComprehensionList: pour la value 18 transform ComprehensionList: pour la value 21 transform ComprehensionList: pour la value 24 2) display comprehension list content Comprehension List value #0 : 100 Comprehension List value #1 : 97 Comprehension List value #2 : 94 Comprehension List value #3 : 91 Comprehension List value #4 : 88 Comprehension List value #5 : 85 Comprehension List value #6 : 82 Comprehension List value #7 : 79 Comprehension List value #8 : 76 --- Generator expression execution --- 1) prepare generator 2) display generator expression content transforme for Generator: pour la value 0 Generator expression value #0 : 100 transforme for Generator: pour la value 3 Generator expression value #1 : 97 transforme for Generator: pour la value 6 Generator expression value #2 : 94 transforme for Generator: pour la value 9 Generator expression value #3 : 91 transforme for Generator: pour la value 12 Generator expression value #4 : 88 transforme for Generator: pour la value 15 Generator expression value #5 : 85 transforme for Generator: pour la value 18 Generator expression value #6 : 82 transforme for Generator: pour la value 21 Generator expression value #7 : 79 transforme for Generator: pour la value 24 Generator expression value #8 : 76
lundi 19 octobre 2009
Exception en Python
Mécanisme standard d'exception
Ce mécanisme n'est pas différent des autres environnements évolués. En voici la notation en Python.
Python requière l'usage de classes dans les mécanismes d'exception. Cette dernière servira à l'identification du type d'exception ainsi qu'au transport des arguments/details de l'exception. Bien que toutes les classes soient acceptées,il est préférable d'utiliser un descendant d'Exception... cela permet de faire un casting d'erreur efficace. Encore une fois, rien de différent par rapport aux autres langages évolués.
Casting d'exception
Le casting d'exception s'obtient en placant la classe après le mot clé "except". Dans ce cas, seule les exceptions de ce type (et dérivés) seront interceptées.
Il est également possible de récupérer une référence vers l'objet d'exception en déclarant un second paramètre après le mot clé except.
Classes d'exception de base
Ce type d'erreur accepte un "Numéro d'erreur" et un message (les No d'erreur étant très courant en programmation système).
Voir attibut "errno".
Parmis les descendant, l'on retrouve IOError et OSError
Parmis les descendant l'on retrouve UnicodeEncodeError, UnicodeDecodeError.
Notes en vrac
Ce mécanisme n'est pas différent des autres environnements évolués. En voici la notation en Python.
try: try: # Création d'une exception ! 4/0 except: print('except') raise finally: print( 'finally' ) # ou encore try: 4/0 except: print('except') raise finally: print( 'finally' )Résultat:
except finally Traceback (most recent call last): File "<stdin>", line 3, in <module> ZeroDivisionError: integer division or modulo by zeroCréer une classe d'exception
Python requière l'usage de classes dans les mécanismes d'exception. Cette dernière servira à l'identification du type d'exception ainsi qu'au transport des arguments/details de l'exception. Bien que toutes les classes soient acceptées,il est préférable d'utiliser un descendant d'Exception... cela permet de faire un casting d'erreur efficace. Encore une fois, rien de différent par rapport aux autres langages évolués.
class myError(Exception): pass def doAnError(): raise myError() doAnError() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in doAnError __main__.myError: <__main__.myError instance at 0xb7d0804c>
Casting d'exception
Le casting d'exception s'obtient en placant la classe après le mot clé "except". Dans ce cas, seule les exceptions de ce type (et dérivés) seront interceptées.
try: 8/0 except ArithmeticError: print( 'Oups!' )
Il est également possible de récupérer une référence vers l'objet d'exception en déclarant un second paramètre après le mot clé except.
class anError( Exception ): pass try: raise anError() except Exception, errObj: print( id(errObj) ) dir( errObj ) print( errObj ) print( '--- End of Exception ---' )Resultat:
3080090404 ['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__getitem__', '__getslice__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__str__', '__weakref__', 'args', 'message'] --- End of Exception ---
Classes d'exception de base
Exception
Classe de base de toutes les exceptions. Le constructeur prend en plusieurs paramètres qui sont stockés dans l'attribut args. Lors de l'affichage par l'interpreteur, le function __str__() est appelée pour afficher les informations de l'exception. Dans le cas de Exception, __str__() affiche le contenu de l'attribut args.StandardError
class StandardError( Exception )
Classe de base de presque toutes les exceptions en Python.ArithmeticError
class ArithmeticError( StandardError )
Pour toutes les erreurs. On retrouve en descendant ZeroDivisionError, OverflowError (dépassement de capacité), FloatingPointError (erreur en calcul flottant)LookupError
class LookupError( StandardError )
Utilisé lors de l'utilisation d'un index est incorrect sur une liste ou lors de l'utilisation d'une clé incorrecte dans un mapping. EnvironmentError
class EnvironmentError( StandardError )
Utilisé comme classe de base pour les erreurs de type système (lecture fichier, appel API, etc).Ce type d'erreur accepte un "Numéro d'erreur" et un message (les No d'erreur étant très courant en programmation système).
Voir attibut "errno".
Parmis les descendant, l'on retrouve IOError et OSError
ValueError
Class ValueError( StandardError )
Utiliser pour indiqué une valeur d'argument inappropriée (de type incorrecte).UnicodeError
class UnicodeError( ValueError )
Classe de base pour les erreur de conversion unicode.Parmis les descendant l'on retrouve UnicodeEncodeError, UnicodeDecodeError.
AttributeError
class AttributeError( StandardError )
Indique un attribut manquant.NameError
class NameError( StandardError )
Indique un nom qui, globalement, ne peut pas être résolu.Notes en vrac
Passage d'arguments à la classe d'Exception
def doSomeStuffWithError():
try:
4/0
except:
raise Exception('Un message d\'erreur', 'un brol', -12 )
doSomeStuffWithError()
print( '-----------------------' )
try:
doSomeStuffWithError()
except Exception, errObj:
print( errObj.args )
avec pour résultat:Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 5, in doSomeStuffWithError Exception: ("Un message d'erreur", 'un brol', -12) ----------------------- ("Un message d'erreur", 'un brol', -12)
Casting multiples
try: doStuffWithError() except ArithmeticError: print( 'Damned!! A math error!' ) # Matching a list of exception class except (AttributeError, IOError ): print( 'Oups!' )
mardi 13 octobre 2009
Quelques distributions Linux
Issus d'un article parut sur TooLinux, voici quelques distributions Linux pouvant présenter un quelconque intérêt (selon les circonstances).
Tiny Core Linux
Une distribution Linux compacte (10Mo). Avec cette taille réduit, Tiny Core s'offre même le luxe d'un environnement graphique!
Plus d'information sur le site Tiny Core Linux (screenshots ici).
Easy Peasy
Distribution destinée aux Netbooks et basée sur Ubuntu.
La vidéo ci-dessous montre d'ailleurs cette distribution en fonctionnement sur un Eee PC d'Asus 900.
Plus d'information sur Easy Peasy ici (screenshots) ou encore sur la Home Page du projet.
Ultimate Edition
Une version Linux spécialement dédiée aux jeux.
Plus d'information et téléchargement sur le site Ultimate Edition
Les incontournables
Voici quelques incontournables comme Puppy (screenshots et intro ici) qui n'a besoin que de 64Mb ou encore SystemRescueCd.
Une liste complète de distributions
Voir cette article sur TooLinux.
On y retrouvera des distribution couteaux Suisse pour le dépannage, le partionning des disques, l'analyse réseau.
Tiny Core Linux
Une distribution Linux compacte (10Mo). Avec cette taille réduit, Tiny Core s'offre même le luxe d'un environnement graphique!
Plus d'information sur le site Tiny Core Linux (screenshots ici).
Easy Peasy
Distribution destinée aux Netbooks et basée sur Ubuntu.
La vidéo ci-dessous montre d'ailleurs cette distribution en fonctionnement sur un Eee PC d'Asus 900.
Plus d'information sur Easy Peasy ici (screenshots) ou encore sur la Home Page du projet.
Ultimate Edition
Une version Linux spécialement dédiée aux jeux.
Plus d'information et téléchargement sur le site Ultimate Edition
Les incontournables
Voici quelques incontournables comme Puppy (screenshots et intro ici) qui n'a besoin que de 64Mb ou encore SystemRescueCd.
Une liste complète de distributions
Voir cette article sur TooLinux.
On y retrouvera des distribution couteaux Suisse pour le dépannage, le partionning des disques, l'analyse réseau.
lundi 12 octobre 2009
Les pics de grippe selon Google
Google évalue l'évolution des pics de grippe dans différents pays sur base de données collectées via la net.
Ces données misent en regard avec les données d'années précédentes permettent de se faire une idée de l'évolution mois par mois.
Ainsi, l'on apprendra:
Saviez-vous que la grippe est assez communément dénommée la "maladie des mains".
Les mains sont un excellent vecteur de contamination... On éternue dans les mains, on touche son matériel... des poignées de portes ainsi que divers endroits où l'on dépose alors ses "petits microbes".
Ces mêmes poignées de portes, ustensiles et endroits touchés par vos congénères, amis et membres de votre famille.
Ces pauvres congénères qui se frottent les yeux, le nez, la bouche... des gestes simplement naturel au quotidien.
C'est la raison pour laquelle il est important d'avoir une hygiène des mains irréprochable.
Dans le milieu de travail, le simple prêt d'un stylo à bille peut devenir un vecteur de contamination si l'hygiène n'est pas correcte.
Il n'est pas nécessaire de devenir parano... quelques règles de bon sens et un peu d'hygiène feront l'affaire :-)
Ces données misent en regard avec les données d'années précédentes permettent de se faire une idée de l'évolution mois par mois.
Ainsi, l'on apprendra:
- Que la Belgique dispose d'un pic de grippe ciblé et donc une période relativement courte de risque de contamination (a comparer avec l'Allemagne et le Canada par exemple).
- Que cette année, la Belgique présente un niveau de contamination un peu plus élevé (entre basse et moyenne) que les autres années. A cette période le taux de contamination est habituellement minimal.
C'est une bonne nouvelle, les conditions sont assez bonnes :-)
- Que le pic de grippe est très étalé au Canada et en Allemagne (bien plus qu'en Belgique).
Ces deux pays présentant taux moyen de contamination plus important et plus longtemps.
- Que la Suède et la Norvège (ayant un modèle de pic Janvier-Février -- similaire à la Belgique) sont en avance. Leurs pics ayant eu le maxima mi-aout par rapport aux autres années.
- Que la Russie connait ses pics aux alentours de février-mars (donc après nous).
- Éternuer et tousser dans un mouchoir (sa manche ou ses mains) pour éviter les prolifération.
- Se laver les mains souvent.
- Rester chez soi en cas de grippe déclarée.
Saviez-vous que la grippe est assez communément dénommée la "maladie des mains".
Les mains sont un excellent vecteur de contamination... On éternue dans les mains, on touche son matériel... des poignées de portes ainsi que divers endroits où l'on dépose alors ses "petits microbes".
Ces mêmes poignées de portes, ustensiles et endroits touchés par vos congénères, amis et membres de votre famille.
Ces pauvres congénères qui se frottent les yeux, le nez, la bouche... des gestes simplement naturel au quotidien.
C'est la raison pour laquelle il est important d'avoir une hygiène des mains irréprochable.
Dans le milieu de travail, le simple prêt d'un stylo à bille peut devenir un vecteur de contamination si l'hygiène n'est pas correcte.
Il n'est pas nécessaire de devenir parano... quelques règles de bon sens et un peu d'hygiène feront l'affaire :-)
jeudi 8 octobre 2009
Delphi 2009 Handbook
Marco Cantù propose son ouvrage "Delphi 2009 Handbook" sur Lulu.com (aussi disponible via Amazon).
Ce livre consacre une partie de son contenu à l'implémentation Unicode maintenant devenu le type par défaut des strings et chars (les anciens types 8 bits étant devenu AnsiChar et AnsiString).
Pour information, le standard de transformation en Delphi est UTF-16.
Hormis le côté Unicode, ce livre se consacre également aux points suivants:
Plus d'information ici sur le site de Marco Cantù.
Note:
Le site de Marco Cantù référence également un article intéressant comparant les langages OOP.
Ce livre consacre une partie de son contenu à l'implémentation Unicode maintenant devenu le type par défaut des strings et chars (les anciens types 8 bits étant devenu AnsiChar et AnsiString).
Pour information, le standard de transformation en Delphi est UTF-16.
Hormis le côté Unicode, ce livre se consacre également aux points suivants:
- Type génériques
- Méthodes anonymes.
- Support COM en Delphi 2009.
- DataSnap 2009
- DBExpress
Plus d'information ici sur le site de Marco Cantù.
Note:
Le site de Marco Cantù référence également un article intéressant comparant les langages OOP.
Libellés :
Delphi,
Développement,
Lecture
Définition des propriétés en Python
Petit exemple montrant la définition des propriétés dans les classes Pyhton (les classes New-Styles dérivant explicitement de "object")
>>> class Car(object): def __init__(self): self._im = '%s' % id(self) self._changed = False def _getim( self ): return self._im def _setim( self, value ): if value != self._im: self._im = value self._changed = True def _getchanged( self ): return self._changed immatriculation = property( _getim, _setim, None ) hasChanged = property( _getchanged, None, None ) >>> Cars = dict() >>> Cars['domeu']= Car() >>> Cars['frc']= Car() >>> # can also be written as follow >>> # Cars = dict( (('domeu', Car()), ('frc', Car())) ) >>> for key, value in Cars.items(): print( 'Car of %s with immatriculation "%s". Changed? %s.' % (key,value.immatriculation, value.hasChanged) ) Car of frc with immatriculation "18698568". Changed? False. Car of domeu with immatriculation "18511832". Changed? False. >>> >>> Cars['domeu'].immatriculation = 'XYZ 103' >>> for key, value in Cars.items(): print( 'Car of %s with immatriculation "%s". Changed? %s.' % (key,value.immatriculation, value.hasChanged) ) Car of frc with immatriculation "18668880". Changed? False. Car of domeu with immatriculation "XYZ 103". Changed? True.
mercredi 7 octobre 2009
Enumérer les méthodes d'une classe (en Run-Time)
L'article "Class RTTI" offre une introduction intéressante à l'utilisation des informations RTTI, HostScripting et de l'invocation automatique des méthodes depuis les WebSnap.
L'utilisation de {$METHODINFO ON} avec l'unité DetailedRtti.pas de David Glassborrow permet d'envisager l'extraction et l'utilisation des informations RTTI en RunTime pour faire des appels dynamiques.
Fournit sous forme de Class Helper et Record Helper, DetailedRtti.pas permet, par exemple, d'extraire la définition des méthodes/fields/etc d'une classe.
L'exemple ci-dessous énumère toutes les méthodes d'un object.
L'énumération des méthodes peuvent s'avérée utile lors de l'invocation sur à la volée (par exemple à l'aide de MethodAddress).
L'utilisation de {$METHODINFO ON} avec l'unité DetailedRtti.pas de David Glassborrow permet d'envisager l'extraction et l'utilisation des informations RTTI en RunTime pour faire des appels dynamiques.
Fournit sous forme de Class Helper et Record Helper, DetailedRtti.pas permet, par exemple, d'extraire la définition des méthodes/fields/etc d'une classe.
L'exemple ci-dessous énumère toutes les méthodes d'un object.
type {$METHODINFO ON} TFRM_Main = class(TForm) SBB_Button1: TButton; ... procedure TFRM_Main.Button1Click(Sender: TObject); begin Log( self.RTTIMethodsAsString ); end;
L'énumération des méthodes peuvent s'avérée utile lors de l'invocation sur à la volée (par exemple à l'aide de MethodAddress).
type TTestProc = procedure of object; {$METHODINFO ON} TForm1 = class(TForm) SBB_DoTesting: TButton; ... published procedure Proc_TestMe; procedure Proc_TestMeAlso; end; ... procedure TForm1.RunThis(aProcedureName: String); var pProc : TTestProc; begin ShowInfo( 'Executer la méthode '+aProcedureName ); TMethod(pProc).Data := Self; TMethod(pProc).Code := MethodAddress( 'proc_'+aProcedureName); try if not Assigned(TMethod(pProc).Code) then raise Exception.Create( 'Failed to locate test "proc_'+aProcedureName+'" method address' ); pProc(); except on e:Exception do ShowError( E.Message+' ('+E.ClassName+')' ); end; end; ... procedure TForm1.SBB_DoTestingClick(Sender: TObject); begin // Exemple d'appel dynamique (à partir du nom de la méthode) RunThis( 'TestMe' ); RunThis( 'TestMeAlso' ); end; ...
mardi 6 octobre 2009
Inclure une DLL dans les ressource d'un logiciel
Voici une recette de cuisine trouvée sur LinkedIn permettant d'inclure une DLL directement dans les ressources d'un éxécutable.
1. Inclure la DLL dans une RAW section du fichier ressource. Ainsi, il sera linker dans l'exe au moment de la compilation.
2a) Ajouter un bout code au programme qui extrait la DLL des ressources et la stocker sur le disque avant de la charger avec un loadLibrary.
2b) Une autre option est de copier directement en mémoire la DLL disponible en ressource . Ensuite créer des liens dynamiques permettant au programme d'appeler les procédures de la DLL (demande un effort de programmation plus poussé).
Le composant TFakeDll (disponible sur uinC/Underground INformation Center) permet d'inclure des DLL en ressources.
Bien qu'ils datent un peu, uinC contient également d'autre code sources Delphi comme des KeyLogger, Password Cracker, etc... toujours intéressant pour assouvir sa curiosité.
1. Inclure la DLL dans une RAW section du fichier ressource. Ainsi, il sera linker dans l'exe au moment de la compilation.
2a) Ajouter un bout code au programme qui extrait la DLL des ressources et la stocker sur le disque avant de la charger avec un loadLibrary.
2b) Une autre option est de copier directement en mémoire la DLL disponible en ressource . Ensuite créer des liens dynamiques permettant au programme d'appeler les procédures de la DLL (demande un effort de programmation plus poussé).
Le composant TFakeDll (disponible sur uinC/Underground INformation Center) permet d'inclure des DLL en ressources.
Bien qu'ils datent un peu, uinC contient également d'autre code sources Delphi comme des KeyLogger, Password Cracker, etc... toujours intéressant pour assouvir sa curiosité.
samedi 3 octobre 2009
L'univers de la sience - Isaac Asimov
Quelle chance, le week-end dernier j'ai découvert mon premier ouvrage de vulgarisation issu de la plume d'Isaac Asimov au pêle-mêle de Waterloo.
En plus d'être un grand écrivain de science fiction, Isaac Asimov était également un excellent vulgarisateur scientifique et historique. A sa mort, Isaac Asimov comptabilisait pas moins de 400 oeuvres.
C'est avec un grand plaisir que je me lance dans la lecture de "l'Univers de la science" (1986, interEditions, Paris), une belle brique de 900 pages.
En voici d'ailleurs un extrait consacré à la curiosité comme le moteur du "désir de savoir", ce désir faisant avancer la science par les découvertes qui en découlent.
En plus d'être un grand écrivain de science fiction, Isaac Asimov était également un excellent vulgarisateur scientifique et historique. A sa mort, Isaac Asimov comptabilisait pas moins de 400 oeuvres.
C'est avec un grand plaisir que je me lance dans la lecture de "l'Univers de la science" (1986, interEditions, Paris), une belle brique de 900 pages.
En voici d'ailleurs un extrait consacré à la curiosité comme le moteur du "désir de savoir", ce désir faisant avancer la science par les découvertes qui en découlent.
Le cerveau humain est le morceau de matière le plus merveilleusement organisé de l'Univers connu, et sa capacité de recevoir, de classer et d'enregistrer l'information dépasse très largement les besoins ordinaires de la vie. On a estimé que, au cours de sa vie, un être humain pouvaient emmagasiner 15000 milliards d'informations.
C'est à cette disponibilité que nous devons d'être vulnérables à une maladie très pénible, l'ennui. Un être humain, placé dans une situation où il n'a aucune occasion d'utiliser son cerveau si ce n'est pour assurer sa survie, ressentira une quantité croissante de symptômes inquiétants, jusqu'à connaître de graves troubles mentaux. Le fait est que l'être humain normal possède une curiosité intense et irrésistible. S'il n'a pas la possibilité de la satisfaire d'une façon immédiatement utile, il la satisfera par d'autres moyen - y compris des moyens regrettables, qui sont à l'origine d'expressions courantes comme "melez-vous de vos affaires" ou "la curiosité est un vilain défaut".
L'univers de la science, Isaac Asimov, Page 4.
Edt InterEditions (Paris), ISBN 2-7296-0141-4
Trad: Françoise Balibar, Claude Guthmann, Alain Laverne et Jean-Pierre Maury.
Inscription à :
Articles (Atom)