Marc Lambert publie 90 Partitions gratuites pour guitare, toutes classées par niveau de difficulté.
"Marc sa guitare" accessible sur guitare.org publie aussi des partitions pour groupe de trois ou quatre guitares.
En guise d'exemple, voici une interprétation de la "Valse Bleue" de Marc Lambert.
Simplement magnifique!
mardi 29 décembre 2009
mercredi 23 décembre 2009
Utilisation des blogs pour consolider les connaissances d'entreprise
L'utilisation et la tenue d'un blog est souvent considéré comme une perte de temps par le monde du travail.
Dans le cadre professionnel, il existe cependant une utilisation rentable de ces blogs
L'avis personnel
L'expérience de cette dernière année avec "Developer Notepad" (ce blog) a été professionnellement payant plus d'une fois. Une simple recherche Google fournissant une réponse aux questions déjà abordées et élucidées.
L'utilisation d'un blog de type professionnel pour organiser et maintenir des connaissances techniques est devenu pour moi une évidence en soi.
A mes yeux, le retour sur investissement (le temps nécessaire à la rédaction) ne fait plus de doute et est parfaitement démontrable.
Je dois avouer que mon expérience recoupe parfaitement les conclusions exposées dans l'article de Jean-Luc Tholozan (voir "un retour d'expérience" ci-dessous).
Article que je vous invite par ailleurs à parcourir.
Un retour d'expérience
Allant plus loin dans l'étude d'utilisation d'un Blog, Jean-Luc Tholozan a écrit l'article "Entreprise 2.0 : Blogging en R&D, Un retour d'expérience".
Dans ce dernier, il partage son expérience et ses conclusions sur l'utilisation des technologies WEB 2.0 (et donc aussi les blogs) "dans le cadre d'une étude sur l'utilisation de ces technologies à la gestion des connaissances dans le monde de l'entreprise" (dixit Jean-Luc Tholozan).
Cet article très bien construit démontre l'utilité, la pertinence et les avantages de l'utilisation d'un Blog publique dans un service de Recherche et Développement.
J'ai également été impressionné par l'approche concernant la pérénité et la consolidation des informations acquises par le service de R&D de son entreprise.
Voici un extrait de de l'article "Entreprise 2.0 : Blogging en R&D, Un retour d'expérience" publié sur Architecture des S.I.
Un article de grande qualité et pertinent.
Un incontournable à lire!
Sources:
Dans le cadre professionnel, il existe cependant une utilisation rentable de ces blogs
L'avis personnel
L'expérience de cette dernière année avec "Developer Notepad" (ce blog) a été professionnellement payant plus d'une fois. Une simple recherche Google fournissant une réponse aux questions déjà abordées et élucidées.
L'utilisation d'un blog de type professionnel pour organiser et maintenir des connaissances techniques est devenu pour moi une évidence en soi.
A mes yeux, le retour sur investissement (le temps nécessaire à la rédaction) ne fait plus de doute et est parfaitement démontrable.
Je dois avouer que mon expérience recoupe parfaitement les conclusions exposées dans l'article de Jean-Luc Tholozan (voir "un retour d'expérience" ci-dessous).
Article que je vous invite par ailleurs à parcourir.
Un retour d'expérience
Allant plus loin dans l'étude d'utilisation d'un Blog, Jean-Luc Tholozan a écrit l'article "Entreprise 2.0 : Blogging en R&D, Un retour d'expérience".
Dans ce dernier, il partage son expérience et ses conclusions sur l'utilisation des technologies WEB 2.0 (et donc aussi les blogs) "dans le cadre d'une étude sur l'utilisation de ces technologies à la gestion des connaissances dans le monde de l'entreprise" (dixit Jean-Luc Tholozan).
Cet article très bien construit démontre l'utilité, la pertinence et les avantages de l'utilisation d'un Blog publique dans un service de Recherche et Développement.
J'ai également été impressionné par l'approche concernant la pérénité et la consolidation des informations acquises par le service de R&D de son entreprise.
Voici un extrait de de l'article "Entreprise 2.0 : Blogging en R&D, Un retour d'expérience" publié sur Architecture des S.I.
Une seconde raison de l'utilisation du Blog est qu'il correspond bien à la problématique de publication d'une équipe de R&D : les phases de recherche s'appuient sur des études bibliographiques importantes. On a très vite tendance à lire et oublier pour passer rapidement à l'étape suivante. Les étapes intermédiaires disparaissent plus ou moins rapidement de la mémoire du chercheur, mais n'entre jamais dans le patrimoine de connaissance de l'entreprise. La publication sous forme de Blog permet d'alterner les phases de lectures et celles de publications : ces dernières permettent à la fois la consolidation des connaissances de l'individu chercheur mais également la consolidation des connaissances dans l'entreprise.Avec ses conclusions
La création de Blog personnel pour une équipe de R&D s'avère très rentable pour l'entreprise :
- le suivi de la R&D est facilité
- la productivité n'est pas pénalisée : l'effort supplémentaire est compensé par les gains qui suivent
- le patrimoine de connaissance de l'entreprise est consolidé
Un article de grande qualité et pertinent.
Un incontournable à lire!
Sources:
- L'article "Entreprise 2.0 : Blogging en R&D, Un retour d'expérience" publié sur Architecture des S.I.
- L'article "Windows Live Writer et Blogger"
- L'article "Pourquoi utiliser Blogger ? Un retour d'expérience"
- Le blog Architecture des S.I
mardi 22 décembre 2009
Isodore de Séville, le saint patron des informaticiens
Fêté le 4 avril, Isodore de Séville à été proposé comme Saint patron des informaticiens (des utilisateurs d'ordinateurs et d'internet par extension).
Ce qui vaut à Saint Isidore de devenir notre potentiel Saint patron, c'est la création et l'organisation d'un bestiaire médiévale pour l'un des 26 volumes constituant son oeuvre relative à l'étymologique.
En agissant de la sorte, Isodore fût un précurseur en créant une table des matières qui sert à l'indexation du contenu (du moins assimilé comme). Ces mêmes indexes, ordonnancements alphabétiques, que l'univers de l'information (et donc les informaticiens) utilise à outrance.
Isidore de Séville, né entre 560 et 570 à Carthagène (Espagne) – mort le 4 avril 636, est un religieux espagnol du VIIe siècle. Il a été canonisé en 1598 et est fêté chaque année le 4 avril (Isidore de Séville sur Wikipédia).
Bref, lors du prochain plantage ou bug, je saurai enfin quel Saint invoquer :-)
Ce qui vaut à Saint Isidore de devenir notre potentiel Saint patron, c'est la création et l'organisation d'un bestiaire médiévale pour l'un des 26 volumes constituant son oeuvre relative à l'étymologique.
En agissant de la sorte, Isodore fût un précurseur en créant une table des matières qui sert à l'indexation du contenu (du moins assimilé comme). Ces mêmes indexes, ordonnancements alphabétiques, que l'univers de l'information (et donc les informaticiens) utilise à outrance.
Isidore de Séville, né entre 560 et 570 à Carthagène (Espagne) – mort le 4 avril 636, est un religieux espagnol du VIIe siècle. Il a été canonisé en 1598 et est fêté chaque année le 4 avril (Isidore de Séville sur Wikipédia).
Bref, lors du prochain plantage ou bug, je saurai enfin quel Saint invoquer :-)
Un meilleur éditeur pour Blogger
Petite mise-à-jour ce 22 décembre pour référencer "Windows Live Writer" et "ScribeFire"
Blogger dispose d'une interface d'édition nettement plus efficace et conviviale que l'interface actuelle.
Cette nouvelle interface est accessible via le site "laboratoire" draft.blogger.com .
Je dois reconnaître que c'est une version vraiment pratique et surtout stable.
Les fonctionnalités de draft.blogger.com sont décrites ici sur le blog de Roberto.
Il est possible de tester l'éditeur directement depuis draft.blogger.com.
S'il convient, activer l'option "Faire de Blogger in Draft mon tableau de bord par défaut" dans le tableau de bord. Il sera ainsi possible de profiter de ce nouvel éditeur directement depuis les pages du blog.
Toujours en se fiant à l'article de Jean-Luc Tholozan, ce logiciel est compatible avec Blogger et offre une confort d'utilisation de loin bien plus agréable que l'éditeur en ligne de Blogger.
WLW supporte le copier/coller avec Word sans importer/générer de code html parasite (véritable plaie du support HTML de Word). WLW se présente là comme un excellent intermédiaire d'autant plus qu'il travaille en mode déconnecté. Finalement, et non des moindres, WLW gère parfaitement les caratères ">" , "<" et dispose d'un mode d'édition HTML.
Jean-Luc semblait assez satisfait de la combinaison Word + WLW + Blogger pour la production d'un blog.
A tester donc...
Blogger dispose d'une interface d'édition nettement plus efficace et conviviale que l'interface actuelle.
Cette nouvelle interface est accessible via le site "laboratoire" draft.blogger.com .
Je dois reconnaître que c'est une version vraiment pratique et surtout stable.
Les fonctionnalités de draft.blogger.com sont décrites ici sur le blog de Roberto.
Il est possible de tester l'éditeur directement depuis draft.blogger.com.
S'il convient, activer l'option "Faire de Blogger in Draft mon tableau de bord par défaut" dans le tableau de bord. Il sera ainsi possible de profiter de ce nouvel éditeur directement depuis les pages du blog.
Windows Live Writer
Pour les habitués de Microsoft, il semblerait qu'il existe un produit gratuit nommé "Windows Live Writer" (WLW).Toujours en se fiant à l'article de Jean-Luc Tholozan, ce logiciel est compatible avec Blogger et offre une confort d'utilisation de loin bien plus agréable que l'éditeur en ligne de Blogger.
WLW supporte le copier/coller avec Word sans importer/générer de code html parasite (véritable plaie du support HTML de Word). WLW se présente là comme un excellent intermédiaire d'autant plus qu'il travaille en mode déconnecté. Finalement, et non des moindres, WLW gère parfaitement les caratères ">" , "<" et dispose d'un mode d'édition HTML.
Jean-Luc semblait assez satisfait de la combinaison Word + WLW + Blogger pour la production d'un blog.
A tester donc...
ScribeFire
Mentionné pour mémoire, ScribeFire est un plug-in FireFox permettant de facilité la publication de billet (y compris sur Blogger)
jeudi 17 décembre 2009
Quelques caratéristiques avancées du langage Python
Le langage Python dispose de quelques fonctions ou classes avancées qui peuvent se montrer vraiment utile dans des domaines pointus et pour le développement d'applications d'envergure.
Cet article reprend également quelques fonctions relatives aux éléments itérables.
__import__
__import__ est une primitive du langage permettant de charger un module (fichier .py) à la volée.
Cette primitive est principalement utilisé dans le cadre d'activation de modules plug-ins.
compile
La fonction compile permet de compiler du code source Pyhton à la volée.
Ce code source pouvant être contenu dans une chaine de caractère.
Par la suite, ce code compilé pourra être exécuté à l'aide de la primitive exec() ou eval().
Les cas d'utilisation de compile sont rare. Cependant, cette fonctionnalité convient très bien aux logiciels évolutifs (capable de se modifier par eux-mêmes).
Note:
Lors de l'utilisation de la fonction compile, il faut indique le mode de compilation.
Pour la compilation d'une expression à évaluer; le mode 'eval' convient très bien.
Bien qu'il soit indiqué que le mode 'single' convienne pour plusieurs instructions, je n'ai eu un résultat probant qu'en utilisant le mode 'exec' (voir l'exemple relatif à eval).
eval
Permet d'effectuer une évaluation (ou exécution) de code Python à la volée.
La fonction eval permet également d'utiliser le contexte actuel d'exécution (les variables définie et accessible au code appelant le seront également pour le code évalué) ou de définir le contexte d'exécution.
execfile
Comme son nom le suggère, execfile permet d'exécuter le code contenu dans un fichier Python.
Cette exécution peut exploiter le contexte actuel ou redéfinir un contexte.
enumerate
Itération. Permet d'associer un indice/index numérique à chaque élément du contenu itérable.
filter
Itération. La fonction filter permet de filtrer le contenu d'un tuple, list ou chaîne de caractères à l'aide d'une fonction. Seuls les éléments retournant True à la fonction de filtrage seront conservés.
None peut également être utilisé comme fonction de filtrage.
Dans ce cas, seul les éléments évalués comme True seront conservés (autrement dit, tout élément/objet ayant une référence). C'est une méthode bien pratique pour éliminer les éléments None d'une liste.
reduce
Itération. Reduce permet d'appliquer une fonction de transformation de façon continu aux éléments d'une séquence.
Les 2 premiers éléments de la séquence sont utilisé avec la fonction.
Le résultat est alors utilisé avec le 3ième élément de la séquence pour rappeler la fonction.
Le nouveau résultat obtenu est alors utilisé avec le 4ième élément de la séquence pour rappeler la fonction.
Et ainsi de suite jusqu'à la fin de la séquence.
L'exemple suivant illustre parfaitement le fonctionnement de la fonction reduce.
Reduce peut également prendre une valeur initiale en troisième argument.
Cela permet de reprendre/compléter une opération reduce avec des nouvelles données.
Cas d'utilisation:
Itération. Permet d'appliquer une fonction de transformation à chacun des éléments d'une structure itérable.
A noter que map peut être utilisé avec plusieurs listes. Dans ce cas, les éléments seront joints (un à un) et passés en paramètres de la fonction de transformation.
La fonction de transformation peut être None, dans ce cas, les éléments sont retournés (joint) tel quel et combinés en Tuple. Si l'une des liste est plus courte le tuple contiendra None pour l'élément manquant.
all
Itération. Permet de tester l'homogénéité d'une séquence.
La fonction all retourne true si tous tous les éléments d'une séquence peuvent être évalués comme vrai.
Les éléments évalués peuvent être des références d'objets (assignés=True ou None=False) ou des expressions booléennes.
any
Itération. Permet de tester facilement le contenu d'une séquence.
La fonction any retourne true si au moins un des éléments de la séquence séquence peut être évalué comme vrai.
Les éléments évalués peuvent être des références d'objets (assignés ou None) ou des expressions booléennes.
Cet article reprend également quelques fonctions relatives aux éléments itérables.
__import__
__import__ est une primitive du langage permettant de charger un module (fichier .py) à la volée.
Cette primitive est principalement utilisé dans le cadre d'activation de modules plug-ins.
compile
La fonction compile permet de compiler du code source Pyhton à la volée.
Ce code source pouvant être contenu dans une chaine de caractère.
Par la suite, ce code compilé pourra être exécuté à l'aide de la primitive exec() ou eval().
Les cas d'utilisation de compile sont rare. Cependant, cette fonctionnalité convient très bien aux logiciels évolutifs (capable de se modifier par eux-mêmes).
Note:
Lors de l'utilisation de la fonction compile, il faut indique le mode de compilation.
Pour la compilation d'une expression à évaluer; le mode 'eval' convient très bien.
Bien qu'il soit indiqué que le mode 'single' convienne pour plusieurs instructions, je n'ai eu un résultat probant qu'en utilisant le mode 'exec' (voir l'exemple relatif à eval).
eval
Permet d'effectuer une évaluation (ou exécution) de code Python à la volée.
La fonction eval permet également d'utiliser le contexte actuel d'exécution (les variables définie et accessible au code appelant le seront également pour le code évalué) ou de définir le contexte d'exécution.
>>> myInt = 123 >>> sToEvaluate = 'myInt * 2' >>> eval( sToEvaluate ) 246 >>> # Modify the execution context >>> eval( sToEvaluate, {'myInt' : 12} ) 24 >>> sToEvaluate = 'x = 3\nprint( "%s * %s = %s" % (x, myInt, x*myInt) )' >>> # Use 'exec' compilation mode because there are several lines! >>> _compiled = compile( sToEvaluate, '/dev/null', 'exec' ) >>> eval( _compiled, {'myInt':12} ) 3 * 12 = 36
execfile
Comme son nom le suggère, execfile permet d'exécuter le code contenu dans un fichier Python.
Cette exécution peut exploiter le contexte actuel ou redéfinir un contexte.
enumerate
Itération. Permet d'associer un indice/index numérique à chaque élément du contenu itérable.
>>> myList = [ 1, 13, 22, 4, 6, 17, 88, 65 ] >>> for index, valeur in enumerate( myList ): print( 'valeur à l''index %s : %s' % (index, valeur) ) valeur à lindex 0 : 1 valeur à lindex 1 : 13 valeur à lindex 2 : 22 valeur à lindex 3 : 4 valeur à lindex 4 : 6 valeur à lindex 5 : 17 valeur à lindex 6 : 88 valeur à lindex 7 : 65 >>> myString = 'Hello !' >>> for index, char in enumerate( myString ): print ( '%s - %s ' % (index, char) ) 0 - H 1 - e 2 - l 3 - l 4 - o 5 - 6 - !
filter
Itération. La fonction filter permet de filtrer le contenu d'un tuple, list ou chaîne de caractères à l'aide d'une fonction. Seuls les éléments retournant True à la fonction de filtrage seront conservés.
None peut également être utilisé comme fonction de filtrage.
Dans ce cas, seul les éléments évalués comme True seront conservés (autrement dit, tout élément/objet ayant une référence). C'est une méthode bien pratique pour éliminer les éléments None d'une liste.
>>> myList = [ 1, 13, 22, 4, 6, 17, 88, 65 ] >>> def myFilter( i ): return i>=10 >>> myFiltered = filter( myFilter, myList ) >>> for item in myFiltered: print item 13 22 17 88 65 >>> myString = "Voici une chaine de caractère. Je veux enlever les espaces" >>> def isNotSpace( aChar ): return aChar != ' ' >>> myFilteredString = filter( isNotSpace, myString ) >>> print myFilteredString Voiciunechainedecaractère.Jeveuxenleverlesespaces
reduce
Itération. Reduce permet d'appliquer une fonction de transformation de façon continu aux éléments d'une séquence.
Les 2 premiers éléments de la séquence sont utilisé avec la fonction.
Le résultat est alors utilisé avec le 3ième élément de la séquence pour rappeler la fonction.
Le nouveau résultat obtenu est alors utilisé avec le 4ième élément de la séquence pour rappeler la fonction.
Et ainsi de suite jusqu'à la fin de la séquence.
L'exemple suivant illustre parfaitement le fonctionnement de la fonction reduce.
>>> def somme( x, y): ... print( '%d + %d = %d' % (x,y,x+y) ) ... return x+y ... >>> >>> reduce( somme, [1,2,3,4,5] ) 1 + 2 = 3 3 + 3 = 6 6 + 4 = 10 10 + 5 = 15 15
Reduce peut également prendre une valeur initiale en troisième argument.
Cela permet de reprendre/compléter une opération reduce avec des nouvelles données.
>>> # poursuivre le calcul avec le dernier résultat obtenu (15) comme >>> # valeur initiale >>> reduce( somme, [6,7,8,9,10], 15 ) 15 + 6 = 21 21 + 7 = 28 28 + 8 = 36 36 + 9 = 45 45 + 10 = 55 55 >>> # la somme des nombres de 1 à 10 fait 55
Cas d'utilisation:
- traitement de flux de donnée.
- Calcul récursif sur série de donnée (ex: calcul de moyenne).
Itération. Permet d'appliquer une fonction de transformation à chacun des éléments d'une structure itérable.
A noter que map peut être utilisé avec plusieurs listes. Dans ce cas, les éléments seront joints (un à un) et passés en paramètres de la fonction de transformation.
La fonction de transformation peut être None, dans ce cas, les éléments sont retournés (joint) tel quel et combinés en Tuple. Si l'une des liste est plus courte le tuple contiendra None pour l'élément manquant.
>>> myList = [1, 13, 22, 4, 6, 17, 88, 65] >>> def mapTest( item ): return item*2 >>> newList = map( mapTest, myList ) >>> newList [2, 26, 44, 8, 12, 34, 176, 130] >>> myList = [1, 13, 22, 4, 6, 17, 88, 65] >>> myList2 = ['A', 'b', 'c', 'd'] >>> def mapTest2( item1, item2 ): # str the items to avoids the error: # TypeError: cannot concatenate 'str' and 'NoneType' objects return str(item1)+'-'+str(item2) >>> newList = map( mapTest2, myList, myList2 ) >>> newList ['1-A', '13-b', '22-c', '4-d', '6-None', '17-None', '88-None', '65-None'] >>> # mapping with None as function >>> # In this case this create TUPLES >>> newList = map( None, myList, myList2 ) >>> newList [(1, 'A'), (13, 'b'), (22, 'c'), (4, 'd'), (6, None), (17, None), (88, None), (65, None)] >>> # mapping strings with None as function >>> str1 = 'elements' >>> str2 = 'langage' >>> newList = map( None, str1, str2 ) >>> newList [('e', 'l'), ('l', 'a'), ('e', 'n'), ('m', 'g'), ('e', 'a'), ('n', 'g'), ('t', 'e'), ('s', None)] >>> # Autre usage des tuples >>> for item1, item2 in map( None, str1, str2 ): print str( item1 ) print ' +-> '+str( item2 ) e +-> l l +-> a e +-> n m +-> g e +-> a n +-> g t +-> e s +-> None
all
Itération. Permet de tester l'homogénéité d'une séquence.
La fonction all retourne true si tous tous les éléments d'une séquence peuvent être évalués comme vrai.
Les éléments évalués peuvent être des références d'objets (assignés=True ou None=False) ou des expressions booléennes.
>>> mySeq1 = [ 1, 2, 'a', None ] >>> mySeq2 = [ 1, 2, 'a', 3 ] >>> mySeq3 = [ 1, 10, 20, 60 ] >>> # Teste si tous les éléments sont assignés >>> all( mySeq1 ) False >>> all( mySeq2 ) True >>> # Test d'homogénéité >>> all( isinstance( el, int ) for el in mySeq1 ) False >>> all( isinstance( el, int ) for el in mySeq2 ) False >>> all( isinstance( el, int ) for el in mySeq3 ) True >>> # Utilisation des [ ] pour construire un élément itérable >>> print [ isinstance( el, int ) for el in mySeq3 ] [True, True, True, True] >>> # Test avec la nouvelle notation >>> print all( [ isinstance( el, int ) for el in mySeq3 ] ) True
any
Itération. Permet de tester facilement le contenu d'une séquence.
La fonction any retourne true si au moins un des éléments de la séquence séquence peut être évalué comme vrai.
Les éléments évalués peuvent être des références d'objets (assignés ou None) ou des expressions booléennes.
>>> mySeq1 = [ 1, 2, 'a', None ] >>> mySeq2 = [ 1, 2, 'a', 3 ] >>> mySeq3 = [ 1, 10, 20, 60 ] >>> print any( el > 10 for el in mySeq1 ) True >>> print any( el > 10 for el in mySeq2 ) True >>> print any( el > 10 for el in mySeq3 ) True >>> print any( [ el > 10 for el in mySeq1 ] ) True >>> print any( [ el > 10 for el in mySeq2 ] ) True >>> print any( [ el > 10 for el in mySeq3 ] ) True >>> print any( [ isinstance( el, str ) for el in mySeq1 ] ) True >>> print any( [ isinstance( el, str ) for el in mySeq2 ] ) True >>> print any( [ isinstance( el, str ) for el in mySeq3 ] ) FalsePetit exemple complémentaire sur le blog amix.dk
lundi 14 décembre 2009
Sql Serveur - Converting une string Hexa en caratère
En Sql Serveur, il n'est pas si simple de convertir une string contenant une valeur hexadécimale en en caractère.
J'ai trouvé la réponse à cette épineuse question sur l'article "T-SQL Convert Hex String to Varbinary" de Peter DeBetta. La fonction HexStrToVarBin de Peter permet ce petit tour de passe-passe.
Exemple:
J'ai trouvé la réponse à cette épineuse question sur l'article "T-SQL Convert Hex String to Varbinary" de Peter DeBetta. La fonction HexStrToVarBin de Peter permet ce petit tour de passe-passe.
Exemple:
-- === CONVERT SIMPLE BYTE ================ DECLARE @strData Varchar(2) -- Some programming extracting a hex digit SET @strData = '4A' print 'Conversion on simple char' print Char( dbo.HexStrToVarBin( '0x'+@StrData ) ) -- === CONVERT SEQUENCE OF BYTES ========== DECLARE @strData2 Varchar(20) -- Some programming extracting a hex digit SET @strData2 = '4A4B4C4D' print 'Conversion to sequence of char' print Cast( dbo.HexStrToVarBin( '0x'+@StrData2 ) as Varchar(10) )
Résultat:
Conversion on simple char J Conversion to sequence of char JKLM
jeudi 10 décembre 2009
Python - Cas pratique 2
Deuxième cas pratique d'utilisation de script Python utilisant XML (libxml), XSL (d'un browser), les itérables et ODBC (pyODBC).
En résumé, ce script Python effectue les opérations suivantes:
Information relative au code source:
Le fichier XML imtermédiaire est fourni avec le code source. Cependant, son contenu a été fortement et volontairement altéré (name scrambling). D'autre part, il ne reste plus d'information sensible sur la ConnectionString dans le code Python.
La transformation XSL du type TzzzDateTime ne sera pas correct car, bien évidemment, il ne s'agit pas du type réel. Bien que le principe de fonctionnement soit correct, le code généré avec cet exemple ne compilera pas.
En résumé, ce script Python effectue les opérations suivantes:
- Connecter une DB MS SqlServeur pour lister le nom de certaines tables et leurs colonnes (en utilisant sysobjects et syscolumns).
- Etablir une structure Python en mémoire avec ces informations.
- Enrichir la structure (avec des informations complémentaires comme les datatypes, type delphi, etc)
- Transformation de la structure en document XML + enregistrement dans un fichier.
- Utilisation d'une XSL pour générer des classes Delphi sur base du contenu XML.
Pour ce faire, ouvrir le fichier XML avec un Browser. Le code Delphi résultant est visible dans Browser. Utiliser de préférence FireFox car IE6 (par exemple) à la mauvaise manie d'ignorer les CR pour un output de type "text".
Information relative au code source:
Le fichier XML imtermédiaire est fourni avec le code source. Cependant, son contenu a été fortement et volontairement altéré (name scrambling). D'autre part, il ne reste plus d'information sensible sur la ConnectionString dans le code Python.
La transformation XSL du type TzzzDateTime ne sera pas correct car, bien évidemment, il ne s'agit pas du type réel. Bien que le principe de fonctionnement soit correct, le code généré avec cet exemple ne compilera pas.
mardi 8 décembre 2009
Nouvelles technologies Google
Voici quelques vidéos relatives aux nouvelles technologies Google (à voir absolument).
Dans les deux premières vidéos ci-dessous, Google exploite l'avantage que peut offrir un appareil photographique embarqué sur les appareils mobiles (GSM).
Recherche sur base d'une image
Après la recherche vocale et sur base de texte écrit, voici la recherche sur base d'une image.
Dans la vidéo ci-jointe, Google va encore plus loin en permettant d'obtenir rapidement des informations à propos d'un objet d'art, d'un livre, d'un code barre, d'un monument connu ou même encore d'un texte photographié.
Google Favorite place
Encore un usage pratique d'une capture d'image (barre code 2D) depuis un appareil mobile.
Résultat en temps réel
Permet de suivre l'actualisation en temps réel d'une recherche sur un sujet précis.
Source: voir cet article de Clubic
Dans les deux premières vidéos ci-dessous, Google exploite l'avantage que peut offrir un appareil photographique embarqué sur les appareils mobiles (GSM).
Recherche sur base d'une image
Après la recherche vocale et sur base de texte écrit, voici la recherche sur base d'une image.
Dans la vidéo ci-jointe, Google va encore plus loin en permettant d'obtenir rapidement des informations à propos d'un objet d'art, d'un livre, d'un code barre, d'un monument connu ou même encore d'un texte photographié.
Google Favorite place
Encore un usage pratique d'une capture d'image (barre code 2D) depuis un appareil mobile.
Résultat en temps réel
Permet de suivre l'actualisation en temps réel d'une recherche sur un sujet précis.
Source: voir cet article de Clubic
Sql Database Space (sp_SDS)
Introduction
Parmi les tâches journalières d'un DBA, il y a la surveillance journalière de la taille des DB.
La capture et le stockage de cette information permettant par ailleurs d'anticiper les futurs besoins et problèmes de stockage.
Cas pratique
Pour les développeurs impliqués dans des processus de migration de données, la surveillance de la taille des DBs (espace libre par fichier physique) peut également s'avérer utile. Il servira, par exemple, à placer judicieusement des opérations SHRINKFILE pour éviter l'engorgement du/des disque(s) en cours de test migration.
En exemple pratique, la migration d'une table de 50 millions de records vers de nouvelles structures peut générer d'assez grosses variations en besoin de stockage. Même avec un recovery model=simple pour limiter le gonflement du transaction log, un delta de plusieurs gigas (15Go dans mon cas) entre deux filegroups est tout à fait possible.
La stored procedure sp_SDS
La stored procedure sp_SDS de Richard Ding est, encore une fois, une des nombreuses perles qu'internet dissimule si facilement.
Compatible Sql Serveur 2000, 2005 et 2008, sp_SDS (Sql Database Space) permet de connaitre exactement l'espace physique occupé par une DB (ou toutes les DB d'un serveur).
Outre la consommation physique, sp_SDS indique également le ratio d'occupation de la DB (son taux de remplissage). Cette dernière information peut s'avérer extrêmement pertinente durant un processus de migration de données.
Cerise sur le gâteau, sp_SDS peut fournir ses statistiques par fichier composant la (ou les) DB(s).
Pour plus d'information:
Parmi les tâches journalières d'un DBA, il y a la surveillance journalière de la taille des DB.
La capture et le stockage de cette information permettant par ailleurs d'anticiper les futurs besoins et problèmes de stockage.
Cas pratique
Pour les développeurs impliqués dans des processus de migration de données, la surveillance de la taille des DBs (espace libre par fichier physique) peut également s'avérer utile. Il servira, par exemple, à placer judicieusement des opérations SHRINKFILE pour éviter l'engorgement du/des disque(s) en cours de test migration.
En exemple pratique, la migration d'une table de 50 millions de records vers de nouvelles structures peut générer d'assez grosses variations en besoin de stockage. Même avec un recovery model=simple pour limiter le gonflement du transaction log, un delta de plusieurs gigas (15Go dans mon cas) entre deux filegroups est tout à fait possible.
La stored procedure sp_SDS
La stored procedure sp_SDS de Richard Ding est, encore une fois, une des nombreuses perles qu'internet dissimule si facilement.
Compatible Sql Serveur 2000, 2005 et 2008, sp_SDS (Sql Database Space) permet de connaitre exactement l'espace physique occupé par une DB (ou toutes les DB d'un serveur).
Outre la consommation physique, sp_SDS indique également le ratio d'occupation de la DB (son taux de remplissage). Cette dernière information peut s'avérer extrêmement pertinente durant un processus de migration de données.
Cerise sur le gâteau, sp_SDS peut fournir ses statistiques par fichier composant la (ou les) DB(s).
Pour plus d'information:
- voir l'article "Check SQL Server database and log file size with this stored procedure" de Richard Ding sur SearchSqlServer.com
- Source de la stored procedure sp_SDS au format doc, ou sa copie miroir en sql.
lundi 7 décembre 2009
Décorateur en Python (solution au typage non stricte)
Introduction - Le typage non strict
Bien que Python supporte très bien le modèle orienté objet, le typage des paramètres (dans l'appel des fonctions) n'est pas du type "strict".
Il est donc possible de passer une chaîne de caractère ou un objet quelconque à une fonction/méthode là ou le développeur a prévu un entier.
Bien de prônant l'utilisation et le renforcement du typage (stricte), je dois reconnaître que l'approche du typage "non stricte" des paramètres et variable en Python permet une plus grande souplesse dans les développements.
C'est quelque-chose qu'il faut tester dans ce langage et ses structures pour en entre-apercevoir la portée. Cette souplesse est certainement l'un des éléments à l'origine de la popularité de Python. Même l'environement .Net s'y est mis en introduisant le mot clé "var".
Cependant, malgré cet avantage le typage non strict des paramètres reste quand même problématique car il prône l'erreur.
Un décorateur et son principe peut être grossièrement décrit avec la métaphore suivante.
C'est un peu comme les décorations de Noel sur un sapin. Pour atteindre les branches d'un sapin décoré, il faut préalablement débrancher les guirlances électriques, passer le barrage des décorations et éviter de casser les boules de verres.
En programmation c'est un peu pareil, pour atteindre la fonction à éxécuter (et l'exécutée), il faudra passer le barrage du décorateur (la fonction décoratrice).
La fonction décoratrive sera exécutée par Pyhton avant l'appel de la fonction décorée.
Vérification stricte des paramètres avec un décorateur
L'un des usages communs des décorateurs est la vérification des paramètres.
dans ce cadre d'utilisation, la fonction décoratrice vérifiera les conditions d'exécution (ou transformera les paramètres). En cas d'erreur, la fonction décoratrice remplira son rôle en retournant une erreur (la boule de verre qui casse :-) )
Vous trouverez plus bas quelques notes pouvant éventuellement facilite cette compréhension.
Notez que la fonction de décoration only_int reçoit en référence la fonction a décorer (func). La fonction à décorée (func) peut être appelée avec son unique argument (ici func(arg) ).
La fonction de décoration only_int retourne une référence vers la fonction de vérification _only_int (_only_int étant une nested/inner function du décorateur).
Pour résumer, le décorateur only_int est une fonction qui met en place une fonction d'interception sur un argument qui dans le cas des décorateur est une référence de fonction.
C'est dans cette technique que s'exprime toute la puissance du typage non-strict dy Python.
Au démarrage du programme (parsing du code source), Python place donc les fonctions d'interception (décorateurs) sur les appels des fonctions décorées.
En gros, en appelant la fonction absmod3 décorée avec only_int:
La fonction only_int (paramètre func=absmod3) installera la fonction de vérification _only_int comme intermédiare aux appels de absmod3. Au run-time, l'interpréteur appelera _only_int qui lui même rapellera la function référencée par func (donc absmod3). Au passage, _only_int vérifiera le paramètre qui sera passé à absmod3.
Bien que Python supporte très bien le modèle orienté objet, le typage des paramètres (dans l'appel des fonctions) n'est pas du type "strict".
Il est donc possible de passer une chaîne de caractère ou un objet quelconque à une fonction/méthode là ou le développeur a prévu un entier.
Bien de prônant l'utilisation et le renforcement du typage (stricte), je dois reconnaître que l'approche du typage "non stricte" des paramètres et variable en Python permet une plus grande souplesse dans les développements.
C'est quelque-chose qu'il faut tester dans ce langage et ses structures pour en entre-apercevoir la portée. Cette souplesse est certainement l'un des éléments à l'origine de la popularité de Python. Même l'environement .Net s'y est mis en introduisant le mot clé "var".
Cependant, malgré cet avantage le typage non strict des paramètres reste quand même problématique car il prône l'erreur.
Solutions
Il existe plusieurs solutions pour éviter ces problèmes de typage.- D'une façon générale, et bien que cela ne soit pas suffisant, une documentation préçise permet déjà au développeur consencieux d'utiliser correctement la fonction.
Au moins, ce dernier n'aura pas à déviner/décoder le type à passer à la fonction. - Utiliser un notation (préfix) identifiant le type de paramètre.
Bien qu'également inssufisant, cette pratique est largement répandue chez les bons développeurs.
C'est ausci que l'on retrouve un s pour string, ex: sVilleName; i pour integer, ex: iPostalCode; f pour float, eg: fSalary; ii pour interface, eg: iiPostalCodeXmlNode; et ainsi de suite. - Vérification systématique des paramètres en tête de fonction (à l'aide de la fonction isinstance qui permet de tester le type du paramètre).
- Finalement, il reste l'utilisation des décorateurs (voir ci-dessous).
Qu'est-ce qu'un décorateur
Un décorateur, est une fonction particulière qui permet de "décorer" une autre fonction. Pour ce faire, Python permet de déclarer une fonction décoratrice et met en place une syntaxe permettant de décorer les fonctions et méthodes avec un ou plusieurs décorateurs (fonctions décoratrices).Un décorateur et son principe peut être grossièrement décrit avec la métaphore suivante.
C'est un peu comme les décorations de Noel sur un sapin. Pour atteindre les branches d'un sapin décoré, il faut préalablement débrancher les guirlances électriques, passer le barrage des décorations et éviter de casser les boules de verres.
En programmation c'est un peu pareil, pour atteindre la fonction à éxécuter (et l'exécutée), il faudra passer le barrage du décorateur (la fonction décoratrice).
La fonction décoratrive sera exécutée par Pyhton avant l'appel de la fonction décorée.
Vérification stricte des paramètres avec un décorateur
L'un des usages communs des décorateurs est la vérification des paramètres.
dans ce cadre d'utilisation, la fonction décoratrice vérifiera les conditions d'exécution (ou transformera les paramètres). En cas d'erreur, la fonction décoratrice remplira son rôle en retournant une erreur (la boule de verre qui casse :-) )
Exemple de mise en place de décorateur
Comprendre le fonctionnement interne d'un décorateur demande un peu de gymnastique intellectuel. Vous trouverez plus bas quelques notes pouvant éventuellement facilite cette compréhension.
# Définition du décorateur # def only_int(func): """decorator pour vérifier que l'argument est seulement un entier""" def _only_int( arg ): if not isinstance( arg, int ): raise TypeError("'%s' doit etre un entier" % str(arg)) return func(arg) return _only_int # definition de la function absmod3 # décorée avec la fonction only_int @only_int def absmod3(a): return abs(a)%3 absmod3( 100 ) # resultat: 1 absmod3( 12.45 ) # produit l'erreur suivante # Traceback (most recent call last): File "", line 1, in absmod3( 12.45 ) File " ", line 6, in _only_int raise TypeError("'%s' doit etre un entier" % str(arg)) TypeError: '12.45' doit etre un entier
Notez que la fonction de décoration only_int reçoit en référence la fonction a décorer (func). La fonction à décorée (func) peut être appelée avec son unique argument (ici func(arg) ).
La fonction de décoration only_int retourne une référence vers la fonction de vérification _only_int (_only_int étant une nested/inner function du décorateur).
Pour résumer, le décorateur only_int est une fonction qui met en place une fonction d'interception sur un argument qui dans le cas des décorateur est une référence de fonction.
C'est dans cette technique que s'exprime toute la puissance du typage non-strict dy Python.
Au démarrage du programme (parsing du code source), Python place donc les fonctions d'interception (décorateurs) sur les appels des fonctions décorées.
En gros, en appelant la fonction absmod3 décorée avec only_int:
La fonction only_int (paramètre func=absmod3) installera la fonction de vérification _only_int comme intermédiare aux appels de absmod3. Au run-time, l'interpréteur appelera _only_int qui lui même rapellera la function référencée par func (donc absmod3). Au passage, _only_int vérifiera le paramètre qui sera passé à absmod3.
dimanche 6 décembre 2009
Quelques How-to pour Python (Regular Expressions, tri, socket)
Petite référence vers l'article "Regular Expression HOWTO" décrivant l'utilisation des régulars expressions sous Python.
Depuis la page "How To" générale, il est également possible d'accéder aux articles suivants:
Depuis la page "How To" générale, il est également possible d'accéder aux articles suivants:
- Curses Programming with Python: An introduction to writing text-mode programs using Python and curses.
- Regular Expression HOWTO: An introduction to using regular expressions and the re module to process text.
- Socket Programming HOWTO, by Gordon McMillan: Sockets are used nearly everywhere, but are often misunderstood. This is a high-level overview of sockets, that doesn't cover all the fine points (there are a lot of them), but will give you enough background to begin using them decently.
- Sorting Mini-HOWTO, by Andrew Dalke: A little tutorial showing a half dozen ways to sort a list with the built-in sort() method.
- Unicode HOWTO: An introduction to Python's features for processing Unicode data.
Structures en Python
Ce qui est un peu déstabilisant avec Python c'est qu'une partie des structures/stéréotypes que l'on identifieraient facilement en C ou Pascal portent des noms/stéréotypes différents en Python.
C'est ainsi qu'une "séquence" Python ressemble a s'y méprendre à un array en Pascal. C'est un peu déstabilisant lorsque l'on vient d'un autre langage.
Je vais donc passer un peu de temps à synthétiser ces structures en vue d'en faire un petit article.
3 décembre 2009:
Premier jet de l'article enfin terminé. Comme pour beaucoup d'autres articles, il faut pouvoir trouver le temps nécessaire à la rédaction...
Si vous êtes déjà quelque peu familiarisé avec Python, jetez néanmoins un coup d'oeil sur la dernière section intitulée "Utilisation des mappings et optimisation".
6 décembre 2009:
La presque totalité des exemples sont disponibles dans le fichier structures.py.
Les séquences
L'une des notions les plus importantes en Python est bien celle des séquences.
Les séquences sont des objets "container"... donc destinés à contenir/maintenir des données ou objets.
Le terme "séquence" est utilisé parce les objets de ce type sont "Itérable" (comprendre que la séquence peut être parcourue de façon "naturelle").
Le contenu de ces objets peut donc être facilement et systématiquement balayé.
Python dispose de plusieurs structures de données séquentielles (tuple, list, bytearray, str, unicode).
Certaines séquences sont dites immuables et les éléments individuels ne peuvent pas être modifiés, c'est le cas des chaines de caractères (str appelé string, unicode), les tuples et les type bytes.
Seul une opération de ré-affectation peut permettre la manipulation du contenu (phénomène identique au type string de la plateforme .Net).
D'un autre coté, les structures séquentielles tel que les lists et les array (bytearray) sont des séquences modifiable. En d'autre terme, il est possible de modifier les éléments la composant de façon individuel sans passer par des opérations de ré-affectation.
La programmation d'éléments/objets séquentiable (et donc itérable) est facile et autorise l'utilisation de syntaxe simple mais néanmoins très puissante.
Un exemple typique de la puissance de l'itération est l'instruction for en Python (équivalent du "foreach" en C#).
Les Tuples
Les tuples sont des séquences non modifiables (immuable pour reprendre le terme
La notation des tuples ressemble fort aux types énumérés du Pascal sans pour autant avoir les même similitudes.
Les tuples permettent de maintenir une séquence de valeurs (de tous types, y compris des tuples eux-mêmes).
Cette structure immuable (dont on ne peut pas modifier indépendamment les valeurs) est principalement utilisée pour maintenir une séquence de "valeurs constantes".
Les tuples se montrent également fort utiles lorsqu'une fonction/méthode doit renvoyer des multiples valeurs. En pascal, on utiliserait un "record", dans ce cas préçis, pour retourner ces valeurs multiples. Python à l'avantage de permettre la définition/création du tuple (et types inclus) à la volée, ce qui offre une grande souplesse.
Il est possible d'accéder les différents éléments d'un tuple par l'intermédaire d'un index (0 to len-1) ou en utilisant les principes d'itération.
Bien qu'un peu déstabilisants dans un premier temps, en autre parce que le tuple semble faire double emploi avec les listes, on constate rapidement que les tuples sont des éléments de programmation efficace et puissant.
Finalement, bien qu'il ne soit pas possible de modifier indépendamment les éléments d'un tuple, il est possible de recomposer un nouveau tuple à partir d'un ancien tuple en effectuant une opération de ré-affectation:
Liens utiles:
Les listes sont des éléments de type "séquence".
Python utilise une notation à l'aide de [ ] pour créer et manipuler les listes. L'instruction list() permet également de créer formellement une liste.
Bien que la notation et l'utilisation des liste soit similaire aux arrays du Pascal, il sont à ne pas a confondre avec les arrays du Pascal!
Les éléments d'une liste sont néanmoins accessibles en utilisant un index (compris entre 0 et len-1).
Il est également possible d'extraire une séquence (sous liste) d'une liste donné.
Voici quelques exemples de manipulation de liste.
Les listes (tout comme les Tuples) sont des éléments itérables.
Il est donc possible décrire un code comme le suivant:
Liens utiles:
Les arrays (séquence)
Le type bytearray est une structure de type séquence destiné a contenir des bytes.
Le type bytes (équivalent de str en Pyhton 2.6) sont immuables.
Les bytearray lui n'est pas immuable et peut donc être modifié. Ce type dispose d'ailleurs d'une grande partie des fonctions dévolues au type str.
Comparé aux autres types de séquences, les arrays (bytearrays) ne présente pas, de prime abord, d'intérêt particulier comme cela pourrait être le cas dans des langages comme C et Pascal.
En Pyhton, les types les plus intéressants restent quand même les list, tuples et mapping (ci-après)
Les types bytes et bytearray présente principalement un intérêt lors d'interfacage avec des API, des OS ou du materiel. Ces types permettent de transposer les notions et les structures de type "string" d'autres langages directement en Python. Le type bytearray est donc utilisé pour facilité l'interopérabilité.
A titre d'exemple, voici quelques références relatives a win32com, ironPython, Socket programming, etc.
Il est par contre important de noter une finesse de convertion entre les types str, bytes, bytearray à partir de Python 3.0. En effet, à partir de cette version, le type str sera unicode.
Plus d'information sont disponible le document "What's new in Python 2.6" à la section "Byte Literals" sur docs.python.org.
Les mappings (dictionnaire)
Bien qu'également itérable, les mappings ne sont pas des séquences à proprement parler.
Le mapping est un dictionnaire permettant d'associer et maintenir des pairs objet + clé (généralement des mots clés/chaines de caractères).
Les différents objets sont accessible via leur clé. Pour maintenir de bonne performance, les mappings utilisent des tables de hashing pour optimiser les temps d'accès/recherches.
L'exemple ci-dessous démontre l'usage général des mappings.
Il est par exemple possible d'obtenir les éléments d'un dictionnaire à l'aide de myDico.items() ou myDico.IterItems(). Un principe similaire s'applique également pour l'obtention séparée des clés ou valeurs.
La fonction items() crée une copie des éléments composant le mapping.
Cela consomme inévitablement de la mémoire. Il faudra l'utiliser avec attention pour évitant de l'appliquer sur des mappings de grande taille. Par ailleurs, le fait même de copier le contenu requière que la copie soit entièrement effectuée avant le retour d'appel de la fonction items().
Finalement, puisqu'il s'agit d'une copie, les modifications faites sur la copie ne sont pas remportées dans le dictionnaire source.
La fonction iteritems() crée un itérateur sur les éléments composant le mapping.
Le retour de fonction iteritem() est immédiat car il n'y a pas d'opération de copie.
Le contenu du dictionnaire ne doit même pas être dénombré/visité pour retourner un itérateur.
Cela permet d'économiser à la fois de la mémoire et les ressources CPU.
La charge CPU d'iteration sera répartie entre les différents appels (à l'itérateur) qui sera utilisé pour balayer le dictionnaire.
A noter que dans ce cas, les éléments du dictionnaire disponible dans l'itérateur ne sont également pas modifiable via les variables d'itération.
En effet, les variables d'itération contiennent une copie de la valeur/clé du dictionnaire et non une référence (ce qui les rendraient modifiable).
C'est ainsi qu'une "séquence" Python ressemble a s'y méprendre à un array en Pascal. C'est un peu déstabilisant lorsque l'on vient d'un autre langage.
Je vais donc passer un peu de temps à synthétiser ces structures en vue d'en faire un petit article.
3 décembre 2009:
Premier jet de l'article enfin terminé. Comme pour beaucoup d'autres articles, il faut pouvoir trouver le temps nécessaire à la rédaction...
Si vous êtes déjà quelque peu familiarisé avec Python, jetez néanmoins un coup d'oeil sur la dernière section intitulée "Utilisation des mappings et optimisation".
6 décembre 2009:
La presque totalité des exemples sont disponibles dans le fichier structures.py.
Les séquences
L'une des notions les plus importantes en Python est bien celle des séquences.
Les séquences sont des objets "container"... donc destinés à contenir/maintenir des données ou objets.
Le terme "séquence" est utilisé parce les objets de ce type sont "Itérable" (comprendre que la séquence peut être parcourue de façon "naturelle").
Le contenu de ces objets peut donc être facilement et systématiquement balayé.
Python dispose de plusieurs structures de données séquentielles (tuple, list, bytearray, str, unicode).
Certaines séquences sont dites immuables et les éléments individuels ne peuvent pas être modifiés, c'est le cas des chaines de caractères (str appelé string, unicode), les tuples et les type bytes.
Seul une opération de ré-affectation peut permettre la manipulation du contenu (phénomène identique au type string de la plateforme .Net).
D'un autre coté, les structures séquentielles tel que les lists et les array (bytearray) sont des séquences modifiable. En d'autre terme, il est possible de modifier les éléments la composant de façon individuel sans passer par des opérations de ré-affectation.
La programmation d'éléments/objets séquentiable (et donc itérable) est facile et autorise l'utilisation de syntaxe simple mais néanmoins très puissante.
Un exemple typique de la puissance de l'itération est l'instruction for en Python (équivalent du "foreach" en C#).
Les Tuples
Les tuples sont des séquences non modifiables (immuable pour reprendre le terme
La notation des tuples ressemble fort aux types énumérés du Pascal sans pour autant avoir les même similitudes.
Les tuples permettent de maintenir une séquence de valeurs (de tous types, y compris des tuples eux-mêmes).
Cette structure immuable (dont on ne peut pas modifier indépendamment les valeurs) est principalement utilisée pour maintenir une séquence de "valeurs constantes".
Les tuples se montrent également fort utiles lorsqu'une fonction/méthode doit renvoyer des multiples valeurs. En pascal, on utiliserait un "record", dans ce cas préçis, pour retourner ces valeurs multiples. Python à l'avantage de permettre la définition/création du tuple (et types inclus) à la volée, ce qui offre une grande souplesse.
Il est possible d'accéder les différents éléments d'un tuple par l'intermédaire d'un index (0 to len-1) ou en utilisant les principes d'itération.
Bien qu'un peu déstabilisants dans un premier temps, en autre parce que le tuple semble faire double emploi avec les listes, on constate rapidement que les tuples sont des éléments de programmation efficace et puissant.
Finalement, bien qu'il ne soit pas possible de modifier indépendamment les éléments d'un tuple, il est possible de recomposer un nouveau tuple à partir d'un ancien tuple en effectuant une opération de ré-affectation:
monTuple = monTuple + ( AjouterCetteValeur )
Notez que la nouvelle valeur à inclure se trouve entre parenthèse (la notation d'un tuple).
En utilisant cette notation, on constate que le nouveau tuple n'est autre que le résultat de la concaténation de deux autres tuples.
# Utilisation de Tuple def testTuple(): print( '--- Tuple testing ------------------------' ) # Déclaration avec valeur multiple myTuple = ( 'Une valeur', 128, None, 4+3 ) # énumeration print( 'Enumeration Tuple' ) for i in myTuple: print( ' %s' % i ) # Test d'inclusion if 128 in myTuple: print( 'Contient la valeur 128' ) # Un tuple est 'non modifiable'. # L'ajout de valeur passe par une operation d'assignation myTuple = myTuple + ('Un autre tuple', 4) # Déclaration d'un tuple vide anotherTuple = () anotherTuple = anotherTuple + ( 1, 5, 7, 'a' ) anotherTuple = anotherTuple + myTuple # L'execution de la ligne suivant produit une erreur try: anotherTuple = anotherTuple + 998 # Operation interdite except TypeError, err: print( 'Ajout de la valeur 998 au tuple produit '+ 'l\'erreur suivante' ) print( ' %s' % err ) # cette ligne sera executée # L'execution de la ligne suivant produit une erreur try: anotherTuple[0] = 'Modifier la valeur' except TypeError, err: print( 'Modifier directement la valeur d\'un element '+ 'd\un tuple produit l\erreur suivante' ) print( ' %s' % err ) # longueur et accès a un simple élément if len( anotherTuple )>0: print( 'longueur de anotherTuple= %s' % len(anotherTuple) ) print( 'Deuxième valeur de anotherTuple= %s' % anotherTuple[1] ) # Compostion d'un tuple complexe complexTuple = ( ['1','5','10'], anotherTuple, ('a','1'), ('b',('un','deux')) ) print( 'contenu de complexTuple' ) print( complexTuple ) print( 'longueur de complexTuple= %s' % len( complexTuple ) ) for i in range( len(complexTuple) ): print( ' élément %s est %s' % (i, complexTuple[i]) )
Liens utiles:
- Article "Python Tuples" sur Tutorials Point
Les listes sont des éléments de type "séquence".
Python utilise une notation à l'aide de [ ] pour créer et manipuler les listes. L'instruction list() permet également de créer formellement une liste.
Bien que la notation et l'utilisation des liste soit similaire aux arrays du Pascal, il sont à ne pas a confondre avec les arrays du Pascal!
Les éléments d'une liste sont néanmoins accessibles en utilisant un index (compris entre 0 et len-1).
Il est également possible d'extraire une séquence (sous liste) d'une liste donné.
Voici quelques exemples de manipulation de liste.
# Crée une liste vide myEmptyList = [] # définition directe myList = [ '1', 123, 'Hello' ] # définition à l'aide de list() et initialisation à l'aide d'une autre liste myList4 = list( [1-2,'World','is','$T0n€'] ) # donnera le résultat [-1, 'World', 'is', '$T0n\x80'] # définition à l'aide de list() et initialization à l'aide d'un Tuple myList3 = list( (1,'helloZ','test') ) # donnera le résultat [1, 'helloZ', 'test'] # définition à l'aide des méthodes de list() myList5 = list() myList5.append( 123 ) myList5.append( 'Zut' ) myList5.append( 'Il y a du monde' ) myList5 # donnera [123, 'Zut', 'Il y a du monde'] # Extraction d'élément par index print( myList5[0] ) # L'utilisation d'un index négatif permet d'accéder # aux éléments depuis la fin de la liste (Python # ajoute la longueur de la liste à l'index) print( myList5[-1] ) # produira 'Il y a du monde' # Extraction d'une séquence myList6 = myList4[1:3] myList6 # produira le résultat ['World', 'is', '$T0n\x80']
Les listes (tout comme les Tuples) sont des éléments itérables.
Il est donc possible décrire un code comme le suivant:
for item in myList5: print( item )ce qui produira le résultat:
123 Zut Il y a du monde
Liens utiles:
- An introduction to Python lists
- Article "Python List" sur Tutorials Point (information sur les lists ainsi que les fonctions et méthodes)
Les arrays (séquence)
Le type bytearray est une structure de type séquence destiné a contenir des bytes.
Le type bytes (équivalent de str en Pyhton 2.6) sont immuables.
Les bytearray lui n'est pas immuable et peut donc être modifié. Ce type dispose d'ailleurs d'une grande partie des fonctions dévolues au type str.
Comparé aux autres types de séquences, les arrays (bytearrays) ne présente pas, de prime abord, d'intérêt particulier comme cela pourrait être le cas dans des langages comme C et Pascal.
En Pyhton, les types les plus intéressants restent quand même les list, tuples et mapping (ci-après)
Les types bytes et bytearray présente principalement un intérêt lors d'interfacage avec des API, des OS ou du materiel. Ces types permettent de transposer les notions et les structures de type "string" d'autres langages directement en Python. Le type bytearray est donc utilisé pour facilité l'interopérabilité.
A titre d'exemple, voici quelques références relatives a win32com, ironPython, Socket programming, etc.
Il est par contre important de noter une finesse de convertion entre les types str, bytes, bytearray à partir de Python 3.0. En effet, à partir de cette version, le type str sera unicode.
Plus d'information sont disponible le document "What's new in Python 2.6" à la section "Byte Literals" sur docs.python.org.
Les mappings (dictionnaire)
Bien qu'également itérable, les mappings ne sont pas des séquences à proprement parler.
Le mapping est un dictionnaire permettant d'associer et maintenir des pairs objet + clé (généralement des mots clés/chaines de caractères).
Les différents objets sont accessible via leur clé. Pour maintenir de bonne performance, les mappings utilisent des tables de hashing pour optimiser les temps d'accès/recherches.
L'exemple ci-dessous démontre l'usage général des mappings.
>>> # Definition d'un dictionnaire (directement) >>> parents = { 'man' : 'dodo', 'woman' : 'fanfan' } >>> parents {'woman': 'fanfan', 'man': 'dodo'} >>> for key, value in parents.items(): print 'the %s is %s' % (key, value) the woman is fanfan the man is dodo >>> # Definition d'un dictionnaire via l'objet dict() >>> # nb: il est également possible d'initialiser le >>> # dictionnaire dans le constructeur >>> kids = dict() >>> kids['kid 1'] = 'didi' >>> kids['kid 2'] = 'jess' >>> kids['kid 3'] = 'ben' >>> kids['kid 4'] = 'lili' >>> kids {'kid 1': 'didi', 'kid 3': 'ben', 'kid 2': 'jess', 'kid 4': 'lili'} >>> familly = dict( parents ) >>> familly.update( kids ) >>> familly {'woman': 'fanfan', 'kid 1': 'didi', 'kid 3': 'ben', 'kid 2': 'jess', 'kid 4': 'lili', 'man': 'dodo'} >>> familly.get( 'kid2', 'NOT AVAILABLE' ) 'NOT AVAILABLE' >>> familly.get( 'kid 2', 'NOT AVAILABLE' ) 'jess' >>> familly.has_key( 'glops' ) False >>> familly.has_key( 'man' ) True >>> familly.iterkeys() <dictionary-keyiterator object at 0x0119A2A0> >>> for item in familly.iterkeys(): print item woman kid 1 kid 3 kid 2 kid 4 man >>> for iterKey, iterValue in familly.iteritems(): print '%s -> %s' % (iterKey, iterValue) woman -> fanfan kid 1 -> didi kid 3 -> ben kid 2 -> jess kid 4 -> lili man -> dodo
Liens utiles
- L'article "Mapping types" de Python Reference Library (sur python.org)
Utilisation des mappings et optimisation
Il faut cependant prendre note d'une notion importante relative à l'optimisation des programmes.Il est par exemple possible d'obtenir les éléments d'un dictionnaire à l'aide de myDico.items() ou myDico.IterItems(). Un principe similaire s'applique également pour l'obtention séparée des clés ou valeurs.
La fonction items() crée une copie des éléments composant le mapping.
Cela consomme inévitablement de la mémoire. Il faudra l'utiliser avec attention pour évitant de l'appliquer sur des mappings de grande taille. Par ailleurs, le fait même de copier le contenu requière que la copie soit entièrement effectuée avant le retour d'appel de la fonction items().
Finalement, puisqu'il s'agit d'une copie, les modifications faites sur la copie ne sont pas remportées dans le dictionnaire source.
La fonction iteritems() crée un itérateur sur les éléments composant le mapping.
Le retour de fonction iteritem() est immédiat car il n'y a pas d'opération de copie.
Le contenu du dictionnaire ne doit même pas être dénombré/visité pour retourner un itérateur.
Cela permet d'économiser à la fois de la mémoire et les ressources CPU.
La charge CPU d'iteration sera répartie entre les différents appels (à l'itérateur) qui sera utilisé pour balayer le dictionnaire.
A noter que dans ce cas, les éléments du dictionnaire disponible dans l'itérateur ne sont également pas modifiable via les variables d'itération.
En effet, les variables d'itération contiennent une copie de la valeur/clé du dictionnaire et non une référence (ce qui les rendraient modifiable).
>>> familly.items() [('woman', 'fanfan'), ('kid 1', 'didi'), ('kid 3', 'ben'), ('kid 2', 'jess'), ('kid 4', 'lili'), ('man', 'dodo')] >>> # Utilisation d'un itérateur >>> familly.iteritems() <dictionary-itemiterator object at 0x0119A3C0> >>> for iterKey, iterValue in familly.iteritems(): if iterKey=='man': iterValue = 'Man will not be replaced (hehe!)' print 'replace attempt' replace attempt >>> familly.items() [('woman', 'fanfan'), ('kid 1', 'didi'), ('kid 3', 'ben'), ('kid 2', 'jess'), ('kid 4', 'lili'), ('man', 'dodo')] >>> # Utilisation d'une copie >>> for iterKey, iterValue in familly.items(): if iterKey=='man': iterValue = 'Man will not be replaced (neither!)' print 'Replace attempt 2' Replace attempt 2 >>> familly.items() [('woman', 'fanfan'), ('kid 1', 'didi'), ('kid 3', 'ben'), ('kid 2', 'jess'), ('kid 4', 'lili'), ('man', 'dodo')]
jeudi 3 décembre 2009
Review d'éditeur UML
Sur le judebert.com, un développeur Java évalue des éditeurs UML open source afin de trouver le meilleur selon "ses critères" pour l'aider dans ses développements.
Voici donc une liste de ses articles (et résumé de l'évaluation):
Voici donc une liste de ses articles (et résumé de l'évaluation):
- Open ModelSphere - pas intuitif
- BOUML - satisfaisant
- Gaphor - à éviter... sauf peut être pour les développeur Python
- Umbrello - pas convaincu
- ArgoUML - très frustrant
mercredi 2 décembre 2009
Open ModelSphere l'outil open source de modélisation UML, DB et Processus
Open ModelSphere est un logiciel de modélisation UML complet mais également de donnée et de processus.
Ecrit en Java, ce logiciel est "cross-platform" et disponible gratuitement.
Diagramme UML
Open ModelSphere permet de créer les diagrammes UML suivants:
Les modèles conceptuels peuvent être convertis en modèles relationnelles (et vice versa).
Comme tous les logiciels de bonne facture, open ModelSphere permet de générer un diagramme directement depuis une DB relationnelle existante. Bien entendu, il est également possible de reporter les modifications effectuées avec le logiciel dans la DB.
Le logiciel dispose également de module expert permettant de valider l'intégrité et la cohérence de l'architecture des DB (fonctionnalité par ailleurs récemment apparu dans Sql Serveur 2008).
Finallement, open ModelSphere peut se supporte de nombreux type de DB. Certaines DB comme DB2, Informix ou Oracle dispose de plug-ins pour inclure leurs concepts spécifiques.
Plus d'informations:
En Juillet 2009, judert.com testait open ModelSphere (lien ici) pour trouver un bon éditeur UML pour ses développements Java.
Le verdit est assez tranché, à savoir:
En effet, open ModelSphere est plus qu'un simple éditeur UML, il couvre d'autres domaines dans lesquels il pourrait offrir une bonne évaluation. Je pense, par exemple, aux diagrammes de données.
Ecrit en Java, ce logiciel est "cross-platform" et disponible gratuitement.
Diagramme UML
Open ModelSphere permet de créer les diagrammes UML suivants:
- Activité
- Classe
- Collaboration
- Composant
- Deploiement
- Package
- Sequence
- Etat-transition
- Use-case
Diagramme de donnée
Open ModelSphere gère à la fois les modèles conceptuels et logiques de données.Les modèles conceptuels peuvent être convertis en modèles relationnelles (et vice versa).
Comme tous les logiciels de bonne facture, open ModelSphere permet de générer un diagramme directement depuis une DB relationnelle existante. Bien entendu, il est également possible de reporter les modifications effectuées avec le logiciel dans la DB.
Le logiciel dispose également de module expert permettant de valider l'intégrité et la cohérence de l'architecture des DB (fonctionnalité par ailleurs récemment apparu dans Sql Serveur 2008).
Finallement, open ModelSphere peut se supporte de nombreux type de DB. Certaines DB comme DB2, Informix ou Oracle dispose de plug-ins pour inclure leurs concepts spécifiques.
Autres diagrammes
Open ModelSphere permet également de modéliser les flots de données, les processus, les workflows (et logiques) de l'entreprise. Il est possible de spécifier des ressources, transactions, échanges de communication, des coûts, etc. Les processus peuvent êtres divisés en sous processus.Plus d'informations:
- Open ModelSphere.org
- Description du produit Open ModelSphere
- Screenshots (via Google)
En Juillet 2009, judert.com testait open ModelSphere (lien ici) pour trouver un bon éditeur UML pour ses développements Java.
Le verdit est assez tranché, à savoir:
" Ce n'est pas intuitif, and je ne sais pas obtenir de support, comment est-il possibe de l'utiliser? Open ModelSphere ne rempli pas mes exigences pour un outil de modélisation UML utile. "Cependant, il faut quelque peu nuancer ces propos.
En effet, open ModelSphere est plus qu'un simple éditeur UML, il couvre d'autres domaines dans lesquels il pourrait offrir une bonne évaluation. Je pense, par exemple, aux diagrammes de données.
mardi 1 décembre 2009
sp_force_shrink_log pour Sql Serveur 2005
Déja relaté dans l'article "Utilitaires pour SQL Server 7", la stored procedure sp_force_shrink_log de Andrew Zanevsky (AZ databases) permet de tronquer le transaction log de façon nettement plus efficace que DBCC SHRINKFILE.
En effet, DBCC SHRINKFILE ne fait que tronquer la partie inactive en fin du fichier de transaction.
Si le transaction log fait 25Go et que "le pointeur de transaction" se trouve actuellement en fin de fichier (ex: à l'offset 24.7 Go, ce qui est assez fréquent); dans ce cas, DBCC SHRINKFILE ne libèrera que 300Mo.
Il faudra attendre un roll-over vers le début du fichier de transaction pour avoir un résultat probant.
Lorsque que le transaction log fait 25 Go et qu'il étouffe littéralement le système de fichier, il n'est pas forcement possible d'attendre patiemment l'opération de Roll-over sur le transaction log. Libérer de l'espace disque peut être impératif pour la bonne conduite d'autres opérations sql.
C'est là qu'intervient précisément sp_force_shrink_log. Cette store procédure va déplacer le pointeur de transaction dans le transaction log en simulant des activités sql sur une table temporaire. Une fois le roll-over effectué (ce qui arrivera tôt ou tard), le transaction log sera efficacement tronqué et la stored procedure pourra interrompre son traitement.
Malheureusement, la store procedure d'origine prévue pour SQL 7 ne fonctionne pas correctement sur SQL Serveur 2005. En effet, le résultat retourné par DBCC LogInfo (utilisé par sp_force_Shrink_log) a été modifié depuis SQL 7.
Voici donc une petite mise à jour (faite par mes soins) du script sp_force_shrink_log pour SQL Serveur 2005 (sp_force_shrink_log_2005.sql).
ressources:
En effet, DBCC SHRINKFILE ne fait que tronquer la partie inactive en fin du fichier de transaction.
Si le transaction log fait 25Go et que "le pointeur de transaction" se trouve actuellement en fin de fichier (ex: à l'offset 24.7 Go, ce qui est assez fréquent); dans ce cas, DBCC SHRINKFILE ne libèrera que 300Mo.
Il faudra attendre un roll-over vers le début du fichier de transaction pour avoir un résultat probant.
Lorsque que le transaction log fait 25 Go et qu'il étouffe littéralement le système de fichier, il n'est pas forcement possible d'attendre patiemment l'opération de Roll-over sur le transaction log. Libérer de l'espace disque peut être impératif pour la bonne conduite d'autres opérations sql.
C'est là qu'intervient précisément sp_force_shrink_log. Cette store procédure va déplacer le pointeur de transaction dans le transaction log en simulant des activités sql sur une table temporaire. Une fois le roll-over effectué (ce qui arrivera tôt ou tard), le transaction log sera efficacement tronqué et la stored procedure pourra interrompre son traitement.
Malheureusement, la store procedure d'origine prévue pour SQL 7 ne fonctionne pas correctement sur SQL Serveur 2005. En effet, le résultat retourné par DBCC LogInfo (utilisé par sp_force_Shrink_log) a été modifié depuis SQL 7.
Voici donc une petite mise à jour (faite par mes soins) du script sp_force_shrink_log pour SQL Serveur 2005 (sp_force_shrink_log_2005.sql).
use master go if object_id( 'sp_force_shrink_log' ) is not null drop proc sp_force_shrink_log go create proc sp_force_shrink_log /* ************************************************************* Name: sp_force_shrink_log Description: Shrink transaction log of the current database in SQL Server 2005. Switch context to proper db to execute. Usage: exec sp_force_shrink_log <target_percent>, <target MB>, <iterations>, <backup options> exec pubs..sp_force_shrink_log Author: Andrew Zanevsky, AZ Databases, Inc., 12/25/1999, v5 - 08/18/2000 zanevsky@azdatabases.com Note: D Meurisse, *no_company_info* , 12/01/2009, v5.1 - 12/01/2009 Updated this wonderfull script to make it running on SQL 2005. Updated the description and change version to v5.1 Input Params: ------------- @target_percent tinyint. default = 0. Target percentage of remaining shrinkable space. Defaults to max possible. @target_size_MB int. default = 10. Target size of final log in MB. @max_iterations int. default = 1000. Number of loops (max) to run proc through. @backup_log_opt nvarchar(1000). default = 'with truncate_only'. Backup options. Output Params: -------------- Return: Results: --------- Locals: -------- @err Holds error value Modifications: -------------- V5.1 - Meurisse D. - 1 dec 2009 - small changes to make it working with Sql 2005 ************************************************************* */ @target_percent tinyint = 0, @target_size_MB int = 10, @max_iterations int = 1000, @backup_log_opt nvarchar(1000) = 'with truncate_only' as set nocount on declare @db sysname, @last_row int, @log_size decimal(15,2), @unused1 decimal(15,2), @unused decimal(15,2), @shrinkable decimal(15,2), @iteration int, @file_max int, @file int, @fileid varchar(5) select @db = db_name(), @iteration = 0 /* drop table #LogInfo drop table #LogFiles */ create table #loginfo ( id int identity, FileId int, FileSize numeric(22,0), StartOffset numeric(22,0), FSeqNo int, Status int, Parity smallint, /* CreateTime datetime */ CreateLSN varchar(50) ) create unique clustered index loginfo_FSeqNo on #loginfo ( FSeqNo, StartOffset ) create table #logfiles ( id int identity(1,1), fileid varchar(5) not null ) insert #logfiles ( fileid ) select convert( varchar, fileid ) from sysfiles where status & 0x40 = 0x40 select @file_max = @@rowcount if object_id( 'table_to_force_shrink_log' ) is null exec( 'create table table_to_force_shrink_log ( x nchar(3000) not null )' ) insert #loginfo ( FileId, FileSize, StartOffset, FSeqNo, Status, Parity, /*CreateTime*/ CreateLSN ) exec ( 'dbcc loginfo' ) select @last_row = @@rowcount select @log_size = sum( FileSize ) / 1048576.00, @unused = sum( case when Status = 0 then FileSize else 0 end ) / 1048576.00, @shrinkable = sum( case when id < @last_row - 1 and Status = 0 then FileSize else 0 end ) / 1048576.00 from #loginfo select @unused1 = @unused -- save for later select 'iteration' = @iteration, 'log size, MB' = @log_size, 'unused log, MB' = @unused, 'shrinkable log, MB' = @shrinkable, 'shrinkable %' = convert( decimal(6,2), @shrinkable * 100 / @log_size ) print 'xx.10' while @shrinkable * 100 / @log_size > @target_percent and @shrinkable > @target_size_MB and @iteration < @max_iterations begin select @iteration = @iteration + 1 -- this is just a precaution exec( 'insert table_to_force_shrink_log select name from sysobjects delete table_to_force_shrink_log') select @file = 0 while @file < @file_max begin select @file = @file + 1 select @fileid = fileid from #logfiles where id = @file exec( 'dbcc shrinkfile( ' + @fileid + ' )' ) end exec( 'backup log [' + @db + '] ' + @backup_log_opt ) truncate table #loginfo insert #loginfo ( FileId, FileSize, StartOffset, FSeqNo, Status, Parity, /* CreateTime */ CreateLSN ) exec ( 'dbcc loginfo' ) select @last_row = @@rowcount select @log_size = sum( FileSize ) / 1048576.00, @unused = sum( case when Status = 0 then FileSize else 0 end ) / 1048576.00, @shrinkable = sum( case when id < @last_row - 1 and Status = 0 then FileSize else 0 end ) / 1048576.00 from #loginfo select 'iteration' = @iteration, 'log size, MB' = @log_size, 'unused log, MB' = @unused, 'shrinkable log, MB' = @shrinkable, 'shrinkable %' = convert( decimal(6,2), @shrinkable * 100 / @log_size ) end if @unused1 < @unused select 'After ' + convert( varchar, @iteration ) + ' iterations the unused portion of the log has grown from ' + convert( varchar, @unused1 ) + ' MB to ' + convert( varchar, @unused ) + ' MB.' union all select 'Since the remaining unused portion is larger than 10 MB,' where @unused > 10 union all select 'you may try running this procedure again with a higher number of iterations.' where @unused > 10 union all select 'Sometimes the log would not shrink to a size smaller than several Megabytes.' where @unused <= 10 else select 'It took ' + convert( varchar, @iteration ) + ' iterations to shrink the unused portion of the log from ' + convert( varchar, @unused1 ) + ' MB to ' + convert( varchar, @unused ) + ' MB' exec( 'drop table table_to_force_shrink_log' ) go if object_id( 'sp_force_shrink_log') Is Null select 'sp_force_shrink_log Not Created' else select 'sp_force_shrink_log Created' go
ressources:
- Voir cet article traitant de la version Sql 7 de la stored procedure sp_force_shrink_log (sur SQL Server Central).
- Voir l'article "Utilitaires pour SQL Server 7" sur ce blog.
- Voir l'article "Réduire la taille de TempDB" sur ce blog (pour un usage efficace de DBCC SHRINKFILE)
Inscription à :
Articles (Atom)