<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Nap&#039;s mini world &#187; Programmation</title>
	<atom:link href="http://www.gabes.fr/jean/category/programmation/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.gabes.fr/jean</link>
	<description>Être admin, ça a parfois des airs de /dev/random...</description>
	<lastBuildDate>Mon, 12 Jul 2010 08:30:01 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>Shinken : example de Hack rapide du code</title>
		<link>http://www.gabes.fr/jean/2010/05/05/shinken-example-de-hack-rapide-du-code/</link>
		<comments>http://www.gabes.fr/jean/2010/05/05/shinken-example-de-hack-rapide-du-code/#comments</comments>
		<pubDate>Wed, 05 May 2010 14:36:53 +0000</pubDate>
		<dc:creator>Nap</dc:creator>
				<category><![CDATA[Programmation]]></category>
		<category><![CDATA[Shinken]]></category>
		<category><![CDATA[Patch]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Supervision]]></category>

		<guid isPermaLink="false">http://www.gabes.fr/jean/?p=561</guid>
		<description><![CDATA[Un exemple de hack rapide
Dans un précédent post, j&#8217;ai déjà parlé des méthodes de développement que j&#8217;ai utilisé dans Shinken. Tout ceci a pour but de faciliter le développement par la suite, comme le rajout facile d&#8217;une propriété sans avoir à se soucier des héritages, distributions sur les différents éléments de l&#8217;architecture, etc etc.
Nous allons [...]]]></description>
			<content:encoded><![CDATA[<h2>Un exemple de hack rapide</h2>
<p>Dans un précédent post, j&#8217;ai déjà parlé des méthodes de développement que j&#8217;ai utilisé dans Shinken. Tout ceci a pour but de faciliter le développement par la suite, comme le rajout facile d&#8217;une propriété sans avoir à se soucier des héritages, distributions sur les différents éléments de l&#8217;architecture, etc etc.</p>
<p>Nous allons en voir un exemple avec un cas simple : le rajout d&#8217;un paramètre pour l&#8217;historique du <em>flapping</em> dans Shinken. En effet, Nagios et Shinken sont capables de détecter un élément qui fait le &#8220;yoyo&#8221; entre deux états. Plutôt que de spammer les users avec des notifications UP/DOWN/UP/DOWN, les schedulers sont assez malin (entendez utilisent un bête algorithme) pour s&#8217;apercevoir que l&#8217;état à changé X% de fois au cours des N derniers tests. La valeur X était déjà paramétrable pour les hôtes et les services, mais celle de N était hardcodée à 20 états.</p>
<p>Le problème c&#8217;est que 20 états ce n&#8217;est pas assez pour détecter un yoyo sur toute la nuit. Il arrive donc souvent des cas où l&#8217;on est averti pour rien, juste car on ne peux pas augmenter cette valeur. C&#8217;est dommage  <img src='http://www.gabes.fr/jean/wp-includes/images/smilies/icon_cry.gif' alt=':cry:' class='wp-smiley' /> </p>
<p>Et bien plus maintenant  <img src='http://www.gabes.fr/jean/wp-includes/images/smilies/icon_mrgreen.gif' alt=':mrgreen:' class='wp-smiley' />  !</p>
<p>Je l&#8217;ai rajouté dans Shinken en quelques lignes qui vont vous monter à quel point c&#8217;est simple d&#8217;aller hacker dans ce code, 5 lignes seulement dans notre cas  <img src='http://www.gabes.fr/jean/wp-includes/images/smilies/icon_biggrin.gif' alt=':-D' class='wp-smiley' /> </p>
<h2>La modification</h2>
<p>Tout se joue dans deux fichiers sources :</p>
<ul>
<li><strong>config.py</strong> : qui gère les paramètres de configurations globaux</li>
<li><strong>schedulingitem.py</strong> : qui gère les algorithmes d&#8217;ordonnancement, des demandes de checks et autres.</li>
</ul>
<p>Dans le premier (<em>config.py</em>) on remarque un tableau nommé <em>properties </em>vers le début du fichier avec toutes les propriétés possibles pour le fichier principal (nagios.cfg). Qu&#8217;à cela ne tienne, on va rajouter notre nouvelle propriété :</p>
<p class="wp-caption" style="text-align: left;">&#8216;flap_history&#8217; : {&#8217;required&#8217;:False, &#8216;default&#8217;:'20&#8242;, &#8216;pythonize&#8217;: to_int, &#8216;class_inherit&#8217; : [(Host, None), (Service, None)]},</p>
<p>On rajoute donc le paramètre <em>flap_history</em>, qui n&#8217;est pas obligatoire (required=False), vaut par défaut 20, se transforme en objet <em>int </em>depuis la lecture de la chaîne de caractère dans le fichier, et va être présentée aux classes <em>Host </em>et <em>Service </em>avec ce même nom de <em>flap_history</em> (rôle de None, expliqué un peu plus haut dans le code, si vous mettez un nouveau nom, c&#8217;est lui qui sera utilisé pour cette classe).</p>
<p>Et voila, c&#8217;est tout pour la configuration ! Et oui, rien de plus. L&#8217;Arbiter va lire la configuration, transformer en entier la valeur, mettre 20 si elle est absente et va la fournir aux configurations envoyées aux schedulers automatiquement ! Là, ne pas hacker un tel code, c&#8217;est plus que de la fainéantise  <img src='http://www.gabes.fr/jean/wp-includes/images/smilies/icon_lol.gif' alt=':lol:' class='wp-smiley' /> </p>
<p>On a réglé le problème de la configuration, maintenant on va utiliser notre nouvelle propriété. Ceci se passe dans deux fonctions du fichier <em>schedulingitem.py</em> : <em>add_flapping_change</em> et <em>update_flapping</em>. La première rajoute le changement d&#8217;état sur la pile de 20 éléments et s&#8217;assure que la pile fait toujours au plus 20 éléments. La seconde fait le calcul de <em>pourcentage de changement</em> à proprement parlé.</p>
<p>Les <em>schedulingitems </em>sont les hosts/services (une classe commune pour factoriser le code), et l&#8217;objet est nommé <strong>self </strong>en Python. On a dit que la propriété a été envoyée sur les classes <em>Host </em>et <em>Service </em>car c&#8217;est un paramètre global à tous les hôtes et services, pas la peine de le multiplier par le nombre d&#8217;hôtes et services. En Python, pour accéder à sa classe (qui est un objet comme un autre), il suffit de faire :</p>
<p class="wp-caption" style="text-align: left;">self.__class__</p>
<p>Donc là pour obtenir notre valeur, il suffit de faire :</p>
<p class="wp-caption" style="text-align: left;">flap_history = self.__class__.flap_history</p>
<p>On remplace les trois occurrences de 20 qui trainent dans le code par <em>flap_history</em> et c&#8217;est réglé, on peut tester/commiter  <img src='http://www.gabes.fr/jean/wp-includes/images/smilies/icon_cool.gif' alt='8-)' class='wp-smiley' />  :</p>
<p class="wp-caption" style="text-align: left;">if len(self.flapping_changes) &gt; flap_history:</p>
<p class="alignleft" style="text-align: left;">
<p class="wp-caption" style="text-align: left;">r += i*(1.2-0.8)/flap_history + 0.8</p>
<p class="wp-caption" style="text-align: left;">r = r / flap_history</p>
<h2>Au final</h2>
<p>Nous avons vu la définition et l&#8217;utilisation d&#8217;un paramètre global dans Shinken. C&#8217;est très simple, et il ne faut pas se priver  <img src='http://www.gabes.fr/jean/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  Nous verrons une autre fois le rajout d&#8217;un paramétrage dans un service ou un hôte, c&#8217;est encore plus simple qu&#8217;ici car il n&#8217;y a pas besoin de passer par l&#8217;accrochage dans les classes <em>Host </em>et <em>Service</em>. Mais ce sera pour une prochaine fois, j&#8217;ai un git push à faire.</p>
<p>Si vous souhaitez hacker vous aussi, n&#8217;hésitez pas :</p>
<pre style="text-align: left;"><code class="wp-caption">git clone git://shinken.git.sourceforge.net/gitroot/shinken/shinken
</code></pre>
<p>J&#8217;accepte volontiers les patchs <img src='http://www.gabes.fr/jean/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Juste pour info, dans le code de Nagios, si on voulait faire la même chose, il faudrait changer la macro <strong>MAX_STATE_HISTORY_ENTRIES</strong> en simple variable :</p>
<p class="wp-caption" style="text-align: left;">grep -r MAX_STATE_HISTORY_ENTRIES * | wc -l<br />
30</p>
<p>30 lignes au minimum juste pour la partie traitement! Je n&#8217;ose même pas regarder combien de lignes ceci va coûter pour la configuration, mais bien plus d&#8217;une, ça c&#8217;est sûr&#8230;  <img src='http://www.gabes.fr/jean/wp-includes/images/smilies/icon_confused.gif' alt=':-?' class='wp-smiley' /> </p>
<p>Notez bien que je ne dis pas ça pour me moquer des développeurs de Nagios, comme quoi le code est imbitable non, car je n&#8217;aurais sûrement pas fait mieux en C.  C&#8217;est juste pour illustrer que parfois, utiliser des techniques de développements avancées (le <em>développement dynamique </em>qui a un peu irrité lors de l&#8217;annonce de Shinken sur la mailing list), ça ne fait pas de mal à l&#8217;efficacité&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gabes.fr/jean/2010/05/05/shinken-example-de-hack-rapide-du-code/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Déduplication : bloc fixe VS bloc variable</title>
		<link>http://www.gabes.fr/jean/2010/03/14/deduplication-bloc-fixe-vs-block-variable/</link>
		<comments>http://www.gabes.fr/jean/2010/03/14/deduplication-bloc-fixe-vs-block-variable/#comments</comments>
		<pubDate>Sun, 14 Mar 2010 13:43:37 +0000</pubDate>
		<dc:creator>Nap</dc:creator>
				<category><![CDATA[Programmation]]></category>
		<category><![CDATA[Déduplication]]></category>
		<category><![CDATA[Planet-Libre]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.gabes.fr/jean/?p=486</guid>
		<description><![CDATA[Intérêt de la dé-duplication
J&#8217;ai testé il y a quelques temps le filesystem lessfs (site officiel du projet). C&#8217;est un filesystem très simple à mettre en place, de type Fuse (donc en user space) qui permet de monter un espace de dé-duplication à la volée.  Cette fonctionnalité permet de gagner une place considérable lorsque l&#8217;on a [...]]]></description>
			<content:encoded><![CDATA[<h2>Intérêt de la dé-duplication</h2>
<p>J&#8217;ai testé il y a quelques temps le filesystem lessfs (<a href="http://www.lessfs.com/wordpress/">site officiel du projet</a>). C&#8217;est un filesystem très simple à mettre en place, de type Fuse (donc en user space) qui permet de monter un espace de dé-duplication à la volée.  Cette fonctionnalité permet de gagner une place considérable lorsque l&#8217;on a des données qui se ressemble fortement.</p>
<p>Elle est complémentaire de la compression. Là où vous aller gagner sur un fichier avec la compression, si vous en avez deux, vous aller stocker deux fois la taille compressée. Avec une passe de dé-duplication avant, vous n&#8217;aurez qu&#8217;une fois chaque bloc, puis vous pouvez compresser ce qui reste.</p>
<h2>Deux méthodes : bloc de taille fixe ou variable</h2>
<h3>Taille fixe</h3>
<p>Les blocs justement. Dans lessfs, ce sont des blocs de taille fixe. Donc on applique un algorithme très simple :</p>
<ul>
<li>on coupe la donnée en bloc de NKo (prenons 4Ko)</li>
<li>on fait un hash de chaque bloc</li>
<li>si on a déjà un hash, on change le bloc par un simple pointeur vers le bloc déjà sauvegardé</li>
<li>sinon on sauvegarde le bloc et son hash</li>
</ul>
<p>Simple. Efficace? Pas si sûr. Bien entendu, si vous faites une copie d&#8217;un fichier, celle-ci ne va quasiment rien vous coûter. Mais faire des copies intactes de vos fichiers arrive parfois avec des sauvegardes, et encore&#8230;</p>
<h3>Taille variable</h3>
<p>Si l&#8217;on veut être plus efficace, il faut faire une recherche dans les données d&#8217;un bloc déjà vu. Mais là où avant on cherchait avec un début de bloc tous les 4Ko, là on cherche pour tous les octets. En effet, si vos blocs ne sont pas parfaitement alignés, vous ne reconnaîtrez pas votre bloc, car il a pris un simple offset de quelques octets!</p>
<p>Bien sûr, ce genre de recherche est bien plus couteux en terme de CPU, 4K calculs fois plus. (En fait u peu moins, dès que vous raccrochez un wagon de blocs déjà connu, un seul calcul suffit).</p>
<h2>Exemple de gain</h2>
<p>Un exemple?</p>
<p>J&#8217;ai codé rapidement un petit script en Python qui réalise ces deux types de dé-duplications :</p>
<ul>
<li>recherche des mêmes blocs de 4Ko avec recherche par fenêtre glissante</li>
<li>recherche brut de frondrie, bloc de 4k</li>
</ul>
<p>Voici les résultats sur un répertoire plein de fichiers de type office and co:</p>
<p class="wp-caption" style="text-align: left;">****** Stats Varible: Deplicated 342756761/465877423 = 73.00% Dedup+compress 426510002 =91.00%<br />
****** Stats Fix: Deplicated 59596755/465877423 = 12.00% Dedup+compress 68349038 =14.00%</p>
<p>On a donc 73% de gain avec des tailles de blocs variables, 91% si on les compresse par dessus. La méthode fixe bourrine n&#8217;arrive elle qu&#8217;à un faible 12%.</p>
<p>Bon bah il faut demander à lessfs d&#8217;appliquer cet algo? Pas si simple, de un c&#8217;est ultra consommateur en CPU, donc il faut le faire en post-process, pas à la volée. Et surtout l&#8217;algo utilisé semble avoir été breveté par EMC&#8230; Et après ça qu&#8217;on vienne encore me sortir que les brevets sont fait pour protéger l&#8217;innovation&#8230;. l&#8217;investissement oui, l&#8217;innovation non&#8230;</p>
<p>Pour ceux qui ont la chance de ne pas habiter dans ce merveilleux pays des brevets logiciels, vous pouvez tester le script<a href="http://www.gabes.fr/pub/dedup.py"> là</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gabes.fr/jean/2010/03/14/deduplication-bloc-fixe-vs-block-variable/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Partie à trois : Python, __slots__ et metaclass</title>
		<link>http://www.gabes.fr/jean/2010/02/15/partie-a-trois-python-__slots__-et-metaclass/</link>
		<comments>http://www.gabes.fr/jean/2010/02/15/partie-a-trois-python-__slots__-et-metaclass/#comments</comments>
		<pubDate>Mon, 15 Feb 2010 13:08:33 +0000</pubDate>
		<dc:creator>Nap</dc:creator>
				<category><![CDATA[Programmation]]></category>
		<category><![CDATA[Développement]]></category>
		<category><![CDATA[metaclass]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[slots]]></category>
		<category><![CDATA[__slots__]]></category>

		<guid isPermaLink="false">http://www.gabes.fr/jean/?p=453</guid>
		<description><![CDATA[Les langages dynamiques sont pratiques pour se frotter facilement à de nouveaux paradigmes de programmations. Aucune technique n&#8217;étant parfaite, l&#8217;aspect dynamique se paye.
Le prix à payer pour les langages dynamiques
Bien souvent on pense au coût CPU pour ces langages, mais cette ressource n&#8217;est pas la seule à prendre cher. Là où un accès à une [...]]]></description>
			<content:encoded><![CDATA[<p>Les langages dynamiques sont pratiques pour se frotter facilement à de nouveaux paradigmes de programmations. Aucune technique n&#8217;étant parfaite, l&#8217;aspect dynamique se paye.</p>
<h2>Le prix à payer pour les langages dynamiques</h2>
<p>Bien souvent on pense au coût CPU pour ces langages, mais cette ressource n&#8217;est pas la seule à prendre cher. Là où un accès à une structure est en 0(1) en C ou C++, il peut être plus élevé dans des langages où les propriétés des objets ne sont pas identiques entre les instances. Il en est de même pour la RAM : les objets pouvant avoir de nouvelles propriétés à chaud, leur accès se fait en vérifiant le dictionnaire <em>__dict__</em> des objets. Le dictionnaire est fort simple:</p>
<p class="wp-caption" style="text-align: left;">class Test:<br />
&nbsp;&nbsp;&nbsp;def __init__(self, x, y):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.x = x<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.y = y<br />
point = Test(1, 2)<br />
print &#8216;Initialement&#8217;, point.__dict__<br />
point.z = 3<br />
print &#8216;Apres&#8217;, point.__dict__</p>
<p style="text-align: left;">Donne :</p>
<p class="wp-caption" style="text-align: left;">Initialement {&#8217;y': 2, &#8216;x&#8217;: 1}<br />
Apres {&#8217;y': 2, &#8216;x&#8217;: 1, &#8216;z&#8217;: 3}</p>
<p style="text-align: left;">C&#8217;est sympa, c&#8217;est dynamique. Mais ceci a un coût en Mémoire : ici nous avons un seul objet, mais si nous avons 1000 points, chacun aura son propre __dict__ indépendant, et surtout les chaînes &#8216;x&#8217;, &#8216;y&#8217; et &#8216;z&#8217; seront dupliquées dans chaque instance. Imaginons que nous avons 1000000 de points à conserver, la consommation de RAM va être de 176mo sur notre exemple (Python 2.6.4). Si nous prenons des classes avec des noms de propriétés plus grandes que &#8216;x&#8217;, on peut atteindre des sommets en terme de consommation de RAM pour finalement pas grand chose.</p>
<p>Le module guppy (disponible sur pypi de mémoire) peut être très pratique pour observer qui consomme de la RAM dans notre application. Son utilisation est fort simple :</p>
<p class="wp-caption" style="text-align: left;">from guppy import hpy<br />
hp=hpy()<br />
print hp.heap()</p>
<p style="text-align: left;">Sa sortie est (relativement) éloquente :</p>
<p class="wp-caption" style="text-align: left;">Partition of a set of 2024657 objects. Total size = 173885852 bytes.<br />
Index  Count   %     Size   % Cumulative  % Kind (class / dict of class)<br />
0 999999  49 135999864  78 135999864  78 dict of __main__.Test<br />
1 999999  49 31999968  18 167999832  97 __main__.Test<br />
2    127   0  4073248   2 172073080  99 list<br />
3  10686   1   744928   0 172818008  99 str<br />
4   5540   0   203368   0 173021376 100 tuple<br />
5    347   0   115160   0 173136536 100 dict (no owner)<br />
6   1539   0   104652   0 173241188 100 types.CodeType<br />
7     64   0   100480   0 173341668 100 dict of module<br />
8    175   0    94840   0 173436508 100 dict of type<br />
9    194   0    86040   0 173522548 100 type</p>
<p style="text-align: left;">78% de la consommation mémoire est due aux<em> __dict__</em> de nos points, les valeurs de ces instances consommant quant à elles 18%.</p>
<h2>__slots__ : c&#8217;est les soldes pour Python</h2>
<p>Lorsque l&#8217;on sait à l&#8217;avance quelles vont être les possibilités des noms de propriétés de nos instances, il peut être pratique de recourir à l&#8217;utilisation des <em>__slots__</em>. C&#8217;est un tuple dans la classe où les noms des propriétés vont être mises en commun pour toutes les instances de la classe. Attention, son utilisation est fort simple, mais elle limite certaines possibilités de Python par la suite, comme certains problèmes avec tout ce qui touche la sérialisation d&#8217;objet par exemple.</p>
<p>Si vous souhaitez l&#8217;utiliser, c&#8217;est fort simple, il suffit de rajouter le tuple à la classe si elle hérite d&#8217;<em>object</em> :</p>
<p class="wp-caption" style="text-align: left;">class Test(object):<br />
&nbsp;&nbsp;&nbsp;__slots__ = (&#8217;x', &#8216;y&#8217;, &#8216;z&#8217;)<br />
&nbsp;&nbsp;&nbsp;def __init__(self, x, y):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.x = x<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.y = y</p>
<p style="text-align: left;">Si simple? Non en fait. le <em>__slots__</em> va remplacer <em>__dict__</em> qui va tout simplement disparaitre! Notre code va lamentablement échouer avec:</p>
<p class="wp-caption" style="text-align: left;">Initialement<br />
Traceback (most recent call last):<br />
File &#8220;test_slot.py&#8221;, line 10, in &lt;module&gt;<br />
print &#8216;Initialement&#8217;, point.__dict__<br />
AttributeError: &#8216;Test&#8217; object has no attribute &#8216;__dict__&#8217;</p>
<p style="text-align: left;">Pour contourner cela, il suffit de rajouter __dict__ au slots:</p>
<p class="wp-caption" style="text-align: left;">class Test(object):<br />
&nbsp;&nbsp;&nbsp;__slots__ = (&#8217;__dict__&#8217;, &#8216;x&#8217;, &#8216;y&#8217;, &#8216;z&#8217;)<br />
&nbsp;&nbsp;&nbsp;def __init__(self, x, y):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.x = x<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.y = y</p>
<p style="text-align: left;">On relance, la consommation passe à 47Mo. (Les gains sont encore plus importants avec des chaînes de plus d&#8217;un caractère <img src='http://www.gabes.fr/jean/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ). Pour Shinken par exemple, avec 100000 services, j&#8217;étais à plus de 2Go de RAM consommée, avec les slots, je suis tombé à moins 50Mo environs&#8230;</p>
<h2>Metaclass : une classe pour en modifier d&#8217;autres</h2>
<p>En Python, on a déjà vu que les classes sont des objets comme les autres. Qui dit objet dit instanciation. Lors de cette instanciation, il peut être pratique de changer des choses à la volée. C&#8217;est justement le rôle des <em>metaclass</em>. C&#8217;est une classe qui va contrôler la création d&#8217;une autre. Elles peuvent être utilisées pour par exemple tracer automatiquement tous les appels de méthode d&#8217;une classe. Pour un tel exemple, voir sur <a href="http://www.afpy.org/Members/kerflyn/metaclass">http://www.afpy.org/Members/kerflyn/metaclass</a> qui présente très bien cela.</p>
<h2>On mixe le tout</h2>
<p>Vous allez me dire: bon c&#8217;est bien les <em>metaclass</em>, mais c&#8217;est quoi le rapport avec les <em>__slots__</em>? Et bien c&#8217;est pratique lorsque l&#8217;on a beaucoup de propriétés dans une classe, comme par exemple Service ou Host de Shinken. Jusqu&#8217;à maintenant, lorsque je rajoutait une nouvelle propriété à ces classes, je rajoutais une ligne dans le tableau <em>properties</em> ou <em>running_properties</em>, mais je devais penser à rajouter ce même paramètre dans le tuple  <em>__slots__</em> de la classe. Autant dire qu&#8217;une fois sur deux, j&#8217;oubliais. De plus, ça fait un gros pâté en début de classe, et je n&#8217;aime pas ça.</p>
<p>Je suis tombé sur <a href="http://code.activestate.com/recipes/435880/">http://code.activestate.com/recipes/435880/</a> qui présente comment générer automatiquement le tuple <em>__slots__</em> pour ses classes en regardant tout simplement les variables fournies à <em>__init__</em> (il semble créer d&#8217;ailleurs une liste qui doit être changée en tuple par l&#8217;interpréteur). Bon pour les Host et Service, il n&#8217;y a qu&#8217;un seul paramètre, un tableau de construction. Mais ça m&#8217;a donné l&#8217;idée d&#8217;adapter ce code pour qu&#8217;il utilise les tableaux <em>properties </em>et <em>running_properties</em> de mes classes qui contiennent toutes les propriétés de mes objets.</p>
<p>Edit : Merci à Bertrand Mathieu pour la simplification du code par set.</p>
<p>Ceci donne au final la classe <em>AutoSlots</em> suivante :</p>
<p class="wp-caption" style="text-align: left;">class AutoSlots(type):<br />
&nbsp;&nbsp;&nbsp;def __new__(cls, name, bases, dct):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;slots = dct.get(&#8217;__slots__&#8217;, set())<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#Now get properties from properties and running_properties<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if &#8216;properties&#8217; in dct:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;slots.update((p for p in dct['properties']))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if &#8216;running_properties&#8217; in dct:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lots.update((p for p in dct['running_properties']))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dct['__slots__'] = tuple(slots)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return type.__new__(cls, name, bases, dct)</p>
<p style="text-align: left;">Qui est appelée avec :</p>
<p class="wp-caption" style="text-align: left;">class Service(SchedulingItem):<br />
&nbsp;&nbsp;&nbsp;#AutoSlots create the __slots__ with properties and<br />
&nbsp;&nbsp;&nbsp;#running_properties names<br />
&nbsp;&nbsp;&nbsp;__metaclass__ = AutoSlots</p>
<p class="wp-caption" style="text-align: left;">[..]</p>
<p>Maintenant les <em>__slots__</em> sont construits à la volée, et il n&#8217;y a plus de risque d&#8217;oublier des paramètres et mes classes Host/Service se re-concentrent un peu sur ce qu&#8217;elles doivent faire, et non sur une astuce pour contourner une consommation excessive de RAM par Python.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.gabes.fr/jean/2010/02/15/partie-a-trois-python-__slots__-et-metaclass/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

