# articles

feed_id: http://sametmax.com/?p=6524
uri: 2013-07-02-Le-guide-ultime-et-définitif-sur-la-programmation-orientée-objet-en
title:
Le guide ultime et définitif sur la programmation orientée objet en Python à l’usage des débutants qui sont rassurés par les textes détaillés qui prennent le temps de tout expliquer. Partie 8.

url:
http://sametmax.com/le-guide-ultime-et-definitif-sur-la-programmation-orientee-objet-en-python-a-lusage-des-debutants-qui-sont-rassures-par-les-textes-detailles-qui-prennent-le-temps-de-tout-expliquer-partie-8/

content:
<p>8ème et dernier chapitre sur la programmation orientée objet en Python. Nous allons voir l&#8217;ultime réalité, le secret cosmique de nirvana Pythonique, le truc dont personne ne se sert avant d&#8217;avoir au moins codé 3 moteurs de blogs, un bot twitter et une IA de real doll.</p>
<p>J&#8217;ai nommé&#8230;</p>
<p>Les métaclasses.</p>
<p>Comme tous les articles sur la question, je commence avec la citation standard :</p>
<blockquote><p>Les métaclasses sont une magie trop obscure pour que 99% des utilisateurs s&#8217;en préoccupe. Si vous vous demandez si vous en avez besoin, ce n&#8217;est pas le cas (les gens qui en ont vraiment besoin le savent avec certitude et n&#8217;ont pas besoin d&#8217;explications sur la raison).
    </p></blockquote>
<p>    <em>Tim Peters, les mec qui <a href="http://www.python.org/dev/peps/pep-0020/">a écrit le PEP20</a>.</em></p>
<p>En résumé, cet article ne vous servira probablement pas. Je me suis servi, en 10 ans, deux fois des métaclasses dans ma vie. C&#8217;est pour le sport, quoi.</p>
<p>Pré-requis:</p>
<ul>
<li>Avoir lu la <a href="http://sametmax.com/le-guide-ultime-et-definitif-sur-la-programmation-orientee-objet-en-python-a-lusage-des-debutants-qui-sont-rassures-par-les-textes-detailles-qui-prennent-le-temps-de-tout-expliquer-partie-7/">partie précédente</a> et bien tout compris. Mais alors bien tout. Si il subsiste un doute dans votre esprit, relisez toute la série car vous ne vous en sortirez pas.</li>
<li>Notamment, avoir bien pigé le principe de <code>object</code>, car les metaclasses ne fonctionnent qu&#8217;avec les New Style classes.</li>
<li>Comprendre le principe de références, callable, lambdas et dictionnaires en Python. En fait à peu prêt tout sauf les métaclasses parce que ce truc est ce que vous voulez apprendre en dernier de toute façon.</li>
<li>Être bien reposé et avoir du temps devant soi. Pas la peine de lire en diagonal. Vraiment.</li>
</ul>
<p>Musique.</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="420" height="315" src="//www.youtube.com/embed/AfNdyoNfPi8" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<h2>Au début, il y avait les objets</h2>
<p>Et <del>Dieu</del> Guido vit que cela était bon, et qu&#8217;il n&#8217;y avait pas de raison de ne pas se marrer un bon coup, alors il décida que le classes, qui servaient à fabriquer les objets, seraient aussi des objets.</p>
<p>Dans la plupart des langages, une classe est vraiment juste un plan pour produire un objet, un bout de code, une syntaxe élaborée pour dire &#8220;voici ma classe&#8221;. On peut l&#8217;imaginer comme cela en Python également, et vivre très heureux et avoir beaucoup de bons moments :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">class</span> CreateurDObject<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
...     <span style="color: #ff7700;font-weight:bold;">pass</span>
...
<span style="color: #66cc66;">&gt;&gt;&gt;</span> mon_objet = CreateurDObject<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>mon_objet<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>__main__.<span style="color: black;">CreateurDObject</span> <span style="color: #008000;">object</span> at 0x1c22fd0<span style="color: #66cc66;">&gt;</span></pre></div></div>

<p>Sauf qu&#8217;en Python, les classes sont aussi des objets.</p>
<p>Je vous laisse maturer ça 1 minute. Prenez une inspiration.</p>
<p>Quand l&#8217;interpréteur Python lit le mot <code>class</code>, il crée un objet. Dans le code ci-dessus, en mémoire, Python crée un objet <code>CreateurDObject</code>.</p>
<p>Cet objet est une classe, il permet de créer d&#8217;autres objets &#8211; ses instances &#8211; mais ça reste un objet. Et comme tous les objets&#8230;</p>
<p>On peut l&#8217;assigner à une variable :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> ReferenceACreateurDObjet = CreateurDObject
<span style="color: #66cc66;">&gt;&gt;&gt;</span> ReferenceACreateurDObjet<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>__main__.<span style="color: black;">CreateurDObject</span> <span style="color: #008000;">object</span> at 0x1c320d0<span style="color: #66cc66;">&gt;</span></pre></div></div>

<p>On peut le passer en paramètre :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">def</span> afficher_une_class<span style="color: black;">&#40;</span>cls<span style="color: black;">&#41;</span>:
...     <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Hey, on m'a passé la classe %s&quot;</span> <span style="color: #66cc66;">%</span> cls<span style="color: black;">&#41;</span>
...
<span style="color: #66cc66;">&gt;&gt;&gt;</span> afficher_une_class<span style="color: black;">&#40;</span>CreateurDObject<span style="color: black;">&#41;</span>
Hey, on m<span style="color: #483d8b;">'a passé la classe &lt;class '</span><span style="color: #dc143c;">__main__</span>.<span style="color: black;">CreateurDObject</span><span style="color: #483d8b;">'&gt;</span></pre></div></div>

<p>On peut lui ajouter des attributs à la volée :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> CreateurDObject.<span style="color: black;">nouvel_attribut</span> = <span style="color: #483d8b;">'nouvelle valeur'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">hasattr</span><span style="color: black;">&#40;</span>CreateurDObject, <span style="color: #483d8b;">'nouvel_attribut'</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">True</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> CreateurDObject.<span style="color: black;">nouvel_attribut</span>
u<span style="color: #483d8b;">'nouvelle valeur'</span></pre></div></div>

<h2>Le 7eme jour, on se faisait grave chier alors on a créé des classes dynamiquement</h2>
<p>Peut être vous souvenez-vous qu&#8217;on peut <a href="http://sametmax.com/comprendre-les-decorateurs-python-pas-a-pas-partie-1/">créer des fonctions à la volée </a>?</p>
<p>Parce qu&#8217;on peut faire pareil avec les classes :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">def</span> fabriquer_une_class<span style="color: black;">&#40;</span>nom<span style="color: black;">&#41;</span>:
...     <span style="color: #ff7700;font-weight:bold;">if</span> nom == <span style="color: #483d8b;">'bulbizarre'</span>:
...         <span style="color: #ff7700;font-weight:bold;">class</span> Bulbizarre<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
...             <span style="color: #ff7700;font-weight:bold;">pass</span>
...         <span style="color: #ff7700;font-weight:bold;">return</span> Bulbizarre <span style="color: #808080; font-style: italic;"># je retourne Bulbizarre, PAS Bulbizarre()</span>
...     <span style="color: #ff7700;font-weight:bold;">else</span>:
...         <span style="color: #ff7700;font-weight:bold;">class</span> Salameche<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>: <span style="color: #808080; font-style: italic;"># qui prenait carapuce, sérieux ?</span>
...             <span style="color: #ff7700;font-weight:bold;">pass</span>
...         <span style="color: #ff7700;font-weight:bold;">return</span> Salameche
<span style="color: #66cc66;">&gt;&gt;&gt;</span> Pokemon = fabriquer_une_class<span style="color: black;">&#40;</span><span style="color: #483d8b;">'autre'</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>Pokemon<span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># Pokemon est une CLASSE, pas une instance</span>
<span style="color: #66cc66;">&lt;</span>type <span style="color: #483d8b;">'type'</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> nouveau_pokemon = Pokemon<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># la je créer une instance</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>nouveau_pokemon<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>class <span style="color: #483d8b;">'__main__.Salameche'</span><span style="color: #66cc66;">&gt;</span></pre></div></div>

<p>Une classe n&#8217;est pas quelque chose de figé dans le marbre, comme tout le reste en  Python, on peut les fabriquer dynamiquement, les modifier en cours de route, les malmener, etc.</p>
<p>Aucun pokemon n&#8217;a cependant été blessé pendant la rédaction de cet article. Tiens je me demande si il y a des sites zoophiles spécialisés dans les Pokemons. Qu&#8217;est-ce que je raconte ? Évidement qu&#8217;il y en a. D&#8217;ailleurs Pikachu est comme une shocking flech torch avec piles incluses quand on y pense. Ou un appareil à abdos. Il faut que je fasse des abdos, j&#8217;ai pris du bide. Heu&#8230; où j&#8217;en étais ?</p>
<p>A oui. Classes. Dynamiques.</p>
<p>Comme toutes les <del>opérations courantes</del> idées à la con, Python vous permet de faire ça complètement à la main. Maintenant vient la troisième Révélation Des Métaclasses : la fonction <code>type()</code> a deux usages.</p>
<p>Dans une première vie <code>type()</code> est une fonction ordinaire, elle sert à retourner le type d&#8217;un objet :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>type <span style="color: #483d8b;">'int'</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;1&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>type <span style="color: #483d8b;">'str'</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>CreateurDObject<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>type <span style="color: #483d8b;">'type'</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>CreateurDObject<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>class <span style="color: #483d8b;">'__main__.CreateurDObject'</span><span style="color: #66cc66;">&gt;</span></pre></div></div>

<p>Et propose à sa logeuse de descendre ses poubelles. Mais elle a une autre vie électronique, elle est aussi capable de créer une classe.</p>
<p>Oui c&#8217;est très con d&#8217;avoir choisit la même PUTAIN DE FONCTION pour faire deux trucs qui n&#8217;ont rien à voir. Mais les deux usages ont un avenir et il va falloir faire avec, se caler ça où je pense et oubliez votre avocat.</p>
<p>Bref, ça marche comme ça :</p>
<p><code>type(nom de la classe, tuple des parents de la classe, dictionnaire contenant les attributs)</code></p>
<p>Le nom de la classe, je pense que vous avez pigé.</p>
<p>Le tuple des parents, il peut être vide. C&#8217;est dans le cas où vous souhaitez un héritage : vous pouvez passer des références aux classes parentes.</p>
<p>Le dictionnaire est assez simple : chaque clé est un nom d&#8217;attribut, chaque valeur est une valeur d&#8217;attribut.</p>
<p>Exemple, cette classe :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">class</span> Pokeball<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
...     <span style="color: #ff7700;font-weight:bold;">pass</span></pre></div></div>

<p>Peut se créer ainsi :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> Pokeball = <span style="color: #008000;">type</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Pokeball'</span>, <span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Et s&#8217;utiliser tout pareil :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>Pokeball<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>class <span style="color: #483d8b;">'__main__.Pokeball'</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>Pokeball<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>__main__.<span style="color: black;">Pokeball</span> <span style="color: #008000;">object</span> at 0x1c32450<span style="color: #66cc66;">&gt;</span></pre></div></div>

<p>Vous aurez noté que le nom de classe passé en paramètre est le même que celui de la variable qui va recevoir la classe ainsi créée. Oui, ils peuvent être différents. Non, ça ne sert à rien.</p>
<p>Et je sais que certains auraient préféré MyLittlePoney, mais je fais avec ma maigre culture G. Faudrait que je tente avec des noms de Pogs.</p>
<p>Un petit exemple avec des attributs :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">class</span> Pokeball<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
...     <span style="color: black;">couleurs</span> = <span style="color: black;">&#40;</span><span style="color: #483d8b;">'rouge'</span>, <span style="color: #483d8b;">'blanc'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Ce qui donne :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> Pokeball = <span style="color: #008000;">type</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Pokeball'</span>, <span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#123;</span><span style="color: #483d8b;">'couleurs'</span>: <span style="color: black;">&#40;</span><span style="color: #483d8b;">'rouge'</span>, <span style="color: #483d8b;">'blanc'</span><span style="color: black;">&#41;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> Pokeball.<span style="color: black;">couleurs</span>
<span style="color: black;">&#40;</span>u<span style="color: #483d8b;">'rouge'</span>, u<span style="color: #483d8b;">'blanc'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Étant donné que les méthodes sont des attributs&#8230;</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">class</span> Pokeball<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
  ...     <span style="color: #ff7700;font-weight:bold;">def</span> attraper<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
  ...         <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;ratééééééééééééé&quot;</span><span style="color: black;">&#41;</span>
  ...</pre></div></div>

<p>Peut se traduire par :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> Pokeball = <span style="color: #008000;">type</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Pokeball'</span>, <span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#123;</span><span style="color: #483d8b;">'attraper'</span>: <span style="color: #ff7700;font-weight:bold;">lambda</span> <span style="color: #008000;">self</span>: <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;ratéééééééééééé&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> Pokeball<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">attraper</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
ratéééééééééééé</pre></div></div>

<p>Au passage, toute classe créée par <code>type</code> hérite automatiquement de <code>object</code>, pas besoin de le préciser.</p>
<p>Petite démo avec de l&#8217;héritage  :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">class</span> Masterball<span style="color: black;">&#40;</span>Pokeball<span style="color: black;">&#41;</span>:
...     <span style="color: #ff7700;font-weight:bold;">def</span> attraper<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
...         <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;yeahhhhhhhhhh&quot;</span><span style="color: black;">&#41;</span>
...</pre></div></div>

<p>Se transforme en :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> Masterball = <span style="color: #008000;">type</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Masterball'</span>, <span style="color: black;">&#40;</span>Pokeball,<span style="color: black;">&#41;</span>, <span style="color: black;">&#123;</span><span style="color: #483d8b;">'attraper'</span>: <span style="color: #ff7700;font-weight:bold;">lambda</span> <span style="color: #008000;">self</span>: <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;yeahhhhhhhhhh&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> Masterball<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">attraper</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
yeahhhhhhhhhh</pre></div></div>

<p>Je répète les Révélations Divines :</p>
<ol>
<li>
Les classes sont des objets.
</li>
<li>On peut créer les classes à la volée.</li>
<li><code>type()</code> permet de créer une classe manuellement.</li>
<li>Keanu Reeves est un mauvais acteur.</li>
</ol>
<p>Vous voyez où je veux en venir, là, non ?</p>
<h2>Et le tout puissant déclara : tu créeras des classes avec des classes</h2>
<p>Et tu n&#8217;aimeras pas ça. Alors au début tu le feras avec des fonctions parce que c&#8217;est plus facile.</p>
<p>Une métaclasse, c&#8217;est seulement le nom du &#8220;truc&#8221; qui fabrique une classe. C&#8217;est tout.</p>
<p>C&#8217;est pour ça qu&#8217;on appelle les métaclasses, les classes des classes.</p>
<p>Puisque les classes sont des objets ?</p>
<p>Vous suivez ?</p>
<p>Non ?</p>
<p>Ah.</p>
<p>o</p>
<p>En deux lignes alors :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">UneClasse = MetaClass<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
un_objet = UneClasse<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Mieux ?</p>
<p>Vous avez vu la fonction <code>type()</code> créer des classes ? En fait la fonction <code>type()</code> est une métaclasse. C&#8217;est la métaclasse dont Python se sert pour créer tous les objets classes, quand vous tapez le keyword <code>class</code>.</p>
<p>Il est facile de voir ça en regardant l&#8217;attribut <code>__class__</code>, qui indique quelle classe a servi à créer un objet :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> pokemon_capture = <span style="color: #ff4500;">149</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> pokemon_capture.__class__
<span style="color: #66cc66;">&lt;</span>type <span style="color: #483d8b;">'int'</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> nom = <span style="color: #483d8b;">'magicarp'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> nom.__class__
<span style="color: #66cc66;">&lt;</span>type <span style="color: #483d8b;">'str'</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">def</span> attrapez_les_presque_tous<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>: <span style="color: #ff7700;font-weight:bold;">pass</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> attrapez_les_presque_tous.__class__
<span style="color: #66cc66;">&lt;</span>type <span style="color: #483d8b;">'function'</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">class</span> Pokedex<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>: <span style="color: #ff7700;font-weight:bold;">pass</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> gadget = Pokedex<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> gadget.__class__
<span style="color: #66cc66;">&lt;</span>class <span style="color: #483d8b;">'__main__.Pokedex'</span><span style="color: #66cc66;">&gt;</span></pre></div></div>

<p>Mais quelle est le <code>__class__</code> de tout <code>__class__</code> ?</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> attrapez_les_presque_tous.__class__.__class__
<span style="color: #66cc66;">&lt;</span>type <span style="color: #483d8b;">'type'</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> pokemon_capture.__class__.__class__
<span style="color: #66cc66;">&lt;</span>type <span style="color: #483d8b;">'type'</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> nom.__class__.__class__
<span style="color: #66cc66;">&lt;</span>type <span style="color: #483d8b;">'type'</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> gadget.__class__.__class__
<span style="color: #66cc66;">&lt;</span>type <span style="color: #483d8b;">'type'</span><span style="color: #66cc66;">&gt;</span></pre></div></div>

<p>Normalement c&#8217;est à ce moment là que vous avez la Grande Révélation.</p>
<p>Faites &#8220;Ahhhhhhhhhhhhhhhhh&#8221;.</p>
<p>Donc la métaclasse, c&#8217;est le machin qui fabrique les classes, c&#8217;est une factory de classe. <code>type</code> est la métaclasse utilisée par défaut, mais vous pensez bien, chers amis, qu&#8217;on peut fabriquer ses propres métaclasses. Sinon ça serait pas marrant.</p>
<p>Ça marche comme ça :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> UneClasse<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
  <span style="color: #0000cd;">__metaclass__</span> = votre métaclasse
  <span style="color: black;">&#91;</span> le reste du <span style="color: #dc143c;">code</span> de la classe <span style="color: black;">&#93;</span></pre></div></div>

<p>Quand Python va voir ça, il ne va pas créer la classe immédiatement, il d&#8217;abord suivre le chaîne d&#8217;héritage pour trouver qu&#8217;elle métaclasse utiliser pour fabriquer la classe :</p>
<p>Il va regarder d&#8217;abord vérifier si il y a <code>__metaclass__</code> de déclarée. Si ce n&#8217;est pas le cas, il va chercher dans les parents si ils ont un attribut <code>__metaclass__</code>. Si ce n&#8217;est pas le cas, il va utiliser <code>type</code>. Si Python trouve <code>__metaclass__</code>, alors il utilisera son contenu à la place de <code>type</code>.</p>
<p>Dans les deux cas, il va collecter toutes les informations sur la classe (le nom, les parents, les attributs), et les passer en paramètres à <code>type</code> ou votre métaclasse, et récupérer le résultat. Puis, seulement à ce moment là, il enregistre votre classe en mémoire.</p>
<p>Prenez votre temps sur ces paragraphes, c&#8217;est un peu la clé de tout le tuto.</p>
<p>Bon, nouvelle révélation : une métaclasse n&#8217;a pas besoin d&#8217;être une classe.</p>
<p>Je sais, c&#8217;est idiot d&#8217;appeler un truc &#8220;métaclass&#8221; si ça n&#8217;a pas besoin d&#8217;être une classe. Mais on parle de la fonctionnalité qui utilise <code>type</code> pour un truc qui n&#8217;a rien à avoir. Ça devait être le jour du beaujolais nouveau quand ils ont introduit la feature.</p>
<p>En fait, une métaclasse peut être n&#8217;importe quel callable qui retourne une classe, donc une fonction toute conne fait très bien l&#8217;affaire.</p>
<p>Le but de la métaclasse, c&#8217;est d&#8217;intercepter la création de la classe afin de la modifier, et voici ce que ça donne :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># une métaclasse DOIT avoir la même signature que type() puisque</span>
<span style="color: #808080; font-style: italic;"># Python va lui passer tout ça automatiquement en paramètre</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> prefixer<span style="color: black;">&#40;</span>nom, parents, attributs<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
        On va créer une métaclasse qui prend tous les noms de méthodes,
        et les prefixe du mot &quot;attaque&quot;. Oui ça ne sert à rien. Mais
        les usages des métaclasses qui servent à quelques choses sont
        généralement très compliqués.
    &quot;&quot;&quot;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># On crée un nouveau dictionnaire d'attributs avec les noms préfixés</span>
    <span style="color: #808080; font-style: italic;"># On fait gaffe à pas modifier les __méthodes_magique__.</span>
    nouveaux_attributs = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> nom, val <span style="color: #ff7700;font-weight:bold;">in</span> attributs.<span style="color: black;">items</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> nom.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'__'</span><span style="color: black;">&#41;</span>:
            nouveaux_attributs<span style="color: black;">&#91;</span><span style="color: #483d8b;">'attaque_'</span> + nom<span style="color: black;">&#93;</span> = val
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            nouveaux_attributs<span style="color: black;">&#91;</span>nom<span style="color: black;">&#93;</span> = val
&nbsp;
    <span style="color: #808080; font-style: italic;"># On délègue la création de la classe à type() :</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>nom, parents, nouveaux_attributs<span style="color: black;">&#41;</span></pre></div></div>

<p>L&#8217;utilisation est toute simple, on écrit une classe normale, et on lui rajoute <code>__metaclass__</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">class</span> Ronflex<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #0000cd;">__metaclass__</span> = prefixer
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> armure<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;defense +15&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> dodo<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;zzzzzz&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> r = Ronflex<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> r.<span style="color: black;">attaque_armure</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
defense +<span style="color: #ff4500;">15</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> r.<span style="color: black;">attaque_dodo</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
zzzzzz
<span style="color: #66cc66;">&gt;&gt;&gt;</span> r.<span style="color: black;">dodo</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&lt;ipython-input-58-90dd54234d5d&gt;&quot;</span>, line <span style="color: #ff4500;">1</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #66cc66;">&lt;</span>module<span style="color: #66cc66;">&gt;</span>
    r.<span style="color: black;">dodo</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">AttributeError</span>: <span style="color: #483d8b;">'armure'</span> <span style="color: #008000;">object</span> has no attribute <span style="color: #483d8b;">'dodo'</span></pre></div></div>

<p>Voilà, c&#8217;est à peut prêt tout ce qu&#8217;il y a à comprendre des métaclasses :</p>
<ol>
<li>On intercepte la création classe.</li>
<li>On modifie les paramètres.</li>
<li>On retourne la classe customisée.</li>
</ol>
<p>Maintenant, la grande question : à quoi ça sert ?</p>
<p>Généralement, ça sert à faire de jolies APIs. Par exemple, les ORM (<a href="http://sametmax.com/sept-petites-libs-qui-changent-la-vie-dun-dev-python/">peewee</a>, SQLAlchemy, l&#8217;ORM de Django) utilisent les métaclasses pour avoir un style déclaratif :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Article<span style="color: black;">&#40;</span>Model<span style="color: black;">&#41;</span>:
    titre = model.<span style="color: black;">CharField</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Ici, <code>Model</code> va contenir une métaclasse, comme c&#8217;est un parent, la métaclasse sera aussi appelée pour <code>Article</code>, et elle peut donc agir pour modifier <code>titre</code> à la volée.</p>
<p>En effet, quand vous faites :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> art = Article.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #008000;">id</span>=<span style="color: #ff4500;">13</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> art.<span style="color: black;">titre</span>
u<span style="color: #483d8b;">'Python pour les méca-scriptophiles'</span></pre></div></div>

<p>Avec un ORM, vous récupérez la valeur de <code>titre</code> dans la base de données et non un <code>CharField()</code>. C&#8217;est le but : cacher des requêtes SQL et donner l&#8217;impression de manipuler des objets.</p>
<p>Ici le rôle de la métaclasse, c&#8217;est de prendre tous les attributs de types <code>xxxField()</code>, et modifier la classe pour qu&#8217;accéder à l&#8217;attribut fasse la requête voulue à la base de données.</p>
<p>On peut aussi utiliser les métaclasses pour faire des vérifications : s&#8217;assurer que la classe n&#8217;utilise pas un nom que vous voulez réserver, ou qu&#8217;elle contient bien un attribut.</p>
<p>Il y a même des <a href="http://docs.python.org/2/library/abc.html?highlight=abc#abc">implémentations</a> d&#8217;interfaces (ou plutôt de l&#8217;équivalent des classes abstraites en Java) pour Python utilisant les métaclasses. Je ne suis pas convaincus par leur utilité, mais c&#8217;est possible.</p>
<h2>Soyez prophètes</h2>
<p>C&#8217;est pas le tout, mais maintenant que vous avez compris, il est temps de limer les bords pour que vous alliez porter la bonne parole.</p>
<p>Donc déjà, bon à savoir : <code>metaclass</code> est un paramètre de classe en Python 3. Ca donne ça:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> DePython3<span style="color: black;">&#40;</span>metaclass=votre_metaclasse<span style="color: black;">&#41;</span></pre></div></div>

<p>Ensuite, il y des conventions de nommage. Tout comme on nomme <code>self</code> le premier paramètre des méthodes, et <code>*args</code> / <code>**kwargs</code> les paramètres dynamiques, les paramètres des métaclasses ont des noms conventionels. La métaclasse précédente s&#8217;écrirait donc plus proprement :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> prefixer<span style="color: black;">&#40;</span>name, bases, dct<span style="color: black;">&#41;</span>:
    nouveaux_attributs = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> nom, val <span style="color: #ff7700;font-weight:bold;">in</span> dct.<span style="color: black;">items</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> nom.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'__'</span><span style="color: black;">&#41;</span>:
            nouveaux_attributs<span style="color: black;">&#91;</span><span style="color: #483d8b;">'attaque_'</span> + nom<span style="color: black;">&#93;</span> = val
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            nouveaux_attributs<span style="color: black;">&#91;</span>nom<span style="color: black;">&#93;</span> = val
&nbsp;
    <span style="color: #808080; font-style: italic;"># On délègue la création de la classe à type() :</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>name, bases, nouveaux_attributs<span style="color: black;">&#41;</span></pre></div></div>

<p>Enfin, souvenez-vous que les métaclasses ne fonctionnent qu&#8217;avec les New Style classes, donc celles qui héritent de <code>object</code>.</p>
<p>Par ailleurs, vous croisez peut être des fois <code>__metaclass__</code> en plein milieu d&#8217;un module (pas dans une classe donc). C&#8217;est une vieille façon de faire, qui affecte toutes les classes du module. Ce n&#8217;est plus recommandé.</p>
<p>Terminons sur une version de métaclasse qui fait la même chose que <code>prefixer()</code>, mais sous forme de classe. Parce que sinon à quoi ça sert que ça s&#8217;appelle une métaclasse, hein ?</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># Oui, on peut hériter de type(), car c'est une classe, enfin une métaclasse.</span>
<span style="color: #808080; font-style: italic;"># Mais pas sous forme de fonction. Sous forme de classe. Mais son nom</span>
<span style="color: #808080; font-style: italic;"># est en minuscule, comme celui des classes int() et str(). Qui ne sont</span>
<span style="color: #808080; font-style: italic;"># pas des métaclasses. Souvenez-vous : Beaujolais.</span>
<span style="color: #ff7700;font-weight:bold;">class</span> Prefixer<span style="color: black;">&#40;</span><span style="color: #008000;">type</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;"># __new__ est le vrai constructeur en Python, et il retourne l'instance</span>
    <span style="color: #808080; font-style: italic;"># en cours d'une classe. Or, qu'elle est l'instance d'une métaclasse ?</span>
    <span style="color: #808080; font-style: italic;"># Une classe !</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__new__</span><span style="color: black;">&#40;</span>cls, name, bases, dct<span style="color: black;">&#41;</span>:
&nbsp;
        nouveaux_attributs = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> nom, val <span style="color: #ff7700;font-weight:bold;">in</span> dct.<span style="color: black;">items</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> nom.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'__'</span><span style="color: black;">&#41;</span>:
                nouveaux_attributs<span style="color: black;">&#91;</span><span style="color: #483d8b;">'attaque_'</span> + nom<span style="color: black;">&#93;</span> = val
            <span style="color: #ff7700;font-weight:bold;">else</span>:
                nouveaux_attributs<span style="color: black;">&#91;</span>nom<span style="color: black;">&#93;</span> = val
&nbsp;
        <span style="color: #808080; font-style: italic;"># On délègue la création de la classe à son parent.</span>
        <span style="color: #808080; font-style: italic;"># Notez que cls doit être passé de bout en bout, ce qui n'est pas</span>
        <span style="color: #808080; font-style: italic;"># le cas d'habitude avec 'self'</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">super</span><span style="color: black;">&#40;</span>Prefixer, cls<span style="color: black;">&#41;</span>.<span style="color: #0000cd;">__new__</span><span style="color: black;">&#40;</span>cls, name, bases, nouveaux_attributs<span style="color: black;">&#41;</span></pre></div></div>

<p>Et ça s&#8217;utilise pareil</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">class</span> Ronflex<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    <span style="color: #0000cd;">__metaclass__</span> = Prefixer
    <span style="color: #ff7700;font-weight:bold;">def</span> armure<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;defense +15&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> dodo<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;zzzzzz&quot;</span><span style="color: black;">&#41;</span>
...
<span style="color: #66cc66;">&gt;&gt;&gt;</span> r = Ronflex<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> r.<span style="color: black;">attaque_dodo</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
zzzzzz
<span style="color: #66cc66;">&gt;&gt;&gt;</span> r.<span style="color: black;">attaque_armure</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
defense +<span style="color: #ff4500;">15</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> r.<span style="color: black;">dodo</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&lt;ipython-input-66-90dd54234d5d&gt;&quot;</span>, line <span style="color: #ff4500;">1</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #66cc66;">&lt;</span>module<span style="color: #66cc66;">&gt;</span>
    r.<span style="color: black;">dodo</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">AttributeError</span>: <span style="color: #483d8b;">'Ronflex'</span> <span style="color: #008000;">object</span> has no attribute <span style="color: #483d8b;">'dodo'</span></pre></div></div>

<p>Pourquoi utiliser une classe plutôt qu&#8217;une fonction alors que c&#8217;est vraiment plus compliqué ?</p>
<p>Et bien l&#8217;avantage d&#8217;utiliser une classe est qu&#8217;elle peut avoir des attributs et hériter. Car bien entendu, on peut avoir des metaclasses, qui héritent de metaclasses, et ainsi de suite, jusqu&#8217;à ce que du Lisp paraisse avoir du sens en comparaison.</p>
<p>On peut même faire plus vicieux et utiliser <code>__call__</code> au lieu de <code>__new__</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># on hérite plus de type, rien à foutre</span>
<span style="color: #ff7700;font-weight:bold;">class</span> Prefixer<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, prefix=<span style="color: #483d8b;">'attaque'</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">prefix</span> = prefix
&nbsp;
    <span style="color: #808080; font-style: italic;"># __call__ est la méthode appelée automatiquement quand on ajoute () après</span>
    <span style="color: #808080; font-style: italic;"># un nom d'objet. Ca permet de rendre un objet callable. En gros, ça nous</span>
    <span style="color: #808080; font-style: italic;"># permet d'utiliser une instance de Prefixer() comme une fonction</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__call__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, name, bases, dct<span style="color: black;">&#41;</span>:
&nbsp;
        nouveaux_attributs = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> nom, val <span style="color: #ff7700;font-weight:bold;">in</span> dct.<span style="color: black;">items</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> nom.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'__'</span><span style="color: black;">&#41;</span>:
                nouveaux_attributs<span style="color: black;">&#91;</span><span style="color: #008000;">self</span>.<span style="color: black;">prefix</span> + nom<span style="color: black;">&#93;</span> = val
            <span style="color: #ff7700;font-weight:bold;">else</span>:
                nouveaux_attributs<span style="color: black;">&#91;</span>nom<span style="color: black;">&#93;</span> = val
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>name, bases, nouveaux_attributs<span style="color: black;">&#41;</span></pre></div></div>

<p>Et c&#8217;est sympa car du coup on peut passer des paramètres à notre métaclasse :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">class</span> Ronflex<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    <span style="color: #0000cd;">__metaclass__</span> = Prefixer<span style="color: black;">&#40;</span>prefix=<span style="color: #483d8b;">'tatayoyo_'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> armure<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;defense +15&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> dodo<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;zzzzzz&quot;</span><span style="color: black;">&#41;</span>
...         
<span style="color: #66cc66;">&gt;&gt;&gt;</span> r = Ronflex<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> r.<span style="color: black;">tatayoyo_dodo</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
zzzzzz</pre></div></div>

<p>Voilà, vous avez vu le visage de Dieu en face. C&#8217;est comme ça qu&#8217;il fabrique le monde.</p>
<p>Ah mais attendez ? Si <code>type()</code> est la métaclasse de tous les objets ? Qu&#8217;est-ce qui et la métaclasse de <code>type()</code> ?</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">type</span>.__class__
<span style="color: #66cc66;">&lt;</span>type <span style="color: #483d8b;">'type'</span><span style="color: #66cc66;">&gt;</span></pre></div></div>

<p>Je vous laisse méditer sur cette découverte métaphysique.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6524&amp;md5=d8e07460f74d9528ca38e6d90fdf4d35" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6544
title: Qu’est-ce que WSGI et à quoi ça sert ?
uri: Qu-est-ce-que-WSGI-et-à-quoi-ça-sert
url: http://sametmax.com/quest-ce-que-wsgi-et-a-quoi-ca-sert/
content:
<p>On va dire que je me répète, mais <a href="https://en.wikipedia.org/wiki/Wsgi">WSGI</a> est typiquement le cas d&#8217;une notion simple et super mal expliquée sur le Web.</p>
<p>C&#8217;est terrible ça, une vrai maladie. Ça me donne envie de faire des vidéos comme le joueur du Grenier pour râler à voix haute.</p>
<p>Bref.</p>
<p>Donc WSGI a le même but que FastCGI, SCGI, or AJP : c&#8217;est une norme qui sert à définir comment un serveur Python et son application peuvent discuter. Ça été pondu pour que tous les serveurs et toutes les applications Python qui respectent la norme soient garantis de pouvoir s&#8217;interfacer.</p>
<p>Ça, c&#8217;est la définition que vous voyez partout. Super, mais concrètement ça veut dire quoi ?</p>
<h2>WSGI, c&#8217;est juste une convention de discussion</h2>
<p>Un bon dessin vaut mieux&#8230;</p>
<div id="attachment_6545" class="wp-caption aligncenter" style="width: 465px"><a href="media/35f3465d.wsgi.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/wsgi.png"><img class=" wp-image-6545  " title="C'est compliqué de faire un schéma comme ça sérieux ? Ah ça pond une norme de 30 pages mais ça peut pas faire 3 ronds dans paint." src="media/35f3465d.wsgi.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/wsgi.png" alt="Schéma du fonctionnement de WSGI" width="455" height="644" /></a><p class="wp-caption-text">C&#39;est compliqué de faire un schéma comme ça sérieux ? Ah ça pond une norme de 30 pages mais ça peut pas faire 3 ronds dans paint.</p></div>
<p>D&#8217;un côté vous avez des serveurs comme ceux de cherrypy, de paste, de werkzeug ou comme la commande runserver de Django, ou tels que les serveurs gunicorn, Apache (avec mod_wsgi). Ces logiciels ont pour boulot d’accueillir une requête HTTP et de renvoyer la réponse. Ils ont des problématiques comme : gérer les sockets, gérer plusieurs processus en parallèle, éviter qu&#8217;un pirate se balade sur votre serveur, etc.</p>
<p>De l&#8217;autre côté vous avez votre application. 9 fois sur 10, votre site Web, donc votre code. Sa problématique c&#8217;est de recevoir une requête, la comprendre, et générer une réponse en tapant dans la base de données, et en faisant sa popotte HTML.</p>
<p>Il faut donc que votre serveur dialogue avec votre app, qu&#8217;il lui passe la requête, que votre app la gère, retourne la réponse, et file la réponse au serveur. Alors le serveur envoie la réponse au navigateur.</p>
<p>C&#8217;est la chose la plus mal expliquée : il y a deux parties à WSGI. Une pour le serveur, et une pour l&#8217;application.</p>
<p>Un serveur est dit &#8220;compatible WSGI&#8221; quand il est capable de transmettre une requête HTTP normale à votre application via le protocole WSGI, et qu&#8217;il est capable de récupérer une réponse HTTP depuis votre application via le protocole WSGI pour en faire une requête HTTP normale.</p>
<p>Une application est dite &#8220;compatible WSGI&#8221; quand elle est capable de recevoir une requête HTTP <strong>transformée en un objet Python</strong> selon la norme WSGI, et qu&#8217;elle retourne une réponse HTTP <strong>sous la forme d&#8217;un objet Python</strong> selon la norme WSGI.</p>
<h2>J&#8217;avais demandé concrètement, show me the fucking code !</h2>
<p>Côté serveur WSGI, on doit lui passer le point d&#8217;entrée de votre app.</p>
<p>Le point d&#8217;entrée est un module Python qui contient une variable nommé <code>application</code>.</p>
<p>C&#8217;est tout.</p>
<p>La variable application doit contenir votre application compatible WSGI.</p>
<p>Une application compatible WSGI a un certain nombre de méthodes pour accepter en paramètres un objet requête HTTP, et retourner un objet réponse HTTP, mais la bonne nouvelle, c&#8217;est que <strong>vous n&#8217;avez absolument pas besoin de savoir comment ça marche</strong>.</p>
<p>En effet, tous les frameworks compatibles WSGI (bottle, django, cherrypy, etc) ont une fonction qui retourne cette application toute faite.</p>
<p>Par exemple, avec bottle, mon fichier wsgi va contenir :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">site</span> <span style="color: #ff7700;font-weight:bold;">import</span> app
&nbsp;
application = app</pre></div></div>

<p>C&#8217;est tout. <code>app</code>, le décorateur qui permet de faire <code>@app.route('/')</code> dans le code du site bottle, est déjà une application WSGI.</p>
<p>Pour Django, ça va donner un truc comme :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #808080; font-style: italic;"># ont dit quel est le module de settings Django</span>
<span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;DJANGO_SETTINGS_MODULE&quot;</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">&quot;project.settings&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># et on fabrique l'application WSGI avec une fonction</span>
<span style="color: #808080; font-style: italic;"># que Django nous donne</span>
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">core</span>.<span style="color: black;">wsgi</span> <span style="color: #ff7700;font-weight:bold;">import</span> get_wsgi_application
&nbsp;
application = get_wsgi_application<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Le simple fait qu&#8217;il y ait une variable nommée <code>application</code> fait que le serveur va se débrouiller. Tout ce qu&#8217;il y a à faire, c&#8217;est passer en paramètre ce module au serveur, et comment le faire dépend du serveur.</p>
<p>Par exemple pour gunicorn, c&#8217;est le premier paramètre de la commande qu&#8217;on utilise pour lancer le serveur :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">gunicorn nom_du_module</pre></div></div>

<p>Il faut que le module soit importable (on peut passer l&#8217;option <code>--pythonpath</code> pour s&#8217;en assurer.)</p>
<p>Pour Apache et mod_wsgi, ça se fait dans le fichier de config <em>apache.conf</em>:</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;">WSGIScriptAlias / /chemin/version/module.wsgi</pre></div></div>

<p>Bref, faire dialoguer un serveur et une application WSGI, c&#8217;est con comme la lune :</p>
<ol>
<li>Faire un module qui contient une variable nommée <code>application</code> contenant l&#8217;app WSGI.</li>
<li>Dire au serveur où se trouve le fichier</li>
</ol>
<h2>Avantages et inconvénients de WSGI</h2>
<p>Parmi les avantages, on retrouve :</p>
<ul>
<li>Pas de parsing de la requête au niveau de l&#8217;application.</li>
<li>Entrée de toutes les apps WSGI normalisées.</li>
<li>Tous les logiciels WSGI sont compatibles entre eux.</li>
<li>Le module WSGI reste chargé en mémoire une bonne fois pour toute, pas besoin de le recréer à chaque requête.</li>
<li>WSGI se suffit à lui même pour écrire une application. Dans la théorie, on n&#8217;a même pas besoin de framework.</li>
</ul>
<p>Quant aux inconvénients :</p>
<ul>
<li>En pratique il y a très peu de code partagé entre les applications WSGI. La communication sur WSGI s&#8217;est très mal passée et cela reste quelque chose de mystérieux pour la plupart des développeurs.</li>
<li>WSGI ne gère pas les websockets, et la norme est en train d&#8217;être mise à jour pour cela. Mais cela prend du temps et les websockets sont déjà là, du coup les gens se tournent vers des solutions non WSGI (tornado, twisted, etc).</li>
<li>Certains serveurs ne gèrent pas WSGI (comme nginx ou lighttpd), du coup on ne peut pas communiquer directement entre l&#8217;app et eux. Il faut un intermédiaire. C&#8217;est pour cela qu&#8217;on voit très souvent des setups comme nginx <=> gunicorn <=> django, avec un serveur WSGI qui sert d&#8217;intermédiaire. Il y a tout de même le bénéfice de pouvoir gérer parfaitement indépendamment le processus WSGI du serveur HTTP, ce qui est très pratique pour le debug, l&#8217;administration système, le déploiement, etc.</li>
<li>WSGI, c&#8217;est du Python. Qui dit Python, dit import, qui dit import, dit PYTHON PATH. 90% des erreurs de mise en prod sont des erreurs d&#8217;import, et pour cette raison <code>sys.path</code> est presque toujours manipulé dans un fichier qui contient une application WSGI.</li>
</ul>
<h2>Pour la culture</h2>
<p>Voici à quoi ressemble un hello world en WSGI :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> application<span style="color: black;">&#40;</span>environ, start_response<span style="color: black;">&#41;</span>:
    start_response<span style="color: black;">&#40;</span><span style="color: #483d8b;">'200 OK'</span>, <span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Content-Type'</span>, <span style="color: #483d8b;">'text/plain'</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #483d8b;">'Hello World<span style="color: #000099; font-weight: bold;">\n</span>'</span></pre></div></div>

<p>Et oui, c&#8217;est très simple, et il n&#8217;y a rien à importer. La norme WSGI est une convention : il doit y avoir une variable nommée <code>application</code> (ici la variable c&#8217;est le nom de la fonction), et cette variable doit contenir une application WSGI.</p>
<p>Mais une application WSGI, c&#8217;est juste un callable (ici une fonction) qui accepte en paramètres <code>environ</code> (la requête), <code>start_response</code> (une fonction qui écrit l&#8217;en-tête de la réponse) et qui retourne un générateur de string. C&#8217;est tout.</p>
<p>Il n&#8217;y a rien de magique. C&#8217;est une simple interface sur laquelle tout le monde s&#8217;est mis d&#8217;accord.</p>
<p>Quand on fait en Django:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">application = get_wsgi_application<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>En fait Django ne fait que fabriquer une fonction comme on vient de voir, qui derrière appelle votre application Django.</p>
<p>En revanche, comme on utilise souvent Django derrière nginx, le setup ressemble très souvent à ça :</p>
<div id="attachment_6546" class="wp-caption aligncenter" style="width: 465px"><a href="media/cfa4386e.wsgi_with_nginx.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/wsgi_with_nginx.png"><img class="size-full wp-image-6546" title="Quand on voit &quot;socket&quot;, ça fait peur, mais c'est juste une ligne de config qui point généralement vers localhost:8000." src="media/cfa4386e.wsgi_with_nginx.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/wsgi_with_nginx.png" alt="Schém d'utilistation de WSGI avec Nginx" width="455" height="644" /></a><p class="wp-caption-text">Quand on voit &quot;socket&quot;, ça fait peur, mais c&#39;est juste une ligne de config qui point généralement vers localhost:8000.</p></div>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6544&amp;md5=7b0bfe72a1ba28286d021e7e0529f0f3" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6562
title: Les vierges, c’est chiant
uri: Les-vierges-c-est-chiant
url: http://sametmax.com/les-vierges-cest-chiant/
content:
<p>D&#8217;où vient ce fantasme des vierges ?</p>
<p>Quel intérêt de coucher avec une personne sans expérience ?</p>
<p>La plupart du temps elle va être timide, ne connait ni le corps de l&#8217;homme, ni le sien, et ne sait pas vraiment quoi faire.</p>
<p>Je ne dis pas que le status de vierge pose problème. On a tous été débutant.</p>
<p>Je ne dis pas qu&#8217;il ne faut pas encourager les débutants, et même s&#8217;envoyer en l&#8217;air avec. Il faut bien qu&#8217;ils apprennent, et on apprend toujours moins vite entre débutants.</p>
<p>Mais quid des mecs qui sont excités par les pucelles, sérieusement ? Je ne parle même pas des pédophiles, alors là je trouve ça aussi logique que de vouloir faire un bras de fer avec un ouistiti.</p>
<p>En plus, et à moins d&#8217;être un gros connard, on se tape la responsabilité de sa première fois. Autant dire qu&#8217;on s&#8217;amuse pas des masses. Surtout que souvent, c&#8217;est douloureux pour la nana. Génial ! Qu&#8217;est-ce qu&#8217;on se marre !</p>
<p>Je pense à ça car j&#8217;étais en train de lire un truc sur les martyrs qui vont au ciel accueilli par 72 vierges.</p>
<p>Arg. Tu viens de t&#8217;exploser en mille morceaux, et en plus pour te détendre t&#8217;as le choix entre 72 boulets ?</p>
<p>Ils auraient pas plutôt pu en mettre une seule bien coquine qui a connu 72 bites ? Ça m&#8217;aurait paru plus rentable comme deal.</p>
<p>Enfin, même comme ça, le sexe pour l&#8217;éternité, c&#8217;est pas fantastique comme contrat. Ok, se faire lécher les couilles, c&#8217;est sympas. Mais dans l&#8217;immense panel des expériences possibles, ça manque un chouilla de diversité pour y passer le reste de ta mort.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6562&amp;md5=34704dde0e6a067e093ae6661fe9f3ec" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6597
title: Première requête de take down pour 0bin
uri: Première-requête-de-take-down-pour-0bin
url: http://sametmax.com/premiere-requete-de-take-down-pour-0bin/
content:
<p>Vous vous souvenez, 0bin, ce <a href="http://sametmax.com/0bin-implementation-python-de-zerobin-pastebin-chiffre-cote-client/">pastebin chiffré côté client écrit en Python</a> ? Le but était de protéger, non pas l&#8217;utilisateur, mais l&#8217;hébergeur, d&#8217;une attaque en justice. La théorie est qu&#8217;il ne peut en effet être tenu de modérer ce qu&#8217;il ne peut consulter.</p>
<p>Et bien on vient de recevoir notre première demande légale de retrait de liens.</p>
<p>Petit retour sur les faits, pistes de réflexion et appel à commentaires.</p>
<h2>Le take down</h2>
<p>La demande ne nous est pas parvenue directement, ni même par notre hébergeur, mais via notre fournisseur de nom de domaine, en l’occurrence pour <a href="0bin.net">0bin.net</a>, l&#8217;américain namecheap.</p>
<p>Techniquement, nous ne sommes pas aux USA, et nos serveurs ne le sont pas non plus. Pour Max, &#8220;c&#8217;est idiot de se prendre un procès pour un site qui rapporte pas&#8221;. Moi je dirais plutôt que le risque, c&#8217;est de perdre le nom de domaine qui est quand même super cool, mais ma première réaction a plutôt été &#8220;nannnnnnn, faut pas censurer&#8221;. Au final, on quand même retiré les pastes, puisqu&#8217;ils contenaient des liens de téléchargement de contenus protégés par le droit d&#8217;auteur.</p>
<p>Voici les demandes que nous avons reçu :</p>
<blockquote><p>2.) Identify the copyrighted work claimed to have been infringed<br />
You link to this copyrighted material (music albums):</p>
<p>DANNY PRESZ &#8211; Inicio &#8211; (2013)<br />
ORQUESTA BRONKO &#038; SHAKAITO &#8211; 30 Aniversario-Homenaje &#8211; (2013)<br />
CHARLIE CRUZ &#8211; Huellas &#8211; (2013)<br />
MONGORAMA &#8211; Baila Que Baila &#8211; (2013)<br />
CONJUNTO SABROSURA &#8211; Moña Pa&#8217; Mi Bongó &#8211; (2013)<br />
V. A. &#8211; Sergio George&#8217;s Salsa Giants &#8211; (2013)<br />
Victor Manuelle &#8211; Me Llamaré Tuyo &#8211; (2013)</p>
<p>3.) Provide us the exact location of the infringing file with the exact link<br />
On your servers here (re-directing to 180upload.com):</p>
<p>http://0bin.net/paste/7eefb6647bb1e606ef95eaa219e4f2de8ef98d5a#GipoKK++q7p3t+56MQPQa7Tm50Vq3BTATm0a9CsiBE0=</p>
<p>http://0bin.net/paste/d3d3db7281b32d1d9ba4be1f0166c0e6681b7904#yuYfcO5g83WDQ7xgF8l39AhHJH4N+XfzMv6Th1IoiVo=</p>
<p>http://0bin.net/paste/4185de7d1d5acc69f149472edb6395603786e622#s22bq9IkdWlm7vajb4+ryNvQLAe79tYZqrICzaexw1E=</p>
<p>http://0bin.net/paste/df3bf3537bec0d54c1fc2d469307d91674172072#uTszh1/Om8baR/hsvWpLyMm50vgwRoRRsMkMbgVouTo=</p>
<p>http://0bin.net/paste/1cbb4a2796db7015412353e9cc6818cd16673338#spj9KqFNfCeMR/VNN5IVof4Sax9njevkcIBuesNWTmE=</p>
<p>http://0bin.net/paste/f67fd84d81bdfeb5da8a529a1064d143c8831fe6#uadJcY9uIaGbJ7oXUZ8kcXXpiktHjwkhE9XUH3TC+9U=</p>
<p>http://0bin.net/paste/a1043ecdf4fe1d1a4d55aedc5d9409f1767223ef#QaT1pCopGaxs9ZC07N+0cmVg6aRoiL9uY3GOPvuUx7w=</p>
<p>4.) Provide us the web address under which the link has been published<br />
The links are shared here in public:</p>
<p>http://bypachayo.blogspot.de/</p></blockquote>
<p>J&#8217;ai groupé les mails en un seul, mais il y en a eu 3. Notez qu&#8217;ils avaient accès aux liens avec la clé de chiffrement, puisqu&#8217;ils étaient posté publiquement sur un blog. De plus, l&#8217;identification a probablement été manuelle étant donné la nature de 0bin.</p>
<h2>L&#8217;état de 0bin</h2>
<p>0bin n&#8217;est pas un outil de lutte contre la censure ou de contournement légal. Il n&#8217;est pas armé pour le cas où la demande de take down arrive avec le lien complet, clé incluse, car il a été exposé ainsi sur le Net.</p>
<p>Il ne permet pas non plus de prévenir l&#8217;utilisateur du retrait de ses liens : tout le monde va tomber sur une 404 jusqu&#8217;à ce que l&#8217;auteur soit averti, et il ne comprendra pas ce qui s&#8217;est passé.</p>
<p>Ici, on a eu la chance d&#8217;avoir un seul blog, donc je suis allé poster un commentaire dessus pour lui expliquer la situation. Mon espagnol est un peu rouillé d&#8217;ailleurs.</p>
<p>On voit aussi que 0bin, et Internet en général, est mal compris : le mec utilisait l&#8217;outil pour poster un lien par paste, qu&#8217;il linkait ensuite sur son site. Qu&#8217;espérait-il ? Camoufler quelque chose ? A-t-il compris comment marchait le service ? A quoi il était destiné ?</p>
<p>La seule bonne nouvelle dans tout ça, c&#8217;est qu&#8217;on a rajouté un script qui supprime permet de supprimer un paste en Python.</p>
<h2>Et après ?</h2>
<p>Même si les liens étaient illégaux (d&#8217;ailleurs je n&#8217;ai aucune connaissance pour vérifier que l&#8217;injonction de retrait est elle, légale), cela fait toujours un peu chier de devoir retirer quelque chose. Cette fois, on n&#8217;a pas recopié l&#8217;information ailleurs, mais peut être qu&#8217;on aurait dû.</p>
<p>La vraie question c&#8217;est : est-ce qu&#8217;on veut ajouter des fonctionnalités de résistance contre la censure à 0bin ? Est-ce que ce but est vraiment complémentaire à l&#8217;objectif initial ? Est-ce que les utilisateurs en ont besoin ? Est-ce que ça ne va pas transformer le logiciel en un truc qui n&#8217;a rien à voir ?</p>
<p>Et si oui, que mettre en place ? De mon chapeau, j&#8217;ai déjà quelques idées :</p>
<ul>
<li>Mettre en place une instance sur Tor et faire un script ou une fonctionnalité de transfert sur celle-ci en cas de take down notice. </li>
<li>Ajouter de la réplication, et lier plusieurs instances qui se font confiance entre elles via une API.</li>
<li>Ajouter une fonctionnalité de liens périssables (temps, nombre de cliques&#8230;), pour que les gens puissent partager des liens de 0bin des pages publiques sans donner l&#8217;URL réelle.</li>
<li>Permettre un faux retrait, c&#8217;est à dire un retraire temporaire, mais les liens sont réactivés plus tard ?</li>
<li>Pouvoir protéger un paste par un mot de passe.</li>
</ul>
<p>Mais rien de tout ça ne règle le problème de notre cher fan de Danny Presz. D&#8217;ailleurs faut-il résoudre son problème ? Et si oui, est-ce le rôle de 0bin ?</p>
<p>J&#8217;ai horreur de terminer une article comme ça, ça fait vraiment pute à commentaires sur un blog cheap, mais qu&#8217;est-ce que vous en pensez ?</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6597&amp;md5=331191f51352f1c91e0220eb019f674a" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6587
title: Des idées, des idées, toujours des idées
uri: Des-idées-des-idées-toujours-des-idées
url: http://sametmax.com/des-idees-des-idees-toujours-des-idees/
content:
<pre>vendredi 5 juillet 2013
[18:37:13] Max: j'ai une idée de fou
[18:37:15] Max: simple
[18:37:19] Max: truc de malade
samedi 6 juillet 2013
[08:42:30] Sam: et je viens de recevoir ce message
[08:42:44] Sam: explique moi tout
[08:43:07] Max: mouiiii bonjour
[08:43:22] Max: tin je phosphore à mort en ce moment :)
[08:43:24] Max: plein d'idées
[08:43:30] Max: bon là l'idée de malade
[08:44:43] Sam: acouche
[08:45:38] Max: myclikz:
systeme de comptage de clicks sur les liens d'articles ou autre d'une
page, on installe un js qui comptabiliser les clicks sur les liens
présent sur la page et afficher le nb de clicks à droite du lien
(facons iphone) , stats, possibilité de faire varier la couleur du
lien si bcp de click pour donner impression de valeur,
etc...possibilité de limiter le comptage de licks à certaines url via
une classe à ajouter dans le tag a, etc...
[08:46:06] Max: ou limiter au corps du texte pour l'affichage des
minis compteurs
[08:46:11] Max: pour pas que ça polue trop
[08:46:28] Max: voire en rendre certains invisibles destinés
uniquement au webmaster pour ses stats particuliere
[08:46:36] Max: c pas une heat map hein
[08:46:40] Sam: j'ai bien compris
[08:46:49] Sam: je vois pas l'interêt, mais j'ai bien compris
[08:46:52] Max: c d'abord informé au visiteur qu'un lien a suscité une
plus grand attention
[08:47:16] Sam: c'est pour catalyser l'effet "mouton de panurge" ?
[08:47:20] Max: l'interet est que ça permet de susciter un plus grand
interet pour des liens beaucops cliqués
[08:47:24] Max: voilà
[08:47:43] Max: et le top faire changer la couleur du lien lorsqu'ils
devient brulant
[08:47:49] Sam: ou le faire grossir
[08:47:54] Max: limite mettent une flamme à côté (pas bleu marine ^^)
[08:47:57] Sam: ou clignoter
[08:47:57] Max: ouais
[08:47:59] Max: voilà
[08:48:00] Sam: avoir des flammes
[08:48:07] Sam: et des éclairs
[08:48:13] Max: le tonnerre
[08:48:14] Sam: à la fin, l'article disparait
[08:48:19] Max: chiens et chats couchants ensembles
[08:48:21] Sam: et il reste plus que le lien
[08:48:28] Max: par exemple :)
[08:48:34] Sam: tu permet que je publie ça sur le blog ?
[08:48:41] Max: heu non pas l'idée
[08:48:46] Max: elle est géniale
[08:48:51] Sam: non elle est nulle à chier
[08:48:56] Max: pffffff
[08:48:56] Sam: et on la réalisera jamais
[08:49:00] Max: t'es réfractaire
[08:49:03] Sam: comme la brique
[08:49:08] Sam: et sceptique
[08:49:11] Sam: comme la fausse
[08:49:18] Sam: mais au moins ça peu faire un bon article
[08:49:26] Sam: rien que le dialogue est marrant
[08:49:41] Max: bon vas y publie alors et demande si ça les
interresserait
[08:49:44] Max: mais bon
[08:49:47] Max: chui sur que l'idée est géniale
[08:49:51] Sam: \o/</pre>
<p>Ceci dit, les idées de Max rapportent généralement plus de pognon que les miennes.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6587&amp;md5=79edb835714d92390acdf03d9b1f7ab2" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6576
title: YAML, XML, JSON, CSV, INI… Qu’est-ce que c’est et à quoi ça sert ?
uri: YAML-XML-JSON-CSV-INI-Qu-est-ce-que-c-est-et-à-quoi-ça-se
url: http://sametmax.com/yaml-xml-json-csv-ini-quest-ce-que-cest-et-a-quoi-ca-sert/
content:
<p>Que voilà de jolis acronymes !</p>
<p>Quand j&#8217;ai débuté la programmation, je les rencontrais partout sur le net. On en parlait comme si on parlait d&#8217;acheter du pain. Apparemment c&#8217;était <a href="http://sametmax.com/bien-expliquer-quelque-chose-les-regles-de-base/">évident</a> pour tout le monde.</p>
<p>Ça m&#8217;a énervé, mais ça m&#8217;a énervé !</p>
<p>Et puis j&#8217;ai oublié. C&#8217;est devenu tellement le quotidien pour moi, tellement banal&#8230; Jusqu&#8217;à ce que je reçoive ce mail :</p>
<blockquote><p>Je viens vous quémander un article</p>
<p>Il y a une question que je me pose assez souvent avant de coder quelque chose et bien que j&#8217;ai pu me faire quelques opinions au fil du temps, je n&#8217;ai jamais trouvé un article ou une conf ou que sais-je qui explique ça clairement.</p>
<p>Ma question concerne le format d&#8217;écriture des données.<br />
Entre les fichiers textes genre ini, json, xml, yaml (que j&#8217;aime bien), les formats binaires (pickle, voir hdf5 pour les scientifiques et j&#8217;en ignore peut être d&#8217;autre&#8230;), les bases de données mysql, postgre, sqlite.</p>
<p>Je n&#8217;ai pas les idées claires sur :<br />
* cas typique d&#8217;utilisation<br />
* les plus et les moins<br />
* la corruptibilité<br />
* la sécurité (point fourre-tout)</p>
<p>En gros, mon raisonnement de béotien dit : binaire plus performant que texte mais texte lisible par l&#8217;éditeur et ça, ça rassure.</p>
<p>A prendre ou à jeter </p></blockquote>
<p>Aujourd&#8217;hui, je vais donc parler des formats texte, et je ferai un article sur les formats binaires plus tard.</p>
<h2>Formats</h2>
<p>YAML, XML, JSON, CSV, INI sont des noms de formats de données texte. Il y a plusieurs choses à comprendre ici:</p>
<dl>
<dt>Donnés : </dt>
<dd>Ca peut être n&#8217;importe quoi que vous vouliez sauvegarder ou transmettre : carnet d&#8217;adresses, configuration d&#8217;un logiciel, contenu d&#8217;une base de données, nom/prenom/age/mensurations, etc. Bref, tout groupe d&#8217;informations que vous souhaitez pourvoir communiquer, ou relire plus tard. </dd>
<dt>Format  :</dt>
<dd>Comment sont organisées ces données. Comme on manipule les données avec un ordinateur, il est nécessaire de les ranger données d&#8217;une certaine façons. En les rangeant de cette façon, l&#8217;ordinateur, si il connait le &#8220;format&#8221;, est capable d&#8217;analyser les données qu&#8217;il reçoit. Sinon pour lui elles ne veulent rien dire.</dd>
<dt>Texte : </dt>
<dd>En opposition à &#8220;binaire&#8221; (ce qui est un abus de langage, puisque du texte en informatique, c&#8217;est du binaire). Cela signifie que votre format est organisé autour d&#8217;un texte lisible par les humains. C&#8217;est ce texte qui va dire &#8220;ceci est l&#8217;age&#8221;, &#8220;ceci est le nom&#8221;, &#8220;ceci est la taille de ses ganglions&#8221;, etc.</dd>
</dl>
<p>En résumé, un format de données texte, c&#8217;est une convention textuelle pour que des ordinateurs puissent échanger des données entre eux et que celui qui reçoit puisse retrouver la même chose que ce que l&#8217;on lui a envoyé.</p>
<h2>Exemples</h2>
<p>Le format XML est une convention qui dit qu&#8217;on va mettre les données (les informations qu&#8217;on transmet) entre des balises.</p>
<p>Les balises ont la forme suivante : <code>< nomDeBalise ></ nomDeBalise ></code>.</p>
<p>Une balise peut contenir une données, ou d&#8217;autres balises.</p>
<p>Le choix des balises est laissé à la personne qui créer le XML. Celui qui reçoit le XML doit connaître ces balises pour récupérer les données.</p>
<p>Imaginez un carnet d&#8217;adresses avec chaque personne ayant un nom et un numéro de téléphone. Il existe de nombreux moyens de représenter ce carnet d&#8217;adresses. L&#8217;UN des moyens de possibles, est d&#8217;écrire un fichier XML. Par exemple :</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;utf8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;personnes<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;personne<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Sam<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;numero<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>555-555-555<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/numero<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/personne<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;personne<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Max<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;numero<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1234567890<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/numero<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/personne<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;personne<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Bob<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;numero<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>666<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/numero<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/personne<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/personnes<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>Pour vous en tant qu&#8217;humain, ça n&#8217;apporte rien.</p>
<p>Mais quand vous avez besoin de créer un programme qui peut sauvegarder / lire ces données ou les transmettre à un autre programme (car oui, les programmes doivent pourvoir se parler entre eux, comment vous croyez que cet article arrive sur votre ordinateur ?), il va falloir choisir un format pour ces données.</p>
<p>Chaque format et différent, et possède des avantages et des inconvénients. <strong>On peut très bien représenter les mêmes données avec deux formats différents.</strong> Ainsi, voici le même carnet d&#8217;adresses, mais au format CSV :</p>

<div class="wp_syntax"><div class="code"><pre class="csv" style="font-family:monospace;">&quot;nom&quot;;&quot;numero&quot;
&quot;Sam&quot;;&quot;555-555-555&quot;
&quot;Max&quot;;&quot;1234567890&quot;
&quot;Bob&quot;;&quot;666&quot;</pre></div></div>

<h2>Quel format est le meilleur ?</h2>
<p>Il n&#8217;existe pas de &#8220;meilleur&#8221; format.</p>
<p>Chaque format ac ses caractéristiques, et il existe de nombreux formats. En fait, il existe même des formats dans les formats, des XML avec des balises qui ont des noms standardisés par exemple. Pire, vous pouvez inventer vos propres formats. Mais à moins d&#8217;être très bon et de combler un besoin qui ne l&#8217;est pas encore, je ne vous le recommande pas.</p>
<p>Aussi il va vous falloir choisir un format selon votre situation. En général, on choisira parmi ces caractéristiques :</p>
<ul>
<li>Facilité de manipulation : votre code va traiter ce format, donc si c&#8217;est galère à manipuler, vous allez vous faire du travail en plus.</li>
<li>Expressivité : certains formats permettent de &#8220;dire&#8221; plus de de choses que d&#8217;autres. Selon la complexité de vos données, certains seront trop simples ou trop complexes.</li>
<li>Pérénité : combien de temps ce format doit être lisible ? Et-il un standard reconnu ? Est-il beaucoup utilisé ? Est-il ouvert ? Avez-vous le droit d&#8217;utiliser ce format (car oui, il y a des questions légales) ?</li>
<li>Performance : le temps de traitement de ce format convient-il à votre usage ? La place qu&#8217;il prend sur le disque ? En Ram ? Le temps de transfert par un réseau ?</li>
</ul>
<p>Dans notre cas, nous allons étudier des formats textes ouverts qui sont tous des standards, et lisibles par un humain. Aussi la pérénité de vos données est le moindre de vos soucis, si tant est que le créateur du format est compétent et bienveillant.</p>
<p>Dans cet article, nous allons en effet voir uniquement les formats texte. Je garderai les formats binaires pou un article suivant, et un dernier pour les bases de données.</p>
<p>Au passage, les formats textes ont tous ces caractéristiques en commun:</p>
<ul>
<li>Ils sont lisibles et modifiables facilement et avec peu de moyen par les humains.</li>
<li>On peut debugger, et même bidouiller un format texte sans trop de souci, même si on a pas de lib faite pour ça.</li>
<li>Ils sont plus lents et prennent plus de place que les formats binaires.</li>
<li>On les utilisent souvent pour les exports / imports de données, les fichiers de configurations, et dans la transmission d&#8217;informations sur le Web entre deux machines.</li>
</ul>
<p>A noter qu&#8217;au passage la sécurité et la corruptibilité ne sont pas des questions liées au format, mais à la méthode de manipulation de ces formats. Donc le choix du format ne prend pas en compte ces questions.</p>
<h2>Le format CSV</h2>
<p>L&#8217;acronyme CSV signifie Coma Separated Values, littéralement valeurs séparées par des virgules. C&#8217;est un des formats les plus simple que l&#8217;on puisse trouver.</p>
<p>Dans sa version la plus basique, c&#8217;est un format ligne à ligne, et chaque ligne représente une entrée (par exemple une personne dans un carnet d&#8217;adresses, un objet dans un catalogue, des groupes d&#8217;ingrédients dans une liste de recettes, etc).</p>
<p>Pour chaque entrée, il y a une série de valeur, chaque valeur est séparée par des virgules. Reprenons l&#8217;exemple du carnet d&#8217;adresse :</p>

<div class="wp_syntax"><div class="code"><pre class="csv" style="font-family:monospace;">sam,555-555-555,5 rue des lilas
max,1234567890,thailande
bob,666,7eme cercle</pre></div></div>

<p>Mais il peut se complexifier dès qu&#8217;on veut rajouter des valeurs plus complexes. Par exemple si elles contiennent des virgules, alors il est d&#8217;usage d&#8217;entourer les valeurs de quotes :</p>

<div class="wp_syntax"><div class="code"><pre class="csv" style="font-family:monospace;">&quot;sam&quot;,&quot;555-555-555&quot;,&quot;5, rue des lilas&quot;
&quot;max,&quot;1234567890&quot;,&quot;Patong, thailande&quot;
&quot;bob&quot;,&quot;666&quot;,&quot;7eme cercle&quot;</pre></div></div>

<p>Le séparateur (la virgule) et les quotes peuvent être aussi un point-virgule et un quote simple, et on peut avoir n&#8217;importe quelle combinaison :</p>

<div class="wp_syntax"><div class="code"><pre class="csv" style="font-family:monospace;">'sam','555-555-555','5, rue des lilas'
'max,'1234567890','Patong, thailande'
'bob','666','7eme cercle'</pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="csv" style="font-family:monospace;">'sam';'555-555-555';'5, rue des lilas'
'max;'1234567890';'Patong, thailande'
'bob';'666';'7eme cercle'</pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="csv" style="font-family:monospace;">sam;555-555-555;5, rue des lilas
max;1234567890;Patong, thailande
bob;666;7eme cercle</pre></div></div>

<p>Il existe aussi des caractères d&#8217;échappement, des exceptions de retour à la ligne, et des programmes qui produisent des lignes avec un séparateur, puis des lignes avec un autre. Autant dire que d&#8217;un format simple, on arrive parfois à quelque chose de complexe. C&#8217;est d&#8217;ailleurs pour ça que je recommande de ne pas traiter le CSV à la main, mais d&#8217;utiliser des modules spécialisés comme <a ahref="http://docs.python.org/2/library/csv.html?highlight=csv#csv">csv</a> en Python.</p>
<p>Sachez néanmoins que le format le plus courant est celui supporté par les tableurs (Excel, LibreOffice Calc&#8230;) utilisant des guillemets doubles et des point-virgules :</p>

<div class="wp_syntax"><div class="code"><pre class="csv" style="font-family:monospace;">&quot;Sam&quot;;&quot;555-555-555&quot;;&quot;5, rue des lilas&quot;
&quot;Max&quot;;&quot;1234567890&quot;;&quot;Patong, thailande&quot;
&quot;Bob&quot;;&quot;666&quot;;&quot;7eme cercle&quot;</pre></div></div>

<p>C&#8217;est donc ce format que je recommande car il est du coup très facile à lire et à modifier. Il est aussi possible de donner un nom à chaque colonne sur la première ligne :</p>

<div class="wp_syntax"><div class="code"><pre class="csv" style="font-family:monospace;">&quot;nom&quot;;&quot;numero&quot;;&quot;adresse&quot;
&quot;Sam&quot;;&quot;555-555-555&quot;;&quot;5, rue des lilas&quot;
&quot;Max&quot;;&quot;1234567890&quot;;&quot;Patong, thailande&quot;
&quot;Bob&quot;;&quot;666&quot;;&quot;7eme cercle&quot;</pre></div></div>

<p>Vous voudrez utiliser ce format quand :</p>
<ul>
<li>Vos données sont simples et facile à représentées sous forme de tableau.</li>
<li>Vous avez pas envie de vous faire chier (TRES bonne raison).</li>
<li>Il n&#8217;y a pas d&#8217;imbrication dans vos données.</li>
<li>Vos données sont statiques (pas de vérification, pas de calculs, pas de transtypage). Bref, on les lis tel quel.</li>
<li>Vous voulez que ce soit lisible dans un tableur. Pratique pour les néophytes.</li>
</ul>
<h2>Le format INI</h2>
<p>Le format INI, utilisé pour l&#8217;INItialisation, est surtout un format pour stocker des configurations de logiciel. On le trouve souvent dans des fichiers avec des paramètres, portant l&#8217;extension .ini, .cfg, .conf ou .txt.</p>
<p>Il est constitué de deux types d&#8217;élément :</p>
<ul>
<li>Les en-têtes, ou sections, qui s&#8217;écrivent [nom_de_l_en_tete]. Ils servent à nommer et délimiter des groupes de valeurs.</li>
<li>Les valeurs, qui s&#8217;écrivent nom=valeur.</li>
</ul>
<p>Les fichiers INI ne sont pas fait pour stocker des données répétitives comme des personnes d&#8217;un carnet d&#8217;adresses. Généralement, chaque entrée est unique, et représente un paramètre du programme :</p>

<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;"><span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>utilisateur<span style="">&#93;</span></span>
<span style="color: #000099;">nom</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">Sam</span>
<span style="color: #000099;">dossier</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">/home/sam</span>
&nbsp;
<span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>dernier_access<span style="">&#93;</span></span>
<span style="color: #000099;">jour</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">2013-07-06</span>
<span style="color: #000099;">fichier</span><span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;">'le_plus_dur_est_derriere_toi.avi'</span></pre></div></div>

<p>C&#8217;est un format simple à manipuler (et <a href="http://docs.python.org/2/library/configparser.html?highlight=config#ConfigParser">il existe un module Python pour ça</a>) et généralement on le lit, on modifie une valeur, et on la sauvegarde.</p>
<p>Vous voudrez utiliser ce format quand :</p>
<ul>
<li>Vous voulez sauvegarder l&#8217;état ou la configuration de votre programme.</li>
<li>Vos données sont très simples.</li>
<li>Vous êtes sous une vieille machine Windows.</li>
<li>Vous voulez <a href="http://www.vaulscastle.com/games/bg/bgcheathelp1.htm">tricher à Baldur&#8217;s Gate</a>.</li>
</ul>
<h2>Le format JSON</h2>
<p>A la base JSON, qui signifie JavaScript Object Notation, n&#8217;était pas un format destiné à être échangé, mais seulement la représentation textuelle des objets Javascript.</p>
<p>Il se trouve qu&#8217;avec l&#8217;age d&#8217;or du Web, et l&#8217;utilisation massive d&#8217;AJAX, il a été utilisé pour communiquer entre le navigateur et le serveur, et les gens se sont apperçu qu&#8217;il était en fait très très très pratique.</p>
<p>Aujourd&#8217;hui, JSON est utilisé un peu pour tout, et si vous ne savez pas trop quoi choisir comme format, choisissez JSON, il y a peu de chance de se planter.</p>
<p>Voilà à quoi ressemble le carnet d&#8217;adresses en JSON:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#91;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #3366CC;">'nom'</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">'Sam'</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">'numero'</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">'555-555-555'</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">'adresse'</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">'5, rue des lilas'</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #3366CC;">'nom'</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">'Max'</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">'numero'</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">'1234567890'</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">'adresse'</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">'Patong, thailande'</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #3366CC;">'nom'</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">'Bob'</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">'numero'</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">'666'</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">'adresse'</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">'7eme cercle'</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#93;</span></pre></div></div>

<p>JSON est extrêmement facile à manipuler de nos jours, et l&#8217;immense majorité des langages ont un module pour ça. <a href="http://docs.python.org/2/library/json.html?highlight=json#json">Python n&#8217;échappe pas à la règle</a>.</p>
<p>Il est rare que JSON soit une mauvaise idée, donc je vais plutôt faire une liste de quand vous ne voulez PAS utiliser JSON :</p>
<ul>
<li>Vos données vont être lues souvent pas des humains sans connaissance techniques (le CSV est plus adapté).</li>
<li>La plupart des systèmes qui vont lire ces données ont de mauvaises bibliothèques pour lire le JSON, mais de grosses facilités pour d&#8217;autres formats.</li>
<li>Le reste du système communique avec un autre format (pas la peine de cumuler 40000 formats).</li>
<li>Vous avez besoin de performances extrêmes (dans ce cas cherchez du côté des formats binaires).</li>
<li>Vous voulez stocker de grosses quantités de données ou faire des analyses complexes dessus (dans ces cas cherchez du côté des bases de données).</li>
<li>Il existe un standard qui correspond à votre usage qui n&#8217;est pas en JSON (ex: notifications : Utilisez RSS, qui est du XML, ou les emails, carnet d&#8217;adresses : utilisez ldif ou vcard, etc.) </li>
<li>Vos données sont très très complexes et demande un format plus riche, des vérifications automatiques, un typage avancé, etc. Préférez XML.</li>
</ul>
<p>Sinon, allez-y, prenez du JSON. On peut l&#8217;utiliser pour les fichiers de configuration (comme le fait Sublime Text), comme API pour son service (ce que font presque tous les grands services du monde), pour communiquer entre plusieurs sites Web (JSONP), pour exporter / importer ses données (fixtures Django)&#8230;</p>
<h2>Le format YAML</h2>
<p>YAML, l&#8217;humoristique &#8220;Yet Another Markup Language&#8221; est a des buts et qualités similaires au JSON, mais avec un format différent.</p>
<p>Voici le fichier INI, traduit en YAML (les espaces sont significatifs) :</p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;">---
utilisateur:
    nom: Sam
    dossier: /home/sam
&nbsp;
dernier_access:
    jour: 2013-07-06
    fichier: 'le_plus_dur_est_derriere_toi.avi'
...</pre></div></div>

<p>Le format YAML est néanmoins plus riche que le JSON:</p>
<ul>
<li>Il permet d&#8217;inclure plusieurs document dans un seul fichier en les séparant par <code>---</code></li>
<li>Il contient des types avancés comme la data.</li>
<li>Il possède plusieurs manière d&#8217;écrire les textes multilignes</li>
</ul>
<p>Globalement le YAML a été créé pour être facilement lisible et éditable par un humain, et pour cette raison la communauté Ruby l&#8217;a adopté pour ses fichiers de configuration. On retrouve donc YAML dans RubyOnRail.</p>
<p>Utilisez YAML quand :</p>
<ul>
<li>Votre fichier est destiné à être aussi souvent lu par une machine qu&#8217;un humain et contient des types complexes.</li>
<li>Vous êtes dans un environnement Ruby (à Rome&#8230;).</li>
</ul>
<p>Contrairement à JSON, on utilisera donc plus YAML pour la configuration que l&#8217;envoie de données.</p>
<p>Personnellement je ne suis pas un aficionado de YAML. Mon expérience est que sa syntaxe complexe (j&#8217;admet que l&#8217;exemple ne le laisse pas paraitre) amène souvent des grattements de tête suite à une édition malheureuse. Frustrant pour un simple fichier de config.. De plus, il faut souvent installer <a href="https://pypi.python.org/pypi/pyaml/13.07.0">une lib additionnelle</a> pour le lire. Par ailleurs, JSON &#8211; qui est en fait un subset de YAML &#8211; fait généralement très bien le boulot.</p>
<h2>Le format XML</h2>
<p>La fameux eXtensible Markup Language. Je ne vais pas vous faire un cours complet sur XML, car on pourrait y passer des mois, au sens propre. Ce format, aux apparences simples, a été utilisé pour des choses extrêmement complexes.</p>
<p>Revenons à notre exemple :</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;utf8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;personnes<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;personne<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Sam<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;numero<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>555-555-555<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/numero<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/personne<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;personne<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Max<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;numero<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1234567890<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/numero<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/personne<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;personne<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Bob<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;numero<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>666<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/numero<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/personne<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/personnes<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p><code>< ?xml version="1.0" encoding="utf8"? ></code> est l&#8217;en-tête du fichier, il annonce quel format de XML on va utiliser, le reste est le contenu.</p>
<p>Ici nous n&#8217;avons que quelques balises, mais bien entendu, les balises peuvent contenir des balises qui peuvent contenir des balises&#8230; En prime, XML autorise des attributs (nom=&#8221;valeur&#8221;), c&#8217;est à dire des valeurs sur les balises qui modifient la signification de celle-ci. Par exemple :</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;">...
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;personne<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Bob<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;numero</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;shortcode&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>666<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/numero<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/personne<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
...</pre></div></div>

<p>Enfin, XML permet ce qu&#8217;on appelle des namespaces, afin de dire que les balises correspondent à un dialecte et pas un autre.</p>
<p>Exemple, j&#8217;ai deux fois nom dans ce XML :</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;utf8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;personnes<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;personne<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Sam<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;numero<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>555-555-555<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/numero<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;ville<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Metro peau lisse<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;coord<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>3.14,6.56<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/coord<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/ville<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/personne<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;personne<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Max<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;numero<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1234567890<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/numero<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;ville<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Patong<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;coord<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>4.2,6.9<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/coord<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/ville<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/personne<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;personne<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Bob<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;numero<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>666<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/numero<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;ville<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Sodome<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;coord<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>-12,-13<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/coord<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/ville<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/personne<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/personnes<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>Comment savoir pour ma machine ce que signifie, &#8220;nom&#8221; ?</p>
<p>Et bien je peux les namespacer, c&#8217;est à dire les lier à une URL qui pointe vers la documentation qui dit ce que signifie chaque balise, ou au moins le site de l&#8217;auteur du XML.</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;utf8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;personnes</span> <span style="color: #000066;">xmlns:sm</span>=<span style="color: #ff0000;">&quot;http://sametmax.com&quot;</span> <span style="color: #000066;">xmlns:osm</span>=<span style="color: #ff0000;">&quot;http://openstreetmap.org&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sm:personne<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sm:nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Sam<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sm:nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sm:numero<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>555-555-555<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sm:numero<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sm:ville<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;osm:nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Metro peau lisse<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/osm:nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;osm:coord<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>3.14,6.56<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/osm:coord<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sm:ville<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sm:personne<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sm:personne<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sm:nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Max<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sm:nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sm:numero<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1234567890<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sm:numero<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sm:ville<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;osm:nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Patong<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/osm:nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;osm:coord<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>4.2,6.9<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/osm:coord<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sm:ville<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sm:personne<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sm:personne<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sm:nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Bob<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sm:nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sm:numero<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>666<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sm:numero<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sm:ville<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;osm:nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Sodome<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/osm:nom<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;osm:coord<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>-12,-13<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/osm:coord<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sm:ville<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sm:personne<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/personnes<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>Et si on veut se marrer un peu plus, on peut utiliser ce qu&#8217;on appelle des DTD (ou le format plus moderne XSD) : un XML, qui définit comment doit être formé un autre XML et qui permet de vérifier cela automatiquement. Il existe également un format appelé XSLT, qui permet de définir, en XML, comment transformer un autre document XML, en un document dans un troisième format de votre choix.</p>
<p>Bref, le XML peut devenir très très compliqué. Si compliqué en fait, que des formats en XML, même avec leurs spécifications, <a href="http://ooxmlisdefectivebydesign.blogspot.fr/">deviennent difficiles à lire</a>.</p>
<p>XML a été historiquement le premier format texte à être souple, extensible et interopérable. Aussi a-t-il été longtemps un format de choix pour communiquer entre machines et pour sauvegarder les configurations complexes. Aujourd&#8217;hui, sa verbosité et sa complexité ont amener les gens à se tourner massivement vers JSON, et XML n&#8217;est maintenant plus utilisé que pour les données très riches ou des raisons historiques (RSS, SOAP, etc).</p>
<p>Il reste un terrain où XML brille, c&#8217;est la validation de données. En effet, grâce au DTD / XSD, on peut publier un document qui permet à tout langage avec <a href="https://pypi.python.org/pypi/pyxsd/0.1">la bibliothèque appropriée</a>, de vérifier si un XML est valide, comme un formulaire. On publie les besoins de validation une fois, et plein de langages peuvent en faire usage. C&#8217;est un vrai plus.</p>
<p>Je recommande rarement d&#8217;utiliser XML, c&#8217;est lourd, difficile à manipuler (malgré un très <a href="http://docs.python.org/2/library/xml.etree.elementtree.html?highlight=xml#xml.etree.ElementTree">bon support général</a> de la plupart des langages), verbeux&#8230; Difficile à un débutant de mettre les mains dans votre système quand la courbe d&#8217;apprentissage est aussi hardos.</p>
<p>Utilisez XML si :</p>
<ul>
<li>Un des dialectes XML correspond à un standard pour votre usage (RSS / Atom).</li>
<li>Vous visez des systèmes qui utilisent historiquement XML : serveurs SOAP, environnement Java&#8230;</li>
<li>La validation des données est importante et elles seront lues par de multiples langages.</li>
</ul>
<h2>Maintenance, versioning, documentation</h2>
<p>Ce n&#8217;est pas le tout de choisir un format, il faut maintenant s&#8217;assurer qu&#8217;on puisse l&#8217;utiliser.</p>
<p>Car mettre des labels à ses données, c&#8217;est bien beau, mais si le mec qui reçoit vos données ne sait pas ce que signifie ces labels, il ne peut rien en faire.</p>
<p>Il va donc falloir écrire une documentation pour cela. Et oui, on ne documente pas seulement son code, mais aussi ses formats !</p>
<p>Je vous invite aussi fortement à versionner vos formats, c&#8217;est à dire à toujours accompagner vos données (dans le fichier, via le protocole d&#8217;échange, ou dans le changelog de votre application) d&#8217;un numéro de version, ceci afin que les utilisateurs / développeurs / admin système ne se retrouvent pas couillonnés quand vous décider de modifier un peu votre format.</p>
<p>Sur le long terme, comme les commentaires de code, cela va vous aider vous. Mais cela rendra aussi votre projet plus accessible et attirant pour les gens de l&#8217;extérieur, ou tout simplement vos collègues.</p>
<p>En écrivant cela je viens de m’apercevoir que l&#8217;on a rien fait de tout cela pour <a href="https://github.com/sametmax/0bin/tree/master/zerobin">0bin</a>. La honte&#8230;</p>
<p>Prochainement, <a href="http://sametmax.com/plist-pickle-hdf5-protocol-buffer-les-formats-binaires/">les formats binaires</a>.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6576&amp;md5=f30b763391729c9215a267cd0e84cd93" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6569
title: Vous n’avez pas besoin de l’utilisateur lambda
uri: Vous-n-avez-pas-besoin-de-l-utilisateur-lambda
url: http://sametmax.com/vous-navez-pas-besoin-de-lutilisateur-lambda/
content:
<p>Cet article va à l&#8217;encontre de beaucoup de choses que l&#8217;on a dit sur le blog. Ce n&#8217;est pourtant pas une contradiction, simplement l&#8217;énoncé d&#8217;une réalité à plusieurs facettes.</p>
<p>D&#8217;un côté, on vous a dit et martelé d&#8217;arrêter de faire vos geeks. De vous rapprocher un peu plus des utilisateurs lambda. Parce que ce sont eux qui paient votre salaire. Parce qu&#8217;<a href="http://sametmax.com/il-ne-faut-pas-prendre-des-gens-pour-des-cons-mais-ne-jamais-oublier-quils-en-sont/">ils représentent le monde réel</a>, pas celui de vos fantasmes nerds. Et c&#8217;est toujours vrai.</p>
<p>Aujourd&#8217;hui, je viens vous dire l&#8217;inverse.</p>
<p>Vous n&#8217;avez pas besoin d&#8217;eux.</p>
<p>Et c&#8217;est aussi vrai.</p>
<p>Internet est né et a grandi grâce à une minorité de marginaux, c&#8217;est seulement ensuite que se sont greffées toutes les Mme Michu. Il n&#8217;y a jamais eu besoin d&#8217;elles pour exister. Bien entendu, son ampleur actuelle est liée à l&#8217;arrivée du main stream.</p>
<p>Mais vous n&#8217;avez pas besoin de l&#8217;ampleur actuelle du réseau pour avoir un impact.</p>
<p>Des technologies comme Linux, PHP, ou HTML ont commencé par concerner peu de personnes, avec peu de moyens, et ont eu une influence majeure sur la Terre entière. Aujourd&#8217;hui, d&#8217;autres technos ou groupes tels que <a href="http://sametmax.com/quest-ce-que-bitcoin/">Bitcoin</a>, Wikileak, Anonymous, Tor, etc. concernent un minorité de gens mais ont un potentiel de provoquer des ruptures dans notre société.</p>
<p>Tout ça pour dire qu&#8217;à votre niveau, et en visant uniquement les geeks, vous pouvez avoir un impact majeur.</p>
<p>D&#8217;ailleurs, même sans viser des effets de grande magnitude, ce que vous allez faire, si c&#8217;est utile à un échantillon de la population, aura des conséquences positives.</p>
<p>Aussi le message du jour est : ne vous souciez pas de savoir si ce que vous faites ne servira pas à monsieur tout-le-monde. OSEF si &#8220;personne n&#8217;utilise le RSS&#8221;, &#8220;le chiffrement c&#8217;est compliqué&#8221;, &#8220;il a trop à lire&#8221; ou tout ce qui peut se résumer ça &#8220;cela demande un effort pour le danseur de lambada&#8221;.</p>
<p>Faites le truc comme vous le sentez.</p>
<p>Bien sûr, si un jour vous voulez faire de l&#8217;argent, ou tout simplement vous assurer de propager les bénéfices de ce que vous faites à un panel plus large d&#8217;utilisateurs, alors il faudra simplifier, amputer, réduire&#8230;</p>
<p>Cependant, tout n&#8217;a pas besoin de viser le grand public. Vous pouvez faire quelque chose qui vise uniquement les geeks, maintenant, et pour toujours. Ils seront toujours là. Et ils ont <strong>besoin</strong> de choses faites pour eux, comme tout le monde.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6569&amp;md5=b1a2c8a3cf266a273e23a0445b3f2122" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6604
title: La Joconde n’est autre qu’un Ladyboy
uri: La-Joconde-n-est-autre-qu-un-Ladyboy
url: http://sametmax.com/la-joconde-nest-autre-quun-ladyboy/
content:
<p>Ces derniers jours, marqueurs véritables d&#8217;une productivité fulgurante de ma part m&#8217;ont ammené à me perdre sur Youtube.</p>
<p>En me baladant de documentaires en documentaires, sur la reproduction asexuée des anémones de mer à la dance tribale des papous d&#8217;océanie entre autre.<br />
Je suis tombé sur un reportage qui présente Leonardounet non pas comme le super peintre que l&#8217;on connait mais sous une autre facette (en fait plusieurs mais celle-là est chouette).</p>
<p>Une théorie nous apprend que la Joconde serait Salai, le petit garçon amant de notre cher Leonard.</p>
<p><strong>En fait si vous ne voulez pas vous taper le doc en entier je vous fais illico presto la synthèse:</strong></p>
<p>Leonard De Vinci serait donc un pédophile d&#8217;1m95 qui a peint à 2 reprises son gentil petit garçon de joie dont une sous les traits de la Joconde, organisait des sodomies festives avec ses potes et collectionnait les mecs.</p>
<p>Des millions de personnes l&#8217;admirent, le vénèrent de part le monde, ses reliques se vendent des millions et on me dit que je suis dégueulasse quand je met le doigt dans mon nez.</p>
<p>C&#8217;était la minute inutile de Max. Bonne journée.</p>
<p>PS: On comprend mieux comment lui est venue l&#8217;idée d&#8217;<a href="media/92a76639.submarines-gay.jpg" data-original-source="http://uicmuntestingserver.goonygoon.com/pluckbuffet/wordpress/wp-content/uploads/2012/03/submarines-gay.jpg">inventer le sous-marin</a></p>
<p><span style="text-align:center; display: block;"><a href="http://sametmax.com/la-joconde-nest-autre-quun-ladyboy/"><img src="media/bb352e12.2.jpg" data-original-source="http://img.youtube.com/vi/SWHMDd5BAe0/2.jpg" alt="" /></a></span></p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6604&amp;md5=5593d142785bb9c3476c1107be249cda" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6620
title: Ceci n’est pas un benchmark…
uri: Ceci-n-est-pas-un-benchmark
url: http://sametmax.com/ceci-nest-pas-un-benchmark/
content:
<p>&#8230; mais quand même. Il va falloir sérieusement étudier le passage de nos sites à pypy.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ pypy <span style="color: #660033;">--version</span>
Python 2.7.2 <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">1.8</span>+dfsg-<span style="color: #000000;">2</span>, Feb <span style="color: #000000;">19</span> <span style="color: #000000;">2012</span>, <span style="color: #000000;">19</span>:<span style="color: #000000;">18</span>:08<span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span>PyPy 1.8.0 with GCC 4.6.2<span style="color: #7a0874; font-weight: bold;">&#93;</span>
&nbsp;
$ <span style="color: #c20cb9; font-weight: bold;">date</span>; pypy <span style="color: #660033;">-c</span> <span style="color: #ff0000;">&quot;for x in xrange(1000000000): pass&quot;</span>; <span style="color: #c20cb9; font-weight: bold;">date</span>
mardi <span style="color: #000000;">9</span> juillet <span style="color: #000000;">2013</span>, <span style="color: #000000;">12</span>:<span style="color: #000000;">30</span>:<span style="color: #000000;">58</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>UTC+0200<span style="color: #7a0874; font-weight: bold;">&#41;</span>
mardi <span style="color: #000000;">9</span> juillet <span style="color: #000000;">2013</span>, <span style="color: #000000;">12</span>:<span style="color: #000000;">31</span>:09 <span style="color: #7a0874; font-weight: bold;">&#40;</span>UTC+0200<span style="color: #7a0874; font-weight: bold;">&#41;</span>
&nbsp;
$ python <span style="color: #660033;">--version</span>
Python 2.7.3
&nbsp;
$ <span style="color: #c20cb9; font-weight: bold;">date</span>; python <span style="color: #660033;">-c</span> <span style="color: #ff0000;">&quot;for x in xrange(1000000000): pass&quot;</span>; <span style="color: #c20cb9; font-weight: bold;">date</span>
mardi <span style="color: #000000;">9</span> juillet <span style="color: #000000;">2013</span>, <span style="color: #000000;">12</span>:<span style="color: #000000;">31</span>:<span style="color: #000000;">16</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>UTC+0200<span style="color: #7a0874; font-weight: bold;">&#41;</span>
mardi <span style="color: #000000;">9</span> juillet <span style="color: #000000;">2013</span>, <span style="color: #000000;">12</span>:<span style="color: #000000;">32</span>:<span style="color: #000000;">49</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>UTC+0200<span style="color: #7a0874; font-weight: bold;">&#41;</span></pre></div></div>

 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6620&amp;md5=9dc36dfc08c48d62f56763aba82325eb" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6624
title: Créer un décorateur à la volée
uri: Créer-un-décorateur-à-la-volée
url: http://sametmax.com/creer-un-decorateur-a-la-volee/
content:
<p>Sur les décorateurs, normalement, vous avez <a href="http://sametmax.com/comprendre-les-decorateurs-python-pas-a-pas-partie-1/">tout ce qu&#8217;il faut</a> pour être au point.</p>
<p>Néanmoins en informatique la moitié de la connaissance, c&#8217;est l&#8217;usage, pas la fonctionnalité. Car il y beaucoup d&#8217;usages auxquels on ne pense pas.</p>
<p>Particulièrement, je vous avais déjà expliqué que les fonctions étaient des objets comme les autres en Python, et qu&#8217;on pouvait donc les créer à la volée, les retourner, les passer en paramètre, et même leur coller des attributs.</p>
<p>Or les décorateurs ne sont jamais que des fonctions.</p>
<p>Maintenant, souvenez vous, le décorateurs <a href="http://sametmax.com/le-guide-ultime-et-definitif-sur-la-programmation-orientee-objet-en-python-a-lusage-des-debutants-qui-sont-rassures-par-les-textes-detailles-qui-prennent-le-temps-de-tout-expliquer-partie-2/">property</a> permet de faire ceci :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Mamouth<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
    _valeur = <span style="color: #483d8b;">&quot;3 calots&quot;</span>
&nbsp;
    @<span style="color: #008000;">property</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> valeur<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>._valeur.<span style="color: black;">upper</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    @valeur.<span style="color: black;">setter</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> valeur<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, valeur<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>._valeur = valeur.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> bille = Mamouth<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> bille.<span style="color: black;">valeur</span>
u<span style="color: #483d8b;">'3 CALOTS'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> bille.<span style="color: black;">valeur</span> = <span style="color: #483d8b;">&quot;une pépite           &quot;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> bille.<span style="color: black;">valeur</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>bille.<span style="color: black;">valeur</span><span style="color: black;">&#41;</span>
UNE PÉPITE</pre></div></div>

<p>La syntaxe qui doit attirer votre attention est <code>@valeur.setter</code>. En effet, d&#8217;où vient ce décorateur ?</p>
<p>On comprend mieux ce qui s&#8217;est passé avec ce test :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> Mamouth.<span style="color: black;">valeur</span>.<span style="color: black;">setter</span>
<span style="color: #66cc66;">&lt;</span>built-<span style="color: #ff7700;font-weight:bold;">in</span> method setter of <span style="color: #008000;">property</span> <span style="color: #008000;">object</span> at 0x1a1baf8<span style="color: #66cc66;">&gt;</span></pre></div></div>

<p><code>setter</code> est tout simplement un attribut de la méthode <code>valeur</code>. Par ailleurs, c&#8217;est une fonction et un décorateur.</p>
<p>Pourquoi faire cela ? Et bien tout simplement parce que cela permet d&#8217;attacher une fonction qui ne sert que dans un cas (ici ça ne sert qu&#8217;à créer le setter de la propriété <code>valeur</code>) à son contexte.</p>
<p>Bien entendu vous pouvez faire ça vous même, il suffit de le vouloir très fort et de croire en le pouvoir de l&#8217;amour.</p>
<p>Par exemple, imaginez un décorateur qui permet d&#8217;attacher un comportement de sérialisation à une fonction. On ne veut pas modifier la fonction, mais on veut qu&#8217;elle puisse automatiquement, pour quelques caractères de plus, pouvoir aussi retourner du JSON ou du pickle.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> json
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">pickle</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> serializable<span style="color: black;">&#40;</span>func<span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;"># Contrairement à la plupart des décorateurs, on ne va pas retourner</span>
    <span style="color: #808080; font-style: italic;"># un wrapper, mais bien la fonction originale. Simplement on lui aura ajouté</span>
    <span style="color: #808080; font-style: italic;"># des attributs</span>
&nbsp;
    func.<span style="color: black;">as_json</span> = <span style="color: #ff7700;font-weight:bold;">lambda</span> <span style="color: #66cc66;">*</span>a, <span style="color: #66cc66;">**</span>k: json.<span style="color: black;">dumps</span><span style="color: black;">&#40;</span>func<span style="color: black;">&#40;</span><span style="color: #66cc66;">*</span>a, <span style="color: #66cc66;">**</span>k<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    func.<span style="color: black;">as_pickle</span> = <span style="color: #ff7700;font-weight:bold;">lambda</span> <span style="color: #66cc66;">*</span>a, <span style="color: #66cc66;">**</span>k: <span style="color: #dc143c;">pickle</span>.<span style="color: black;">dumps</span><span style="color: black;">&#40;</span>func<span style="color: black;">&#40;</span><span style="color: #66cc66;">*</span>a, <span style="color: #66cc66;">**</span>k<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> func</pre></div></div>

<p>Et ça s&#8217;utilise ainsi :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">locale</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">calendar</span> <span style="color: #ff7700;font-weight:bold;">import</span> TimeEncoding, day_name, day_abbr
&nbsp;
<span style="color: #808080; font-style: italic;"># obtenir les noms de jours localisés est complètement rocambolesque en python</span>
<span style="color: #ff7700;font-weight:bold;">def</span> get_day_name<span style="color: black;">&#40;</span>day_number, <span style="color: #dc143c;">locale</span>, short=<span style="color: #008000;">False</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
        Retourne le nom d'un jour dans la locale sélectionnée.
&nbsp;
        Exemple :
&nbsp;
        &gt;&gt;&gt; get_day_name(0,  ('fr_FR', 'UTF-8'))
        'lundi'
    &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">with</span> TimeEncoding<span style="color: black;">&#40;</span><span style="color: #dc143c;">locale</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> encoding:
        s = day_abbr<span style="color: black;">&#91;</span>day_number<span style="color: black;">&#93;</span> <span style="color: #ff7700;font-weight:bold;">if</span> short <span style="color: #ff7700;font-weight:bold;">else</span> day_name<span style="color: black;">&#91;</span>day_number<span style="color: black;">&#93;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> s.<span style="color: black;">decode</span><span style="color: black;">&#40;</span>encoding<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> encoding <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">None</span> <span style="color: #ff7700;font-weight:bold;">else</span> s
&nbsp;
@serializable
<span style="color: #ff7700;font-weight:bold;">def</span> get_days_names<span style="color: black;">&#40;</span><span style="color: #dc143c;">locale</span>=<span style="color: #dc143c;">locale</span>.<span style="color: black;">getdefaultlocale</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, short=<span style="color: #008000;">False</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
        Un dictionnaire contenant un mapping entre les numéros des jours
        de semaine et leurs noms selon la locale donnée.
    &quot;&quot;&quot;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#123;</span>i: get_day_name<span style="color: black;">&#40;</span>i, <span style="color: #dc143c;">locale</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">xrange</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">7</span><span style="color: black;">&#41;</span><span style="color: black;">&#125;</span></pre></div></div>

<p>En usage ordinaire, la fonction retourne bien ce qui est prévu :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> get_days_names<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#123;</span><span style="color: #ff4500;">0</span>: <span style="color: #483d8b;">'lundi'</span>, <span style="color: #ff4500;">1</span>: <span style="color: #483d8b;">'mardi'</span>, <span style="color: #ff4500;">2</span>: <span style="color: #483d8b;">'mercredi'</span>, <span style="color: #ff4500;">3</span>: <span style="color: #483d8b;">'jeudi'</span>, <span style="color: #ff4500;">4</span>: <span style="color: #483d8b;">'vendredi'</span>, <span style="color: #ff4500;">5</span>: <span style="color: #483d8b;">'samedi'</span>, <span style="color: #ff4500;">6</span>: <span style="color: #483d8b;">'dimanche'</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> get_days_names<span style="color: black;">&#40;</span><span style="color: #dc143c;">locale</span>=<span style="color: black;">&#40;</span><span style="color: #483d8b;">'en_US'</span>, <span style="color: #483d8b;">'UTF-8'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#123;</span><span style="color: #ff4500;">0</span>: <span style="color: #483d8b;">'Monday'</span>, <span style="color: #ff4500;">1</span>: <span style="color: #483d8b;">'Tuesday'</span>, <span style="color: #ff4500;">2</span>: <span style="color: #483d8b;">'Wednesday'</span>, <span style="color: #ff4500;">3</span>: <span style="color: #483d8b;">'Thursday'</span>, <span style="color: #ff4500;">4</span>: <span style="color: #483d8b;">'Friday'</span>, <span style="color: #ff4500;">5</span>: <span style="color: #483d8b;">'Saturday'</span>, <span style="color: #ff4500;">6</span>: <span style="color: #483d8b;">'Sunday'</span><span style="color: black;">&#125;</span></pre></div></div>

<p>Mais on peut choisir le format à la sortie :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> get_days_names.<span style="color: black;">as_json</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'{&quot;0&quot;: &quot;lundi&quot;, &quot;1&quot;: &quot;mardi&quot;, &quot;2&quot;: &quot;mercredi&quot;, &quot;3&quot;: &quot;jeudi&quot;, &quot;4&quot;: &quot;vendredi&quot;, &quot;5&quot;: &quot;samedi&quot;, &quot;6&quot;: &quot;dimanche&quot;}'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> get_days_names.<span style="color: black;">as_pickle</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">locale</span>=<span style="color: black;">&#40;</span><span style="color: #483d8b;">'en_US'</span>, <span style="color: #483d8b;">'UTF-8'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">&quot;(dp0<span style="color: #000099; font-weight: bold;">\n</span>I0<span style="color: #000099; font-weight: bold;">\n</span>S'Monday'<span style="color: #000099; font-weight: bold;">\n</span>p1<span style="color: #000099; font-weight: bold;">\n</span>sI1<span style="color: #000099; font-weight: bold;">\n</span>S'Tuesday'<span style="color: #000099; font-weight: bold;">\n</span>p2<span style="color: #000099; font-weight: bold;">\n</span>sI2<span style="color: #000099; font-weight: bold;">\n</span>S'Wednesday'<span style="color: #000099; font-weight: bold;">\n</span>p3<span style="color: #000099; font-weight: bold;">\n</span>sI3<span style="color: #000099; font-weight: bold;">\n</span>S'Thursday'<span style="color: #000099; font-weight: bold;">\n</span>p4<span style="color: #000099; font-weight: bold;">\n</span>sI4<span style="color: #000099; font-weight: bold;">\n</span>S'Friday'<span style="color: #000099; font-weight: bold;">\n</span>p5<span style="color: #000099; font-weight: bold;">\n</span>sI5<span style="color: #000099; font-weight: bold;">\n</span>S'Saturday'<span style="color: #000099; font-weight: bold;">\n</span>p6<span style="color: #000099; font-weight: bold;">\n</span>sI6<span style="color: #000099; font-weight: bold;">\n</span>S'Sunday'<span style="color: #000099; font-weight: bold;">\n</span>p7<span style="color: #000099; font-weight: bold;">\n</span>s.&quot;</span></pre></div></div>

<p>Ici, on a attacher une fonction à une autre fonction, en mettant la deuxième dans un attribut de la première.</p>
<p>Comme les décorateurs sont des fonctions, rien ne vous empêche de faire pareil avec un décorateur, et c&#8217;est de cette manière que <code>@property</code> attache un décorateur <code>setter</code> à chaque méthode.</p>
<hr />
<a href="https://github.com/sametmax/codes-des-articles/blob/master/2013/juillet/functions_as_functions_attributes.py"><br />
Télécharger le code des articles</a></p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6624&amp;md5=0fbef2eeec16925d51aa13c0acb911c6" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6634
title: Fichiers temporaires avec tempfile en Python
uri: Fichiers-temporaires-avec-tempfile-en-Python
url: http://sametmax.com/fichiers-temporaires-avec-tempfile-en-python/
content:
<p>Il est de ces petits modules qui sont tout simples et bien pratiques. Et la lib standard de Python en regorge. Aujourd&#8217;hui (cette nuit, ce matin, choisissez votre référentiel, pour moi c&#8217;est le petit dej), on va voir le module <code>tempfile</code>.</p>
<p>Il permet de manipuler des fichiers et dossiers &#8211; qui après tout sont des fichiers &#8211; temporaires, c&#8217;est à dire jetable, en quelque sorte.</p>
<p>Donc :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">tempfile</span></pre></div></div>

<h2>Dossier temporaire</h2>
<p>La fonction la plus simple permet d&#8217;obtenir le dossier de l&#8217;OS dans lequel on met généralement les fichiers temporaires, comme par exemple <em>C:\TEMP</em>, <em>C:\TMP</em>, <em>/tmp</em>, <em>/var/tmp</em>, ou <em>/usr/tmp</em> selon la machine, l&#8217;OS, les variables d&#8217;environnement. Sur ma machine :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">tempfile</span>.<span style="color: black;">gettempdir</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'/tmp'</span></pre></div></div>

<p>Si vous avez juste besoin d&#8217;un dossier temporaire dans lequel travailler :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">tempfile</span>.<span style="color: black;">mkdtemp</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'/tmp/tmps01VJw'</span></pre></div></div>

<p>Il va être créé et sera accessible en lecture et écriture pour l&#8217;utilisateur qui l&#8217;a créé (permissions 700 sous Linux par exemple). Le chemin est retourné sous forme de string, à charge de votre programme de le supprimer, ou laisser l&#8217;OS s&#8217;en charger naturellement au prochain reboot.</p>
<h2>Fichier temporaire</h2>
<p>Il existe plusieurs manière de créer un fichier temporaire avec ce module, mais je vous invite à utiliser principalement :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> f = <span style="color: #dc143c;">tempfile</span>.<span style="color: black;">NamedTemporaryFile</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> f
<span style="color: #66cc66;">&lt;</span>open <span style="color: #008000;">file</span> <span style="color: #483d8b;">'&lt;fdopen&gt;'</span>, mode <span style="color: #483d8b;">'w+b'</span> at 0x1b7fc00<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> f.<span style="color: black;">name</span>
<span style="color: #483d8b;">'/tmp/tmp0FxO_c'</span></pre></div></div>

<p>C&#8217;est la méthode la plus simple et la plus passe-partout. Vous pouvez oublier <code>mktemp()</code>, <code>mkstemp()</code>, <code>TemporaryFile()</code>, etc. Le fichier est automatiquement supprimé quand vous appelez <code>close()</code> dessus, à moins de passer <code>False</code> via le paramètre <code>delete</code>.</p>
<p>Au passage vous pouvez influencer le nom du fichier résultant en passant <code>prefix</code>, <code>suffix</code>, et <code>dir</code> en arguments.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">tempfile</span>.<span style="color: black;">NamedTemporaryFile</span><span style="color: black;">&#40;</span>prefix=<span style="color: #483d8b;">'~'</span><span style="color: black;">&#41;</span>.<span style="color: black;">name</span>
u<span style="color: #483d8b;">'/tmp/~XAoApc'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">tempfile</span>.<span style="color: black;">NamedTemporaryFile</span><span style="color: black;">&#40;</span>suffix=<span style="color: #483d8b;">&quot;tmp&quot;</span><span style="color: black;">&#41;</span>.<span style="color: black;">name</span>
u<span style="color: #483d8b;">'/tmp/tmpbirE0Jtmp'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">tempfile</span>.<span style="color: black;">NamedTemporaryFile</span><span style="color: black;">&#40;</span>suffix=<span style="color: #483d8b;">&quot;.tmp&quot;</span><span style="color: black;">&#41;</span>.<span style="color: black;">name</span>
u<span style="color: #483d8b;">'/tmp/tmpm4iHXE.tmp'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">tempfile</span>.<span style="color: black;">NamedTemporaryFile</span><span style="color: black;">&#40;</span><span style="color: #008000;">dir</span>=<span style="color: #483d8b;">&quot;/home/sam/.tmp&quot;</span><span style="color: black;">&#41;</span>.<span style="color: black;">name</span>
u<span style="color: #483d8b;">'/home/sam/.tmp/tmpHfwhQI'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">tempfile</span>.<span style="color: black;">NamedTemporaryFile</span><span style="color: black;">&#40;</span><span style="color: #008000;">dir</span>=<span style="color: #483d8b;">&quot;/home/sam/.tmp&quot;</span><span style="color: black;">&#41;</span>.<span style="color: black;">name</span></pre></div></div>

<p><code>mode</code> et <code>bufsize</code> sont aussi disponibles, et seront relayés à <code>file()</code> sous le capot.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">tempfile</span>.
<span style="color: #dc143c;">tempfile</span>.<span style="color: black;">NamedTemporaryFile</span>    <span style="color: #dc143c;">tempfile</span>.<span style="color: black;">TMP_MAX</span>               <span style="color: #dc143c;">tempfile</span>.<span style="color: black;">gettempdir</span>            <span style="color: #dc143c;">tempfile</span>.<span style="color: black;">mkdtemp</span>               <span style="color: #dc143c;">tempfile</span>.<span style="color: black;">mktemp</span>                <span style="color: #dc143c;">tempfile</span>.<span style="color: black;">template</span>
<span style="color: #dc143c;">tempfile</span>.<span style="color: black;">SpooledTemporaryFile</span>  <span style="color: #dc143c;">tempfile</span>.<span style="color: black;">TemporaryFile</span>         <span style="color: #dc143c;">tempfile</span>.<span style="color: black;">gettempprefix</span>         <span style="color: #dc143c;">tempfile</span>.<span style="color: black;">mkstemp</span>               <span style="color: #dc143c;">tempfile</span>.<span style="color: black;">tempdir</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">tempfile</span>.<span style="color: black;">get</span>
<span style="color: #dc143c;">tempfile</span>.<span style="color: black;">gettempdir</span>     <span style="color: #dc143c;">tempfile</span>.<span style="color: black;">gettempprefix</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">tempfile</span>.<span style="color: black;">gettempdir</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'/tmp'</span></pre></div></div>

<p>Une dernière astuce qui ne m&#8217;a jamais servi : <code>tempfile.SpooledTemporaryFile(max_size=X)</code>. Similaire à <code>NamedTemporaryFile</code>, mais le fichier est uniquement en mémoire, et sera transformé en un fichier sur le disque si sa taille dépasse X octets. <code>StringIO</code> est utilisé pour la partie en RAM.</p>
<p>Le fait de demander son file descriptor (l&#8217;entier qui représente le fichier pour le programme) le fait aussi passer en mode &#8220;sur le disque&#8221; :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> a = <span style="color: #dc143c;">tempfile</span>.<span style="color: black;">SpooledTemporaryFile</span><span style="color: black;">&#40;</span>max_size=<span style="color: #ff4500;">10000</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> a.<span style="color: black;">name</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&lt;ipython-input-43-c0a6f6c60584&gt;&quot;</span>, line <span style="color: #ff4500;">1</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #66cc66;">&lt;</span>module<span style="color: #66cc66;">&gt;</span>
    a.<span style="color: black;">name</span>
  File <span style="color: #483d8b;">&quot;/usr/lib/python2.7/tempfile.py&quot;</span>, line <span style="color: #ff4500;">569</span>, <span style="color: #ff7700;font-weight:bold;">in</span> name
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>._file.<span style="color: black;">name</span>
<span style="color: #008000;">AttributeError</span>: <span style="color: #483d8b;">'cStringIO.StringO'</span> <span style="color: #008000;">object</span> has no attribute <span style="color: #483d8b;">'name'</span>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> a.<span style="color: black;">fileno</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">9</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> a.<span style="color: black;">name</span>
<span style="color: #483d8b;">'&lt;fdopen&gt;'</span></pre></div></div>

 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6634&amp;md5=4780c44208eaf604051f732aae5bd0b9" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6640
title: Ca y est on est célèbres
uri: Ca-y-est-on-est-célèbres
url: http://sametmax.com/ca-y-est-on-est-celebres/
content:
<p>Après l&#8217;apfy et reddit qui nous ont retiré de leur flux, et django-fr qui a refusé de nous y mettre du fait de nos articles NSFW, voici le grand Norton himself qui nous qui nous donne le traitement VIP.</p>
<p>Merci au lecteur qui nous a envoyé ça par email :</p>
<div id="attachment_6643" class="wp-caption aligncenter" style="width: 502px"><a href="media/a59c8a18.sametmax.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/sametmax.png"><img class=" wp-image-6643  " title="Bien que le blog soit à 80 % prog, 20 % cul, notre article le plus populaire reste celui sur la masturbation féminine en vidéo." src="media/a59c8a18.sametmax.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/sametmax.png" alt="Capture d'écran du blocage de sam et max par Norton" width="492" height="277" /></a><p class="wp-caption-text">Achievement unlocked</p></div>
<p>Heureusement, <a href="http://www.mywot.com/en/scorecard/sametmax.com">WOT nous aime toujours</a>. Et puis, who wants MORE Norton ?</p>
<p>Évidement il me faut conclure sur un visuel qui convient au thème, et il m&#8217;est venu à l&#8217;esprit que vous avions négligé notre lectorat gay pendant trop longtemps.</p>
<div id="attachment_6645" class="wp-caption aligncenter" style="width: 378px"><a href="media/71bbc9e7.partouze-de-minet-gay-12.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/partouze-de-minet-gay-12.jpg"><img class=" wp-image-6645  " title="C'est un peu un croisement entre une pub jean-paul gauthier et une station de métro du marais" src="media/71bbc9e7.partouze-de-minet-gay-12.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/partouze-de-minet-gay-12.jpg" alt="Photo d'une partouze gay" width="368" height="246" /></a><p class="wp-caption-text">C&#39;est un peu un croisement entre une pub jean-paul gauthier et une station de métro du marais</p></div>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6640&amp;md5=87ae71ecc981d455b42effeb64d0ff9a" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6654
title: plist, pickle, hdf5, protocol buffers… : les formats binaires
uri: plist-pickle-hdf5-protocol-buffers-les-formats-binaires
url: http://sametmax.com/plist-pickle-hdf5-protocol-buffer-les-formats-binaires/
content:
<p>Dans <a href="http://sametmax.com/yaml-xml-json-csv-ini-quest-ce-que-cest-et-a-quoi-ca-sert/">un article précédent</a>, on avait fait un petit tour des formats texte, et j&#8217;avais promis qu&#8217;on verrait les formats binaires.</p>
<p>Contrairement à cette fois là, je vais faire un peu plus technique, et donc <strong>il est probable que ça ne parle pas aux non informaticiens</strong>.</p>
<p>Avant toute chose, il faut faire un peu de ménage. En effet, tous les formats de données sont des formats binaires, même les formats texte. Quand bien même on retire les formats texte par convention, tout le reste sont des formats binaires.</p>
<p>tar.gz, zip, 7zip, rar, iso, dmg et compagnie sont des formats binaires. Il servent à l&#8217;archivage.</p>
<p>doc, xls, ppt, pps, etc. sont des formats binaires. Ils servent à sauvegarder un document édité sous une suite Microsoft Office.</p>
<p>jpg, tiff, png, gif ou webp sont des formats binaires. Ils servent à représenter des images.</p>
<p>wav, mp3, ogg, acc, opus et monkey sont des formats binaires. Ils servent à stocker des données sonores.</p>
<p>mkv, avi, mov, mp4, ogm, webm&#8230; sont des formats binaires. Ils servent à contenir des informations vidéos.</p>
<p>Bref, tout fichier est un format binaire, toute donnée transmise d&#8217;un système informatique à un autre est un format binaire.</p>
<p>Alors qu&#8217;est-ce qu&#8217;on entend ici par &#8220;format binaire&#8221; ?</p>
<p>Principalement, format de <strong>sérialisation</strong> binaire.</p>
<p>En effet JSON, XML ou CSV sont avant tout, bien que pas uniquement, des formats de sérialisation, et nous allons donc voir des équivalents dans le monde du binaire. Attention cependant, il existe de centaines de formats, et beaucoup sont très utilisés même si je n&#8217;en ai jamais entendu parler. Les formats de sérialisation binaires sont en effet moins universels, c&#8217;est à dire qu&#8217;on les retrouve plus souvent liés à un usage ou un corps de métier. Les scientifiques ont les leurs, les industriels les leurs, les concepteurs d&#8217;OS les leurs, les constructeur de matériel les leurs, etc. Le fait que je ne les connaisse pas ne veut pas du tout dire qu&#8217;ils ne sont pas massivement utilisés. Cela veut juste dire que je ne les ai jamais croisés dans mon activité.</p>
<p>Par ailleurs je ne présenterai pas tous ceux que j&#8217;ai effectivement croisés. Voyez l&#8217;article comme une base de travail qui va vous permettre d&#8217;évaluer les autres formats binaires plutôt qu&#8217;un listing exhaustif.</p>
<p>En théorie, on distingue des données binaires, et des données encodées en binaire. En pratique, on s&#8217;en branle.</p>
<h2>Séria-quoi ?</h2>
<p>A la conception d&#8217;un programme se pose la question de savoir comment stocker ses données dans un fichier ou les transmettre par le réseau. Vous avez vos données sous forme de code, par exemple en Python une collections d&#8217;instances de vos propres classes, des dictionnaires, des listes, des entiers, des chaînes, etc. Ces objets, il va falloir les transformer en quelque chose qui puisse sauvegardé dans un fichier. Ou envoyé sur le réseau.</p>
<p>Cette opération de transformation, c&#8217;est ce qu&#8217;on appelle la sérialisation.</p>
<p>Quand on lit le fichier ou que l&#8217;on récupère la donnée via un réseau, on doit la transformer pour obtenir des objets manipulables sous forme de code : les collections d&#8217;instances de vos propres classes, des dictionnaires, des listes, des entiers, des chaînes qui étaient là à l&#8217;origine.</p>
<p>Cette opération de transformation, c&#8217;est ce qu&#8217;on appelle la dé-sérialisation.</p>
<p>Prenons un exemple en Python. J&#8217;ai une classe <code>Personne()</code> :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">class</span> Personne<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
...    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span>nom, age<span style="color: black;">&#41;</span>:
...         <span style="color: #008000;">self</span>.<span style="color: black;">nom</span> = nom
...         <span style="color: #008000;">self</span>.<span style="color: black;">age</span> = age</pre></div></div>

<p>Et j&#8217;ai un calendrier qui liste les personnes présentes selon les jours de la semaine :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> gertrude = Personne<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Gertrude&quot;</span>, <span style="color: #ff4500;">18</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> monique = Personne<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Monique&quot;</span>, <span style="color: #ff4500;">12</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> jenifer = Personne<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Jenifer&quot;</span>, <span style="color: #ff4500;">97</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> cal = <span style="color: black;">&#123;</span>
<span style="color: #483d8b;">&quot;lundi&quot;</span>: <span style="color: black;">&#91;</span>gertrude<span style="color: black;">&#93;</span>,
<span style="color: #483d8b;">&quot;mardi&quot;</span>: <span style="color: black;">&#91;</span>gertrude, monique<span style="color: black;">&#93;</span>,
<span style="color: #483d8b;">&quot;mercredi&quot;</span>: <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>,
<span style="color: #483d8b;">&quot;jeudi&quot;</span>: <span style="color: black;">&#91;</span>monique<span style="color: black;">&#93;</span>,
<span style="color: #483d8b;">&quot;vendredi&quot;</span>: <span style="color: black;">&#91;</span>gertrude, jenifer<span style="color: black;">&#93;</span>,
<span style="color: #483d8b;">&quot;samedi&quot;</span>: <span style="color: black;">&#91;</span>gertrude, monique, jenifer<span style="color: black;">&#93;</span>,
<span style="color: #483d8b;">&quot;dimanche&quot;</span>: <span style="color: black;">&#91;</span>gertrude<span style="color: black;">&#93;</span>
<span style="color: black;">&#125;</span></pre></div></div>

<p>On a donc un format riche ici, avec plusieurs types imbriqués : du dico, de la liste, de l&#8217;instance de classe perso, de l&#8217;entier et des strings. On a donc des primitives, des données associatives, des séquences ordonnées et un structure complexe.</p>
<p>Pour sauvegarder ça dans un fichier ou le faire passer sur un réseau, il va falloir écrire un sacré bout de code. Par exemple si vous voulez le transformer en XML ou en JSON, il n&#8217;y a pas de type &#8220;Personne&#8221; dans ces formats. Il va donc falloir vous mettre d&#8217;accord sur une convention, écrire le code qui génère les données formatées selon cette convention, et également le code qui permet de lire ces données formatées et recréer les bons objets derrière. Sans parler du fait que la techno qui écrit ne va peut être pas être celle qui lit. C&#8217;est ça, la problématique de la sérialisation.</p>
<p>Les formats binaires se prêtent bien au jeu de la sérialisation, bien qu&#8217;ils puissent, eux aussi, servir à bien d&#8217;autre chose. Il sont compacts, et non limités par un besoin de lisibilité, ils contiennent souvent des moyens de contenir des données au format complexe. Ils sont aussi en général rapides à traiter, et prennent peu de place.</p>
<h2>Pickle</h2>
<p><a href="http://docs.python.org/2/library/pickle.html?highlight=pickle#pickle">Pickle</a> est un format de sérialisation spécialisé pour Python. Seul un programme Python peut écrire et lire du Pickle, même si <a href="https://github.com/terryf/Phpickle">des projets existent</a> pour faire le pont avec d&#8217;autres langages.</p>
<p>Voilà ce que ça donne à l&#8217;usage, en reprenant notre calendrier précédent :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">pickle</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">pickle</span>.<span style="color: black;">dumps</span><span style="color: black;">&#40;</span>cal<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">&quot;(dp0<span style="color: #000099; font-weight: bold;">\n</span>Vmardi<span style="color: #000099; font-weight: bold;">\n</span>p1<span style="color: #000099; font-weight: bold;">\n</span>(lp2<span style="color: #000099; font-weight: bold;">\n</span>ccopy_reg<span style="color: #000099; font-weight: bold;">\n</span>_reconstructor<span style="color: #000099; font-weight: bold;">\n</span>p3<span style="color: #000099; font-weight: bold;">\n</span>(c__main__<span style="color: #000099; font-weight: bold;">\n</span>Personne<span style="color: #000099; font-weight: bold;">\n</span>p4<span style="color: #000099; font-weight: bold;">\n</span>c__builtin__<span style="color: #000099; font-weight: bold;">\n</span>object<span style="color: #000099; font-weight: bold;">\n</span>p5<span style="color: #000099; font-weight: bold;">\n</span>Ntp6<span style="color: #000099; font-weight: bold;">\n</span>Rp7<span style="color: #000099; font-weight: bold;">\n</span>(dp8<span style="color: #000099; font-weight: bold;">\n</span>S'nom'<span style="color: #000099; font-weight: bold;">\n</span>p9<span style="color: #000099; font-weight: bold;">\n</span>VGertrude<span style="color: #000099; font-weight: bold;">\n</span>p10<span style="color: #000099; font-weight: bold;">\n</span>sS'age'<span style="color: #000099; font-weight: bold;">\n</span>p11<span style="color: #000099; font-weight: bold;">\n</span>I18<span style="color: #000099; font-weight: bold;">\n</span>sbag3<span style="color: #000099; font-weight: bold;">\n</span>(g4<span style="color: #000099; font-weight: bold;">\n</span>g5<span style="color: #000099; font-weight: bold;">\n</span>Ntp12<span style="color: #000099; font-weight: bold;">\n</span>Rp13<span style="color: #000099; font-weight: bold;">\n</span>(dp14<span style="color: #000099; font-weight: bold;">\n</span>g9<span style="color: #000099; font-weight: bold;">\n</span>VMonique<span style="color: #000099; font-weight: bold;">\n</span>p15<span style="color: #000099; font-weight: bold;">\n</span>sg11<span style="color: #000099; font-weight: bold;">\n</span>I12<span style="color: #000099; font-weight: bold;">\n</span>sbasVsamedi<span style="color: #000099; font-weight: bold;">\n</span>p16<span style="color: #000099; font-weight: bold;">\n</span>(lp17<span style="color: #000099; font-weight: bold;">\n</span>g7<span style="color: #000099; font-weight: bold;">\n</span>ag13<span style="color: #000099; font-weight: bold;">\n</span>ag3<span style="color: #000099; font-weight: bold;">\n</span>(g4<span style="color: #000099; font-weight: bold;">\n</span>g5<span style="color: #000099; font-weight: bold;">\n</span>Ntp18<span style="color: #000099; font-weight: bold;">\n</span>Rp19<span style="color: #000099; font-weight: bold;">\n</span>(dp20<span style="color: #000099; font-weight: bold;">\n</span>g9<span style="color: #000099; font-weight: bold;">\n</span>VJenifer<span style="color: #000099; font-weight: bold;">\n</span>p21<span style="color: #000099; font-weight: bold;">\n</span>sg11<span style="color: #000099; font-weight: bold;">\n</span>I97<span style="color: #000099; font-weight: bold;">\n</span>sbasVvendredi<span style="color: #000099; font-weight: bold;">\n</span>p22<span style="color: #000099; font-weight: bold;">\n</span>(lp23<span style="color: #000099; font-weight: bold;">\n</span>g7<span style="color: #000099; font-weight: bold;">\n</span>ag19<span style="color: #000099; font-weight: bold;">\n</span>asVjeudi<span style="color: #000099; font-weight: bold;">\n</span>p24<span style="color: #000099; font-weight: bold;">\n</span>(lp25<span style="color: #000099; font-weight: bold;">\n</span>g13<span style="color: #000099; font-weight: bold;">\n</span>asVlundi<span style="color: #000099; font-weight: bold;">\n</span>p26<span style="color: #000099; font-weight: bold;">\n</span>(lp27<span style="color: #000099; font-weight: bold;">\n</span>g7<span style="color: #000099; font-weight: bold;">\n</span>asVdimanche<span style="color: #000099; font-weight: bold;">\n</span>p28<span style="color: #000099; font-weight: bold;">\n</span>(lp29<span style="color: #000099; font-weight: bold;">\n</span>g7<span style="color: #000099; font-weight: bold;">\n</span>asVmercredi<span style="color: #000099; font-weight: bold;">\n</span>p30<span style="color: #000099; font-weight: bold;">\n</span>(lp31<span style="color: #000099; font-weight: bold;">\n</span>s.&quot;</span></pre></div></div>

<p>Ce blougi blouga est une représentation sérialisée de notre calendrier. Si vous le sauvegardez dans un fichier ou que vous l&#8217;envoyez à un autre programme Python, il peut récupérer les objets initiaux :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> cal2 = <span style="color: #dc143c;">pickle</span>.<span style="color: black;">loads</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;(dp0<span style="color: #000099; font-weight: bold;">\n</span>Vmardi<span style="color: #000099; font-weight: bold;">\n</span>p1<span style="color: #000099; font-weight: bold;">\n</span>(lp2<span style="color: #000099; font-weight: bold;">\n</span>ccopy_reg<span style="color: #000099; font-weight: bold;">\n</span>_reconstructor<span style="color: #000099; font-weight: bold;">\n</span>p3<span style="color: #000099; font-weight: bold;">\n</span>(c__main__<span style="color: #000099; font-weight: bold;">\n</span>Personne<span style="color: #000099; font-weight: bold;">\n</span>p4<span style="color: #000099; font-weight: bold;">\n</span>c__builtin__<span style="color: #000099; font-weight: bold;">\n</span>object<span style="color: #000099; font-weight: bold;">\n</span>p5<span style="color: #000099; font-weight: bold;">\n</span>Ntp6<span style="color: #000099; font-weight: bold;">\n</span>Rp7<span style="color: #000099; font-weight: bold;">\n</span>(dp8<span style="color: #000099; font-weight: bold;">\n</span>S'nom'<span style="color: #000099; font-weight: bold;">\n</span>p9<span style="color: #000099; font-weight: bold;">\n</span>VGertrude<span style="color: #000099; font-weight: bold;">\n</span>p10<span style="color: #000099; font-weight: bold;">\n</span>sS'age'<span style="color: #000099; font-weight: bold;">\n</span>p11<span style="color: #000099; font-weight: bold;">\n</span>I18<span style="color: #000099; font-weight: bold;">\n</span>sbag3<span style="color: #000099; font-weight: bold;">\n</span>(g4<span style="color: #000099; font-weight: bold;">\n</span>g5<span style="color: #000099; font-weight: bold;">\n</span>Ntp12<span style="color: #000099; font-weight: bold;">\n</span>Rp13<span style="color: #000099; font-weight: bold;">\n</span>(dp14<span style="color: #000099; font-weight: bold;">\n</span>g9<span style="color: #000099; font-weight: bold;">\n</span>VMonique<span style="color: #000099; font-weight: bold;">\n</span>p15<span style="color: #000099; font-weight: bold;">\n</span>sg11<span style="color: #000099; font-weight: bold;">\n</span>I12<span style="color: #000099; font-weight: bold;">\n</span>sbasVsamedi<span style="color: #000099; font-weight: bold;">\n</span>p16<span style="color: #000099; font-weight: bold;">\n</span>(lp17<span style="color: #000099; font-weight: bold;">\n</span>g7<span style="color: #000099; font-weight: bold;">\n</span>ag13<span style="color: #000099; font-weight: bold;">\n</span>ag3<span style="color: #000099; font-weight: bold;">\n</span>(g4<span style="color: #000099; font-weight: bold;">\n</span>g5<span style="color: #000099; font-weight: bold;">\n</span>Ntp18<span style="color: #000099; font-weight: bold;">\n</span>Rp19<span style="color: #000099; font-weight: bold;">\n</span>(dp20<span style="color: #000099; font-weight: bold;">\n</span>g9<span style="color: #000099; font-weight: bold;">\n</span>VJenifer<span style="color: #000099; font-weight: bold;">\n</span>p21<span style="color: #000099; font-weight: bold;">\n</span>sg11<span style="color: #000099; font-weight: bold;">\n</span>I97<span style="color: #000099; font-weight: bold;">\n</span>sbasVvendredi<span style="color: #000099; font-weight: bold;">\n</span>p22<span style="color: #000099; font-weight: bold;">\n</span>(lp23<span style="color: #000099; font-weight: bold;">\n</span>g7<span style="color: #000099; font-weight: bold;">\n</span>ag19<span style="color: #000099; font-weight: bold;">\n</span>asVjeudi<span style="color: #000099; font-weight: bold;">\n</span>p24<span style="color: #000099; font-weight: bold;">\n</span>(lp25<span style="color: #000099; font-weight: bold;">\n</span>g13<span style="color: #000099; font-weight: bold;">\n</span>asVlundi<span style="color: #000099; font-weight: bold;">\n</span>p26<span style="color: #000099; font-weight: bold;">\n</span>(lp27<span style="color: #000099; font-weight: bold;">\n</span>g7<span style="color: #000099; font-weight: bold;">\n</span>asVdimanche<span style="color: #000099; font-weight: bold;">\n</span>p28<span style="color: #000099; font-weight: bold;">\n</span>(lp29<span style="color: #000099; font-weight: bold;">\n</span>g7<span style="color: #000099; font-weight: bold;">\n</span>asVmercredi<span style="color: #000099; font-weight: bold;">\n</span>p30<span style="color: #000099; font-weight: bold;">\n</span>(lp31<span style="color: #000099; font-weight: bold;">\n</span>s.&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>cal2<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>type <span style="color: #483d8b;">'dict'</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">for</span> jour, personnes <span style="color: #ff7700;font-weight:bold;">in</span> cal2.<span style="color: black;">items</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
...     <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>jour<span style="color: black;">&#41;</span>
...     <span style="color: #ff7700;font-weight:bold;">for</span> personne <span style="color: #ff7700;font-weight:bold;">in</span> personnes:
...         <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\t</span>- {}&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>personne.<span style="color: black;">nom</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
...
<span style="color: black;">mardi</span>
    - Gertrude
    - Monique
samedi
    - Gertrude
    - Monique
    - Jenifer
vendredi
    - Gertrude
    - Jenifer
jeudi
    - Monique
lundi
    - Gertrude
dimanche
    - Gertrude
mercredi</pre></div></div>

<p>On utilisera Pickle essentiellement par fainéantise, quand on veut sauvegarder des objets Python et qu&#8217;on souhaite les récupérer plus tard, mais qu&#8217;on ne veut pas coder un code de sérialisation. Il existe des formes hybrides de cette approche, comme <a href="http://jsonpickle.github.io/">cette lib</a> qui essaye de mélanger JSON et une forme de sérialisation d&#8217;objets complexes.</p>
<p>Quel que soit l&#8217;approche choisit, restaurer des objets complets, et non juste des primitives, comporte sont lot de risques de sécurité. En effet, un fichier Pickle malicieux sera exécuté comme code Python valide sans aucune vérification.</p>
<p>A noter que Python vient avec un autre format de sérialisation : <a href="http://docs.python.org/2/library/marshal.html">marshall</a>. Il est utilisé par Python en interne pour les fichiers .pyc et n&#8217;est pas recommandé pour un usage de persistance de données car le format évolue avec les versions de Python.</p>
<h2>plist</h2>
<p>Il existe de nombreux formats binaires qu&#8217;utilisent les OS comme .DS_store ou Thumbs.db. plist est l&#8217;un deux, et on va le voir parce qu&#8217;il est relativement simple à comprendre par rapport aux autres. Le principe est le même pour tous : on a des données, on les stock dans le fichier.</p>
<p>plist est un format qui existe aujourd&#8217;hui en XML, preuve que le même rôle peut très bien être rempli par deux formats différents. Il sert à stocker les réglages qu&#8217;on effectue dans le finder de Mac OS X, et ceux pour chaque dossier. Il sait représenter les types suivant : string, nombre, boolean, date, array, dictionnaire et des données arbitraires en base64 (un encodage binaire représentable sous forme de texte. Qu&#8217;est-ce qu&#8217;on se marre ^^).</p>
<p>Ce qui signifie par exemple, qu&#8217;il n&#8217;est pas capable de représenter un objet <strong>Personne()</strong> tel quel. Par contre il a des équivalents des types list, int, str, etc, ce qui en fait un format facile à manipuler en Python, surtout étant donné que la lib standard contient <a href="http://docs.python.org/2/library/plistlib.html?highlight=plist#plistlib">un module pour ça</a> :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">gertrude = <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Gertrude&quot;</span>, <span style="color: #ff4500;">18</span><span style="color: black;">&#41;</span>
monique = <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Monique&quot;</span>, <span style="color: #ff4500;">12</span><span style="color: black;">&#41;</span>
jenifer = <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Jenifer&quot;</span>, <span style="color: #ff4500;">97</span><span style="color: black;">&#41;</span>
cal = <span style="color: black;">&#123;</span>
<span style="color: #483d8b;">&quot;lundi&quot;</span>: <span style="color: black;">&#91;</span>gertrude<span style="color: black;">&#93;</span>,
<span style="color: #483d8b;">&quot;mardi&quot;</span>: <span style="color: black;">&#91;</span>gertrude, monique<span style="color: black;">&#93;</span>,
<span style="color: #483d8b;">&quot;mercredi&quot;</span>: <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>,
<span style="color: #483d8b;">&quot;jeudi&quot;</span>: <span style="color: black;">&#91;</span>monique<span style="color: black;">&#93;</span>,
<span style="color: #483d8b;">&quot;vendredi&quot;</span>: <span style="color: black;">&#91;</span>gertrude, jenifer<span style="color: black;">&#93;</span>,
<span style="color: #483d8b;">&quot;samedi&quot;</span>: <span style="color: black;">&#91;</span>gertrude, monique, jenifer<span style="color: black;">&#93;</span>,
<span style="color: #483d8b;">&quot;dimanche&quot;</span>: <span style="color: black;">&#91;</span>gertrude<span style="color: black;">&#93;</span>
<span style="color: black;">&#125;</span>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> gertrude = <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Gertrude&quot;</span>, <span style="color: #ff4500;">18</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> monique = <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Monique&quot;</span>, <span style="color: #ff4500;">12</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> jenifer = <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Jenifer&quot;</span>, <span style="color: #ff4500;">97</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> cal = <span style="color: black;">&#123;</span>
... <span style="color: #483d8b;">&quot;lundi&quot;</span>: <span style="color: black;">&#91;</span>gertrude<span style="color: black;">&#93;</span>,
... <span style="color: #483d8b;">&quot;mardi&quot;</span>: <span style="color: black;">&#91;</span>gertrude, monique<span style="color: black;">&#93;</span>,
... <span style="color: #483d8b;">&quot;mercredi&quot;</span>: <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>,
... <span style="color: #483d8b;">&quot;jeudi&quot;</span>: <span style="color: black;">&#91;</span>monique<span style="color: black;">&#93;</span>,
... <span style="color: #483d8b;">&quot;vendredi&quot;</span>: <span style="color: black;">&#91;</span>gertrude, jenifer<span style="color: black;">&#93;</span>,
... <span style="color: #483d8b;">&quot;samedi&quot;</span>: <span style="color: black;">&#91;</span>gertrude, monique, jenifer<span style="color: black;">&#93;</span>,
... <span style="color: #483d8b;">&quot;dimanche&quot;</span>: <span style="color: black;">&#91;</span>gertrude<span style="color: black;">&#93;</span>
... <span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> plistlib.<span style="color: black;">writePlistToString</span><span style="color: black;">&#40;</span>cal<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;<span style="color: #000099; font-weight: bold;">\n</span>&lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&gt;<span style="color: #000099; font-weight: bold;">\n</span>&lt;plist version=&quot;1.0&quot;&gt;<span style="color: #000099; font-weight: bold;">\n</span>&lt;dict&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;key&gt;dimanche&lt;/key&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;string&gt;Gertrude&lt;/string&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;integer&gt;18&lt;/integer&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;/array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;/array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;key&gt;jeudi&lt;/key&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;string&gt;Monique&lt;/string&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;integer&gt;12&lt;/integer&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;/array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;/array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;key&gt;lundi&lt;/key&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;string&gt;Gertrude&lt;/string&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;integer&gt;18&lt;/integer&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;/array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;/array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;key&gt;mardi&lt;/key&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;string&gt;Gertrude&lt;/string&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;integer&gt;18&lt;/integer&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;/array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;string&gt;Monique&lt;/string&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;integer&gt;12&lt;/integer&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;/array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;/array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;key&gt;mercredi&lt;/key&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;/array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;key&gt;samedi&lt;/key&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;string&gt;Gertrude&lt;/string&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;integer&gt;18&lt;/integer&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;/array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;string&gt;Monique&lt;/string&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;integer&gt;12&lt;/integer&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;/array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;string&gt;Jenifer&lt;/string&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;integer&gt;97&lt;/integer&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;/array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;/array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;key&gt;vendredi&lt;/key&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;string&gt;Gertrude&lt;/string&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;integer&gt;18&lt;/integer&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;/array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;string&gt;Jenifer&lt;/string&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;integer&gt;97&lt;/integer&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;/array&gt;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\t</span>&lt;/array&gt;<span style="color: #000099; font-weight: bold;">\n</span>&lt;/dict&gt;<span style="color: #000099; font-weight: bold;">\n</span>&lt;/plist&gt;<span style="color: #000099; font-weight: bold;">\n</span>'</span></pre></div></div>

<p>Bon, là j&#8217;ai un peu foiré mon exemple parce que la lib standard, elle pond la version XML (puisque la version binaire est obsolète), pas la version binaire de plist, et maintenant que j&#8217;ai écris tout ça, ça me fait chier de tout refaire. Heureusement j&#8217;ai trouvé <a href="https://github.com/wooster/biplist">une lib sur le net</a> qui va sauver mon honneur :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> biplist.<span style="color: black;">writePlistToString</span><span style="color: black;">&#40;</span>cal<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'bplist00bybiplist1.0<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>d7<span style="color: #000099; font-weight: bold;">\x</span>01<span style="color: #000099; font-weight: bold;">\x</span>02<span style="color: #000099; font-weight: bold;">\x</span>03<span style="color: #000099; font-weight: bold;">\x</span>04<span style="color: #000099; font-weight: bold;">\x</span>05<span style="color: #000099; font-weight: bold;">\x</span>06<span style="color: #000099; font-weight: bold;">\x</span>07<span style="color: #000099; font-weight: bold;">\x</span>08<span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\x</span>0b<span style="color: #000099; font-weight: bold;">\x</span>0c<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\x</span>0ee<span style="color: #000099; font-weight: bold;">\x</span>00m<span style="color: #000099; font-weight: bold;">\x</span>00a<span style="color: #000099; font-weight: bold;">\x</span>00r<span style="color: #000099; font-weight: bold;">\x</span>00d<span style="color: #000099; font-weight: bold;">\x</span>00if<span style="color: #000099; font-weight: bold;">\x</span>00s<span style="color: #000099; font-weight: bold;">\x</span>00a<span style="color: #000099; font-weight: bold;">\x</span>00m<span style="color: #000099; font-weight: bold;">\x</span>00e<span style="color: #000099; font-weight: bold;">\x</span>00d<span style="color: #000099; font-weight: bold;">\x</span>00ih<span style="color: #000099; font-weight: bold;">\x</span>00v<span style="color: #000099; font-weight: bold;">\x</span>00e<span style="color: #000099; font-weight: bold;">\x</span>00n<span style="color: #000099; font-weight: bold;">\x</span>00d<span style="color: #000099; font-weight: bold;">\x</span>00r<span style="color: #000099; font-weight: bold;">\x</span>00e<span style="color: #000099; font-weight: bold;">\x</span>00d<span style="color: #000099; font-weight: bold;">\x</span>00ie<span style="color: #000099; font-weight: bold;">\x</span>00j<span style="color: #000099; font-weight: bold;">\x</span>00e<span style="color: #000099; font-weight: bold;">\x</span>00u<span style="color: #000099; font-weight: bold;">\x</span>00d<span style="color: #000099; font-weight: bold;">\x</span>00ie<span style="color: #000099; font-weight: bold;">\x</span>00l<span style="color: #000099; font-weight: bold;">\x</span>00u<span style="color: #000099; font-weight: bold;">\x</span>00n<span style="color: #000099; font-weight: bold;">\x</span>00d<span style="color: #000099; font-weight: bold;">\x</span>00ih<span style="color: #000099; font-weight: bold;">\x</span>00d<span style="color: #000099; font-weight: bold;">\x</span>00i<span style="color: #000099; font-weight: bold;">\x</span>00m<span style="color: #000099; font-weight: bold;">\x</span>00a<span style="color: #000099; font-weight: bold;">\x</span>00n<span style="color: #000099; font-weight: bold;">\x</span>00c<span style="color: #000099; font-weight: bold;">\x</span>00h<span style="color: #000099; font-weight: bold;">\x</span>00eh<span style="color: #000099; font-weight: bold;">\x</span>00m<span style="color: #000099; font-weight: bold;">\x</span>00e<span style="color: #000099; font-weight: bold;">\x</span>00r<span style="color: #000099; font-weight: bold;">\x</span>00c<span style="color: #000099; font-weight: bold;">\x</span>00r<span style="color: #000099; font-weight: bold;">\x</span>00e<span style="color: #000099; font-weight: bold;">\x</span>00d<span style="color: #000099; font-weight: bold;">\x</span>00i<span style="color: #000099; font-weight: bold;">\x</span>a2<span style="color: #000099; font-weight: bold;">\x</span>0f<span style="color: #000099; font-weight: bold;">\x</span>10<span style="color: #000099; font-weight: bold;">\x</span>a2<span style="color: #000099; font-weight: bold;">\x</span>11<span style="color: #000099; font-weight: bold;">\x</span>12h<span style="color: #000099; font-weight: bold;">\x</span>00G<span style="color: #000099; font-weight: bold;">\x</span>00e<span style="color: #000099; font-weight: bold;">\x</span>00r<span style="color: #000099; font-weight: bold;">\x</span>00t<span style="color: #000099; font-weight: bold;">\x</span>00r<span style="color: #000099; font-weight: bold;">\x</span>00u<span style="color: #000099; font-weight: bold;">\x</span>00d<span style="color: #000099; font-weight: bold;">\x</span>00e<span style="color: #000099; font-weight: bold;">\x</span>10<span style="color: #000099; font-weight: bold;">\x</span>12<span style="color: #000099; font-weight: bold;">\x</span>a2<span style="color: #000099; font-weight: bold;">\x</span>13<span style="color: #000099; font-weight: bold;">\x</span>14g<span style="color: #000099; font-weight: bold;">\x</span>00M<span style="color: #000099; font-weight: bold;">\x</span>00o<span style="color: #000099; font-weight: bold;">\x</span>00n<span style="color: #000099; font-weight: bold;">\x</span>00i<span style="color: #000099; font-weight: bold;">\x</span>00q<span style="color: #000099; font-weight: bold;">\x</span>00u<span style="color: #000099; font-weight: bold;">\x</span>00e<span style="color: #000099; font-weight: bold;">\x</span>10<span style="color: #000099; font-weight: bold;">\x</span>0c<span style="color: #000099; font-weight: bold;">\x</span>a3<span style="color: #000099; font-weight: bold;">\x</span>15<span style="color: #000099; font-weight: bold;">\x</span>16<span style="color: #000099; font-weight: bold;">\x</span>17<span style="color: #000099; font-weight: bold;">\x</span>a2<span style="color: #000099; font-weight: bold;">\x</span>11<span style="color: #000099; font-weight: bold;">\x</span>12<span style="color: #000099; font-weight: bold;">\x</span>a2<span style="color: #000099; font-weight: bold;">\x</span>13<span style="color: #000099; font-weight: bold;">\x</span>14<span style="color: #000099; font-weight: bold;">\x</span>a2<span style="color: #000099; font-weight: bold;">\x</span>18<span style="color: #000099; font-weight: bold;">\x</span>19g<span style="color: #000099; font-weight: bold;">\x</span>00J<span style="color: #000099; font-weight: bold;">\x</span>00e<span style="color: #000099; font-weight: bold;">\x</span>00n<span style="color: #000099; font-weight: bold;">\x</span>00i<span style="color: #000099; font-weight: bold;">\x</span>00f<span style="color: #000099; font-weight: bold;">\x</span>00e<span style="color: #000099; font-weight: bold;">\x</span>00r<span style="color: #000099; font-weight: bold;">\x</span>10a<span style="color: #000099; font-weight: bold;">\x</span>a2<span style="color: #000099; font-weight: bold;">\x</span>1a<span style="color: #000099; font-weight: bold;">\x</span>1b<span style="color: #000099; font-weight: bold;">\x</span>a2<span style="color: #000099; font-weight: bold;">\x</span>11<span style="color: #000099; font-weight: bold;">\x</span>12<span style="color: #000099; font-weight: bold;">\x</span>a2<span style="color: #000099; font-weight: bold;">\x</span>18<span style="color: #000099; font-weight: bold;">\x</span>19<span style="color: #000099; font-weight: bold;">\x</span>a1<span style="color: #000099; font-weight: bold;">\x</span>1c<span style="color: #000099; font-weight: bold;">\x</span>a2<span style="color: #000099; font-weight: bold;">\x</span>13<span style="color: #000099; font-weight: bold;">\x</span>14<span style="color: #000099; font-weight: bold;">\x</span>a1<span style="color: #000099; font-weight: bold;">\x</span>1d<span style="color: #000099; font-weight: bold;">\x</span>a2<span style="color: #000099; font-weight: bold;">\x</span>11<span style="color: #000099; font-weight: bold;">\x</span>12<span style="color: #000099; font-weight: bold;">\x</span>a1<span style="color: #000099; font-weight: bold;">\x</span>1e<span style="color: #000099; font-weight: bold;">\x</span>a2<span style="color: #000099; font-weight: bold;">\x</span>11<span style="color: #000099; font-weight: bold;">\x</span>12<span style="color: #000099; font-weight: bold;">\x</span>a0<span style="color: #000099; font-weight: bold;">\x</span>15$/&lt;MXct<span style="color: #000099; font-weight: bold;">\x</span>85<span style="color: #000099; font-weight: bold;">\x</span>b2<span style="color: #000099; font-weight: bold;">\x</span>d0<span style="color: #000099; font-weight: bold;">\x</span>d9<span style="color: #000099; font-weight: bold;">\x</span>de<span style="color: #000099; font-weight: bold;">\x</span>e3<span style="color: #000099; font-weight: bold;">\x</span>e8<span style="color: #000099; font-weight: bold;">\x</span>88<span style="color: #000099; font-weight: bold;">\x</span>9e<span style="color: #000099; font-weight: bold;">\x</span>8b<span style="color: #000099; font-weight: bold;">\x</span>9c<span style="color: #000099; font-weight: bold;">\x</span>a1<span style="color: #000099; font-weight: bold;">\x</span>b0<span style="color: #000099; font-weight: bold;">\x</span>b6<span style="color: #000099; font-weight: bold;">\x</span>b9<span style="color: #000099; font-weight: bold;">\x</span>bc<span style="color: #000099; font-weight: bold;">\x</span>bf<span style="color: #000099; font-weight: bold;">\x</span>ce<span style="color: #000099; font-weight: bold;">\x</span>d3<span style="color: #000099; font-weight: bold;">\x</span>d6<span style="color: #000099; font-weight: bold;">\x</span>db<span style="color: #000099; font-weight: bold;">\x</span>e0<span style="color: #000099; font-weight: bold;">\x</span>e5<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>01<span style="color: #000099; font-weight: bold;">\x</span>01<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>1f<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>e9'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> biplist.<span style="color: black;">readPlistFromString</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'bplist00bybiplist1.0<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>d7<span style="color: #000099; font-weight: bold;">\x</span>01<span style="color: #000099; font-weight: bold;">\x</span>02<span style="color: #000099; font-weight: bold;">\x</span>03<span style="color: #000099; font-weight: bold;">\x</span>04<span style="color: #000099; font-weight: bold;">\x</span>05<span style="color: #000099; font-weight: bold;">\x</span>06<span style="color: #000099; font-weight: bold;">\x</span>07<span style="color: #000099; font-weight: bold;">\x</span>08<span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\x</span>0b<span style="color: #000099; font-weight: bold;">\x</span>0c<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\x</span>0ee<span style="color: #000099; font-weight: bold;">\x</span>00m<span style="color: #000099; font-weight: bold;">\x</span>00a<span style="color: #000099; font-weight: bold;">\x</span>00r<span style="color: #000099; font-weight: bold;">\x</span>00d<span style="color: #000099; font-weight: bold;">\x</span>00if<span style="color: #000099; font-weight: bold;">\x</span>00s<span style="color: #000099; font-weight: bold;">\x</span>00a<span style="color: #000099; font-weight: bold;">\x</span>00m<span style="color: #000099; font-weight: bold;">\x</span>00e<span style="color: #000099; font-weight: bold;">\x</span>00d<span style="color: #000099; font-weight: bold;">\x</span>00ih<span style="color: #000099; font-weight: bold;">\x</span>00v<span style="color: #000099; font-weight: bold;">\x</span>00e<span style="color: #000099; font-weight: bold;">\x</span>00n<span style="color: #000099; font-weight: bold;">\x</span>00d<span style="color: #000099; font-weight: bold;">\x</span>00r<span style="color: #000099; font-weight: bold;">\x</span>00e<span style="color: #000099; font-weight: bold;">\x</span>00d<span style="color: #000099; font-weight: bold;">\x</span>00ie<span style="color: #000099; font-weight: bold;">\x</span>00j<span style="color: #000099; font-weight: bold;">\x</span>00e<span style="color: #000099; font-weight: bold;">\x</span>00u<span style="color: #000099; font-weight: bold;">\x</span>00d<span style="color: #000099; font-weight: bold;">\x</span>00ie<span style="color: #000099; font-weight: bold;">\x</span>00l<span style="color: #000099; font-weight: bold;">\x</span>00u<span style="color: #000099; font-weight: bold;">\x</span>00n<span style="color: #000099; font-weight: bold;">\x</span>00d<span style="color: #000099; font-weight: bold;">\x</span>00ih<span style="color: #000099; font-weight: bold;">\x</span>00d<span style="color: #000099; font-weight: bold;">\x</span>00i<span style="color: #000099; font-weight: bold;">\x</span>00m<span style="color: #000099; font-weight: bold;">\x</span>00a<span style="color: #000099; font-weight: bold;">\x</span>00n<span style="color: #000099; font-weight: bold;">\x</span>00c<span style="color: #000099; font-weight: bold;">\x</span>00h<span style="color: #000099; font-weight: bold;">\x</span>00eh<span style="color: #000099; font-weight: bold;">\x</span>00m<span style="color: #000099; font-weight: bold;">\x</span>00e<span style="color: #000099; font-weight: bold;">\x</span>00r<span style="color: #000099; font-weight: bold;">\x</span>00c<span style="color: #000099; font-weight: bold;">\x</span>00r<span style="color: #000099; font-weight: bold;">\x</span>00e<span style="color: #000099; font-weight: bold;">\x</span>00d<span style="color: #000099; font-weight: bold;">\x</span>00i<span style="color: #000099; font-weight: bold;">\x</span>a2<span style="color: #000099; font-weight: bold;">\x</span>0f<span style="color: #000099; font-weight: bold;">\x</span>10<span style="color: #000099; font-weight: bold;">\x</span>a2<span style="color: #000099; font-weight: bold;">\x</span>11<span style="color: #000099; font-weight: bold;">\x</span>12h<span style="color: #000099; font-weight: bold;">\x</span>00G<span style="color: #000099; font-weight: bold;">\x</span>00e<span style="color: #000099; font-weight: bold;">\x</span>00r<span style="color: #000099; font-weight: bold;">\x</span>00t<span style="color: #000099; font-weight: bold;">\x</span>00r<span style="color: #000099; font-weight: bold;">\x</span>00u<span style="color: #000099; font-weight: bold;">\x</span>00d<span style="color: #000099; font-weight: bold;">\x</span>00e<span style="color: #000099; font-weight: bold;">\x</span>10<span style="color: #000099; font-weight: bold;">\x</span>12<span style="color: #000099; font-weight: bold;">\x</span>a2<span style="color: #000099; font-weight: bold;">\x</span>13<span style="color: #000099; font-weight: bold;">\x</span>14g<span style="color: #000099; font-weight: bold;">\x</span>00M<span style="color: #000099; font-weight: bold;">\x</span>00o<span style="color: #000099; font-weight: bold;">\x</span>00n<span style="color: #000099; font-weight: bold;">\x</span>00i<span style="color: #000099; font-weight: bold;">\x</span>00q<span style="color: #000099; font-weight: bold;">\x</span>00u<span style="color: #000099; font-weight: bold;">\x</span>00e<span style="color: #000099; font-weight: bold;">\x</span>10<span style="color: #000099; font-weight: bold;">\x</span>0c<span style="color: #000099; font-weight: bold;">\x</span>a3<span style="color: #000099; font-weight: bold;">\x</span>15<span style="color: #000099; font-weight: bold;">\x</span>16<span style="color: #000099; font-weight: bold;">\x</span>17<span style="color: #000099; font-weight: bold;">\x</span>a2<span style="color: #000099; font-weight: bold;">\x</span>11<span style="color: #000099; font-weight: bold;">\x</span>12<span style="color: #000099; font-weight: bold;">\x</span>a2<span style="color: #000099; font-weight: bold;">\x</span>13<span style="color: #000099; font-weight: bold;">\x</span>14<span style="color: #000099; font-weight: bold;">\x</span>a2<span style="color: #000099; font-weight: bold;">\x</span>18<span style="color: #000099; font-weight: bold;">\x</span>19g<span style="color: #000099; font-weight: bold;">\x</span>00J<span style="color: #000099; font-weight: bold;">\x</span>00e<span style="color: #000099; font-weight: bold;">\x</span>00n<span style="color: #000099; font-weight: bold;">\x</span>00i<span style="color: #000099; font-weight: bold;">\x</span>00f<span style="color: #000099; font-weight: bold;">\x</span>00e<span style="color: #000099; font-weight: bold;">\x</span>00r<span style="color: #000099; font-weight: bold;">\x</span>10a<span style="color: #000099; font-weight: bold;">\x</span>a2<span style="color: #000099; font-weight: bold;">\x</span>1a<span style="color: #000099; font-weight: bold;">\x</span>1b<span style="color: #000099; font-weight: bold;">\x</span>a2<span style="color: #000099; font-weight: bold;">\x</span>11<span style="color: #000099; font-weight: bold;">\x</span>12<span style="color: #000099; font-weight: bold;">\x</span>a2<span style="color: #000099; font-weight: bold;">\x</span>18<span style="color: #000099; font-weight: bold;">\x</span>19<span style="color: #000099; font-weight: bold;">\x</span>a1<span style="color: #000099; font-weight: bold;">\x</span>1c<span style="color: #000099; font-weight: bold;">\x</span>a2<span style="color: #000099; font-weight: bold;">\x</span>13<span style="color: #000099; font-weight: bold;">\x</span>14<span style="color: #000099; font-weight: bold;">\x</span>a1<span style="color: #000099; font-weight: bold;">\x</span>1d<span style="color: #000099; font-weight: bold;">\x</span>a2<span style="color: #000099; font-weight: bold;">\x</span>11<span style="color: #000099; font-weight: bold;">\x</span>12<span style="color: #000099; font-weight: bold;">\x</span>a1<span style="color: #000099; font-weight: bold;">\x</span>1e<span style="color: #000099; font-weight: bold;">\x</span>a2<span style="color: #000099; font-weight: bold;">\x</span>11<span style="color: #000099; font-weight: bold;">\x</span>12<span style="color: #000099; font-weight: bold;">\x</span>a0<span style="color: #000099; font-weight: bold;">\x</span>15$/&lt;MXct<span style="color: #000099; font-weight: bold;">\x</span>85<span style="color: #000099; font-weight: bold;">\x</span>b2<span style="color: #000099; font-weight: bold;">\x</span>d0<span style="color: #000099; font-weight: bold;">\x</span>d9<span style="color: #000099; font-weight: bold;">\x</span>de<span style="color: #000099; font-weight: bold;">\x</span>e3<span style="color: #000099; font-weight: bold;">\x</span>e8<span style="color: #000099; font-weight: bold;">\x</span>88<span style="color: #000099; font-weight: bold;">\x</span>9e<span style="color: #000099; font-weight: bold;">\x</span>8b<span style="color: #000099; font-weight: bold;">\x</span>9c<span style="color: #000099; font-weight: bold;">\x</span>a1<span style="color: #000099; font-weight: bold;">\x</span>b0<span style="color: #000099; font-weight: bold;">\x</span>b6<span style="color: #000099; font-weight: bold;">\x</span>b9<span style="color: #000099; font-weight: bold;">\x</span>bc<span style="color: #000099; font-weight: bold;">\x</span>bf<span style="color: #000099; font-weight: bold;">\x</span>ce<span style="color: #000099; font-weight: bold;">\x</span>d3<span style="color: #000099; font-weight: bold;">\x</span>d6<span style="color: #000099; font-weight: bold;">\x</span>db<span style="color: #000099; font-weight: bold;">\x</span>e0<span style="color: #000099; font-weight: bold;">\x</span>e5<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>01<span style="color: #000099; font-weight: bold;">\x</span>01<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>1f<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>e9'</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'mardi'</span>: <span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Gertrude'</span>, <span style="color: #ff4500;">18</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Monique'</span>, <span style="color: #ff4500;">12</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>, <span style="color: #483d8b;">'samedi'</span>: <span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Gertrude'</span>, <span style="color: #ff4500;">18</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Monique'</span>, <span style="color: #ff4500;">12</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Jenifer'</span>, <span style="color: #ff4500;">97</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>, <span style="color: #483d8b;">'vendredi'</span>: <span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Gertrude'</span>, <span style="color: #ff4500;">18</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Jenifer'</span>, <span style="color: #ff4500;">97</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>, <span style="color: #483d8b;">'jeudi'</span>: <span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Monique'</span>, <span style="color: #ff4500;">12</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>, <span style="color: #483d8b;">'lundi'</span>: <span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Gertrude'</span>, <span style="color: #ff4500;">18</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>, <span style="color: #483d8b;">'dimanche'</span>: <span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Gertrude'</span>, <span style="color: #ff4500;">18</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>, <span style="color: #483d8b;">'mercredi'</span>: <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><span style="color: black;">&#125;</span></pre></div></div>

<p>Pourquoi utiliser plist ? A part quand on est en Objectif-C où c&#8217;est le format le plus simple à parser ou si on veut communiquer avec finder, il n&#8217;y a pas vraiment de raison. C&#8217;est le cas typique d&#8217;un format qui a été créé parce qu&#8217;à l&#8217;époque il n&#8217;y avait rien d&#8217;aussi bien, les parsers XML étaient alors trop lents pour scanner toutes les plist de tous les dossiers récursivement.</p>
<h2>hdf5</h2>
<p>hdf5 est très intéressant, c&#8217;est le cas typique d&#8217;un format qui existe pour un usage très très particulier, et que des formats ordinaires ne comblent pas, ne peuvent pas par nature combler. C&#8217;est un format cross-plateforme qui peut contenir de très grosses quantités de données numériques (un fichier peut avoir une taille virtuellement illimitée), et les manipuler pour faire des calculs complexes. Cela ressemble à un système de fichiers&#8230; qui tient dans un fichier. En effet, il peut contenir une arborescence de données, et gère la compression transparente, mais les données sont essentiellement des arrays à plusieurs dimensions, appelés ici datasets.</p>
<p>On peut y mettre des arrays, des labels, des attributs, organiser tout ça par groupe et même avoir des références vers des données extérieures. L&#8217;avantage c&#8217;est qu&#8217;on peut bosser dessus presque de manière transparente, comme si c&#8217;était en RAM. Tout ce qui est array est stocké tel quel, et donc très rapide d&#8217;accès (bien plus qu&#8217;une colonne de base SQL), pour le reste, c&#8217;est indexé avec arbre binaire, donc facilement triable.</p>
<p>Pour manipuler ce format avec Python, on va utiliser la lib <a href="http://www.h5py.org">h5py</a> :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">sudo apt-get install libhdf5-serial-dev python-dev <span style="color: #808080; font-style: italic;"># sur ubuntu en tout cas</span>
pip install numpy
pip install h5py</pre></div></div>

<p>La normalement, ça compile à mort pendant 10 minutes.</p>
<p>Et pif paf pouf :</p>
<p>>>> import numpy # hdf5 s&#8217;utilise beaucoup avec les libs scientifiques type numpy<br />
>>> import h5py<br />
>>> array = numpy.ones((1000000000, 1000000000)) # une grosse matrice<br />
>>> f = h5py.File(&#8216;data.hdf5&#8242;)<br />
>>> dset = f.create_dataset(&#8220;Nom du dataset&#8221;, data=array)<br />
>>> dset<br />
<HDF5 dataset "Nom du dataset": shape (100, 100), type "<i8"><br />
>>> f.close()</p>
<p>Et voilà, on vient de créer array contenant 1000000000 lignes de 1000000000 de 1000000000 de int ayant pour valeur &#8220;1&#8243;, et stocké tout ça dans un fichier au format hdf5. Ca prend quelques secondes, et le fichier fait quand même 800 Mo !</p>
<p>On le voit ici, hdf5 est entre le format de sérialisation et la base de données, et il est très orienté chiffre. Il existe tout un tas de formats binaires spécialisés pour un usage en particulier comme hdf5, à votre charge, donc, de chercher si il en existe un pour le votre. Ou même si vous en avez besoin d&#8217;un.</p>
<p>Des libs de haut niveau ont été construite en utilisant hdf5, telles que <a href="http://www.pytables.org/">pytables</a>, qui permettent de traiter très facilement d&#8217;énormes jeux de données tabulaires.</p>
<h2>Protocol Buffers</h2>
<p>Aussi appelé protobuf par ses amis, c&#8217;est un format de sérialisation <a href="https://developers.google.com/protocol-buffers/">inventé par Google</a> qu&#8217;il utilise pour communiquer entre ses machines. On a donc vu un format de sérialisation orienté persistance avec Pickle, un orienté configuration, un orienté &#8220;grosse quantité de données&#8221; et voilà un dernier orienté communication réseau.</p>
<p>Protocol Buffers est un espèce d&#8217;hybride, puisqu&#8217;il utilise une description du schéma pour générer du code qui va sérialiser les donner en binaire. Vous suivez ? Non ?</p>
<p>Attendez ça va devenir plus clair.</p>
<p>Reprenons notre bonne vielle personne. Pour utiliser protobuf, vous allez décrire à quoi ressemble votre personne, dans un <strong>format texte</strong> spécialement conçu :</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">message Personne <span style="color: #009900;">&#123;</span>
  required string nom <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
  required int32 age <span style="color: #339933;">=</span> <span style="color: #cc66cc;">2</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Vous constatez qu&#8217;on décrit ici un message, qui va devoir contenir au minimum un nom et un age, de type string et entier. Les chiffres représentent des identifiants uniques de champs qui seront utilisés dans le message binaire.</p>
<p>Ceci n&#8217;est pas du code d&#8217;un langage particulier, c&#8217;est la syntaxe de modèle de protobuf.</p>
<p>On sauvegarde tout ça dans un fichier <em>personne.proto</em>, et on utilise la commande <code>protoc</code> pour transformer cette description en code dans le langage de son choix. C++ et Java sont supportés, nous on va utiliser Python :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">protoc personne.proto --python_out=.</pre></div></div>

<p>Et il va nous pondre un fichier <em>personne_pb2.py</em>, qui est un module Python valide qui va contenir une classe <code>Personne</code> :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">from</span> personne_pb2 <span style="color: #ff7700;font-weight:bold;">import</span> Personne
<span style="color: #66cc66;">&gt;&gt;&gt;</span> p = Personne<span style="color: black;">&#40;</span>nom=<span style="color: #483d8b;">&quot;Gertrude&quot;</span>, age=<span style="color: #ff4500;">12</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> p.<span style="color: black;">SerializeToString</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\x</span>08Gertrude<span style="color: #000099; font-weight: bold;">\x</span>10<span style="color: #000099; font-weight: bold;">\x</span>0c'</span></pre></div></div>

<p>Il vous suffit d&#8217;envoyer ça par un socket, et de l&#8217;autre côté, une machine qui possède le même fichier .proto peut le lire et récupérer la donnée sous forme d&#8217;un objet Python, Java ou C++. Il a donc l&#8217;avantage d&#8217;un pickle, multi langages.</p>
<p>Parmi les bénéfices de protobuf, il y a que sa sortie est assez courte :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> json.<span style="color: black;">dumps</span><span style="color: black;">&#40;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;nom&quot;</span>:<span style="color: #483d8b;">&quot;Gertrude&quot;</span>, <span style="color: #483d8b;">&quot;age&quot;</span>:<span style="color: #ff4500;">12</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'{&quot;nom&quot;: &quot;Gertrude&quot;, &quot;age&quot;: 12}'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">pickle</span>.<span style="color: black;">dumps</span><span style="color: black;">&#40;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;nom&quot;</span>:<span style="color: #483d8b;">&quot;Gertrude&quot;</span>, <span style="color: #483d8b;">&quot;age&quot;</span>:<span style="color: #ff4500;">12</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'(dp0<span style="color: #000099; font-weight: bold;">\n</span>Vnom<span style="color: #000099; font-weight: bold;">\n</span>p1<span style="color: #000099; font-weight: bold;">\n</span>VGertrude<span style="color: #000099; font-weight: bold;">\n</span>p2<span style="color: #000099; font-weight: bold;">\n</span>sVage<span style="color: #000099; font-weight: bold;">\n</span>p3<span style="color: #000099; font-weight: bold;">\n</span>I12<span style="color: #000099; font-weight: bold;">\n</span>s.'</span></pre></div></div>

<p>Ca fait moins de données à envoyer par le réseau.</p>
<p>Et en prime on a la validation des données :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> p.<span style="color: black;">age</span> = <span style="color: #483d8b;">&quot;12&quot;</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&lt;ipython-input-4-d897accc3848&gt;&quot;</span>, line <span style="color: #ff4500;">1</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #66cc66;">&lt;</span>module<span style="color: #66cc66;">&gt;</span>
    p.<span style="color: black;">age</span> = <span style="color: #483d8b;">&quot;12&quot;</span>
  File <span style="color: #483d8b;">&quot;/usr/lib/python2.7/dist-packages/google/protobuf/internal/python_message.py&quot;</span>, line <span style="color: #ff4500;">435</span>, <span style="color: #ff7700;font-weight:bold;">in</span> setter
    type_checker.<span style="color: black;">CheckValue</span><span style="color: black;">&#40;</span>new_value<span style="color: black;">&#41;</span>
  File <span style="color: #483d8b;">&quot;/usr/lib/python2.7/dist-packages/google/protobuf/internal/type_checkers.py&quot;</span>, line <span style="color: #ff4500;">104</span>, <span style="color: #ff7700;font-weight:bold;">in</span> CheckValue
    <span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #008000;">TypeError</span><span style="color: black;">&#40;</span>message<span style="color: black;">&#41;</span>
<span style="color: #008000;">TypeError</span>: u<span style="color: #483d8b;">'12'</span> has <span style="color: #008000;">type</span> <span style="color: #66cc66;">&lt;</span>type <span style="color: #483d8b;">'unicode'</span><span style="color: #66cc66;">&gt;</span>, but expected one of: <span style="color: black;">&#40;</span><span style="color: #66cc66;">&lt;</span>type <span style="color: #483d8b;">'int'</span><span style="color: #66cc66;">&gt;</span>, <span style="color: #66cc66;">&lt;</span>type <span style="color: #483d8b;">'long'</span><span style="color: #66cc66;">&gt;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Du coup on peut utiliser protobuf en lieu et place d&#8217;un XML + DTD, en tout cas pour les cas simples.</p>
<p>Normalement, c&#8217;est aussi un format très rapide à parser.</p>
<p>Bref, Google a voulu le format pour les utilisations industrielles : c&#8217;est un peu chiant à mettre en place, mais c&#8217;est performant, robuste et ça marche avec les 3 langages qu&#8217;ils utilisent en interne.</p>
<p>Néanmoins ce n&#8217;est pas le seul à avoir pensé à ça : <a lang="http://msgpack.org/">msgpack</a> est une sorte de JSON binaire plus rapide à parser et qui prend moins de place. Il est assez utilisé avec les outils de file d&#8217;attente genre celery ou de communication type ZeroMq. Mais il perd un intérêt fort du JSON : sa transparence pour javascript, et n&#8217;a pas la vérification des données comme protobuf. <a href="http://bsonspec.org/">BSON</a> existe aussi dans le même genre, et sert de format de stockage pour mongodb, en supportant nativement des types avancées comme les dates.</p>
<p>Comme je vous le disais, des formats binaire, il y en a <a href="http://fr.wikipedia.org/wiki/Wikip%C3%A9dia:Pastiches/Pifom%C3%A8tre#Les_unit.C3.A9s_du_syst.C3.A8me_pifom.C3.A8trique">une bonne chiée</a>.</p>
<p>La prochaine et dernière session, on se fera un petit tour des bases de données SQL et NoSQL.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6654&amp;md5=c22470fd5124424eb8594b10e6f5c655" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6667
title: Pouvez-vous séparer le cul de la programmation SVP ?
uri: Pouvez-vous-séparer-le-cul-de-la-programmation-SVP
url: http://sametmax.com/pouvez-vous-separer-le-cul-de-la-programmation-svp/
content:
<p>Régulièrement, par twitter, mail ou en comment, on reçoit quelque chose qui ressemble à ça :</p>
<blockquote><p>Bonjour !</p>
<p>  En rapport avec votre dernier article et NSFW toussa toussa, je sais que vous êtes contre la création d&#8217;une catégorie NSFW mais est-ce qu&#8217;il serait possible de ne pas poster du cul dans la catégorie &#8220;programmation&#8221; &#8211; ou plutôt ne pas mettre de flag programmation dans ce genre de cas ? Vous feriez un heureux.</p>
<p>Parce que si l&#8217;image gay était marrante, les images en commentaires étaient moyenne et j&#8217;aimerais pouvoir continuer à consulter votre blog que j&#8217;apprécie depuis mon boulot.</p>
<p>Sinon, merci pour tous vos articles, j&#8217;ai appris beaucoup de choses grâce à vous </p>
<p>En espérant que vous me comprendrez.</p></blockquote>
<p>Les gens sont toujours très polis et respectueux dans leur demande, et on l’apprécie beaucoup. En fait, même quand l&#8217;AFPY nous a annoncé qu&#8217;ils nous viraient, ils l&#8217;ont fait dans le respect. C&#8217;est comme ça que les choses doivent se faire.</p>
<p>Et c&#8217;est donc comme ça que je vais essayer de répondre.</p>
<h2>Non</h2>
<p>Nous mélangeons le cul et la programmation parce que cela nous amuse. Nous écrivons ce blog pour le plaisir. Devoir réfléchir à ce qu&#8217;on y met, comment on l&#8217;y met, et aller à l&#8217;encontre de notre spontanéité pour des raisons autres que pédagogiques irait à l&#8217;encontre de cela.</p>
<p>Comprenez bien, tous les jours nous vivons l&#8217;intolérance de personnes qui <a href="http://sametmax.com/montrer-un-meurtre-est-moins-grave-que-montrer-sa-bite/">voient le sexe comme quelque chose de mal, à cacher, mais qui par contre n&#8217;ont rien contre la violence</a>.</p>
<p>Personnellement (je pense que Max s&#8217;en branle un peu plus que moi), j&#8217;utilise le blog comme moyen de faire passer ce message : on peut mélanger la double pénétration et la compétence technique, l&#8217;osé et le casual, l&#8217;arrache et le recherché. </p>
<p>Si vous ne pouvez pas consulter ce blog au travail, le problème ne vient pas du blog.</p>
<p>Il vient de votre lieu de travail.</p>
<p>Le blog lui, est ce qui l&#8217;est, avec sa formule annoncée dès le départ.</p>
<p>Vous ne pouvez pas consulter ce blog à cause de cela ? Ce n&#8217;est pas grave, ne consultez pas le blog. Il n&#8217;y a pas mort d&#8217;homme. Internet est grand, le monde aussi. Il y a de la place pour tout, des ressources en masse et des domaines qui conviendrons mieux à vos contraintes.</p>
<p>Personnellement si je travaillais dans un lieu qui m&#8217;empêchait d&#8217;accéder à des contenus que je considère utile, je changerais de travail.</p>
<p>Sans rancune. Sans jugement. Simplement parce que cela fait partie des choses qui sont importantes pour moi.</p>
<p>Si vous ne voulez pas faire cela, alors c&#8217;est que ce travail vous apporte plus que ce que vous retire cette contrainte, et c&#8217;est très bien ainsi.</p>
<p>Mais ne nous demandez pas de changer le blog, ça na pas de sens.</p>
<p>Par ailleurs, ce qui me dérange dans ces demandes, c&#8217;est que leurs auteurs n&#8217;envisagent pas de faire un effort de leur côté, et nous demandent d&#8217;en faire un. Le blog est sous Creative Common, quelqu&#8217;un pourrait sans problème en faire une version SFW. Il existe <a href="http://sametmax.com/telechargez-le-blog-en-entier-pour-le-lire-hors-ligne/">un dump du blog</a>, il est donc consultable hors ligne. On peut aussi imaginer que la personne lise uniquement le blog en dehors du bureau. Ou alors qu&#8217;elle s&#8217;installe un proxy anonymisant. On peut aussi désactiver les images dans un Firefox, pour éviter de se faire griller en Open Space, ou utiliser Lynx. On peut aussi en parler à ses collègues et ses boss, et régler le problème avec le dialogue. Bref, il y a des tas de solutions à ce problème, et étant donné que nous fournissons un travail colossal avec ce blog (on en est à 500 articles, mine de rien, ça fait presque deux bouquins, en moins de 2 ans), je crois qu&#8217;il est important que vous vous responsabilisiez un peu.</p>
<p>Oh, et non, je ne pense pas aux enfants. Les enfants ne sont pas traumatisés par la pornographie, les enfants sont traumatisés par les adultes qui sont gênés en parlant de sexe et qui ne sont pas capables de remettre les choses dans leur contexte.</p>
<p><strong>Ceci n&#8217;est pas un article destiné à être vindicatif ou moraliste. Je comprends parfaitement la position des personnes qui nous font ces demandes. Comprenez vous aussi, que c&#8217;est non.</strong></p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6667&amp;md5=792c7751cb0559a50a2924e208781c11" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6673
title: Sam et Max en quelques chiffres
uri: Sam-et-Max-en-quelques-chiffres
url: http://sametmax.com/sam-et-max-en-quelques-chiffres/
content:
<p>haaaaa les stats, j&#8217;adore ça moi, c&#8217;est étroitement lié au métier de webmaster ceci dit. Un jour sans regarder les stats c&#8217;est comme un jour sans pignole.</p>
<p><strong>Voici Sametmax.com en quelques chiffres pour les curieux:</strong></p>
<p><strong>Date de création:</strong> 4 février 2012<br />
<strong>Articles:</strong> 505<br />
<strong>Tags:</strong> 748<br />
<strong>Commentaires:</strong> 6472<br />
<strong>Premier inscrit: </strong>roro<br />
<strong>Premier commentateur: </strong>roro le <a href="http://sametmax.com/purger-les-fichiers-pyc-et-un-hook-git-en-bonus/#comment-59">2012/04/23 at 01:27</a><br />
<strong>Tampons:</strong> 208<br />
<strong>Spams:</strong> 33,249<br />
<strong>Visites par mois:</strong> 100,862<br />
<strong>Vistes depuis la création du blog:</strong> 837,446<br />
<strong>Moteurs de recherche (par mois):</strong> 38,312<br />
<strong>Mots clefs:</strong> masturbation feminine, fkk, freeplug, sex japon, abreviation escort, git stash, sublime text 2, ubuntu 12.10, node.js &#8230;</p>
<p><strong>Les posts les plus vus:</strong></p>
<table cellspacing="0">
<tbody>
<tr>
<td><a href="http://sametmax.com/">Home page / Archives</a></td>
<td><a href="http://sametmax.com/wp-admin/admin.php?page=stats&amp;view=post&amp;post=0"><img src="media/ab0bfaa3.stats-icon.png" data-original-source="http://dashboard.wordpress.com/i/stats-icon.png" alt="More stats" /></a></td>
<td>201,116</td>
</tr>
<tr>
<td><a href="http://sametmax.com/un-peu-de-theorie-sur-la-masturbation-feminine-en-video/" target="_blank">Masturbation féminine – Un peu de théorie en vidéo</a></td>
<td><a href="http://sametmax.com/wp-admin/admin.php?page=stats&amp;view=post&amp;post=4166"><img src="media/ab0bfaa3.stats-icon.png" data-original-source="http://dashboard.wordpress.com/i/stats-icon.png" alt="More stats" /></a></td>
<td>95,796</td>
</tr>
<tr>
<td><a href="http://sametmax.com/synchroniser-les-freeplugs-les-adaptateurs-reseaux-cpl-de-free/" target="_blank">Synchroniser les freeplugs (les adaptateurs réseaux CPL de free)</a></td>
<td><a href="http://sametmax.com/wp-admin/admin.php?page=stats&amp;view=post&amp;post=1259"><img src="media/ab0bfaa3.stats-icon.png" data-original-source="http://dashboard.wordpress.com/i/stats-icon.png" alt="More stats" /></a></td>
<td>33,993</td>
</tr>
<tr>
<td><a href="http://sametmax.com/une-journee-dans-un-fkk-maison-close-allemande/" target="_blank">Une journée dans un FKK (maison close Allemande)</a></td>
<td><a href="http://sametmax.com/wp-admin/admin.php?page=stats&amp;view=post&amp;post=4275"><img src="media/ab0bfaa3.stats-icon.png" data-original-source="http://dashboard.wordpress.com/i/stats-icon.png" alt="More stats" /></a></td>
<td>32,124</td>
</tr>
<tr>
<td><a href="http://sametmax.com/les-japonais-et-le-sexe-des-gros-malades-ou-pas/" target="_blank">Les Japonais et le sexe – des gros malades… Ou pas…</a></td>
<td><a href="http://sametmax.com/wp-admin/admin.php?page=stats&amp;view=post&amp;post=1009"><img src="media/ab0bfaa3.stats-icon.png" data-original-source="http://dashboard.wordpress.com/i/stats-icon.png" alt="More stats" /></a></td>
<td>20,968</td>
</tr>
<tr>
<td><a href="http://sametmax.com/10-astuces-pour-sublime-text-2/" target="_blank">10 astuces pour Sublime Text 2</a></td>
<td><a href="http://sametmax.com/wp-admin/admin.php?page=stats&amp;view=post&amp;post=744"><img src="media/ab0bfaa3.stats-icon.png" data-original-source="http://dashboard.wordpress.com/i/stats-icon.png" alt="More stats" /></a></td>
<td>14,013</td>
</tr>
<tr>
<td><a href="http://sametmax.com/les-abreviations-dans-le-domaine-adulte-vous-connaissez/" target="_blank">Les abréviations de la prostitution et des Escorts, vous connaissez ?</a></td>
<td><a href="http://sametmax.com/wp-admin/admin.php?page=stats&amp;view=post&amp;post=3016"><img src="media/ab0bfaa3.stats-icon.png" data-original-source="http://dashboard.wordpress.com/i/stats-icon.png" alt="More stats" /></a></td>
<td>13,430</td>
</tr>
<tr>
<td><a href="http://sametmax.com/il-ne-faut-pas-prendre-des-gens-pour-des-cons-mais-ne-jamais-oublier-quils-en-sont/" target="_blank">Il ne faut pas prendre des gens pour des cons mais ne jamais oublier qu’ils en sont</a></td>
<td><a href="http://sametmax.com/wp-admin/admin.php?page=stats&amp;view=post&amp;post=5468"><img src="media/ab0bfaa3.stats-icon.png" data-original-source="http://dashboard.wordpress.com/i/stats-icon.png" alt="More stats" /></a></td>
<td>12,302</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><strong>Le pognon que ça nous rapporte:</strong></p>
<p>Non contents d&#8217;avoir asséché le trafic des autres blogs du net grâce à nos articles sulfureux écrits d&#8217;une plume féérique nous avons également pulvérisé tous les records précédents en terme de monétisation.</p>
<p>Depuis que Sam a mis Flattr sur S&amp;M on a récolté <strong>45€</strong>. Ce qui paie le serveur (environ 5€/mois en VPS chez <a href="http://www.leaseweb.com/en/cloud-hosting">leaseweb</a>).</p>
<p>Si vous voulez d&#8217;autres chiffres demandez-nous et nous les rajouterons.</p>
<p>Allez voir <a href="http://sametmax.com/python-django-git-et-du-cul/">le premier post</a> par nostalgie ;)</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6673&amp;md5=bbc8960f851679aa91f11f202f71777b" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6686
title: On a un nouveau projet et on a besoin d’UNE info sur vous
uri: On-a-un-nouveau-projet-et-on-a-besoin-d-UNE-info-sur-vous
url: http://sametmax.com/on-a-un-nouveau-projet-et-on-a-besoin-dune-info-sur-vous/
content:
<p>On bosse sur un projet (on en parlera à la sortie, si sortie il y a) WebRTC, qui est une techno très peu stable et pas finie.</p>
<p>Problème, le data channel actuellement marche entre Firefox, et entre Chrome, mais pas entre Firefox et Chrome. Safari, IE, Opera et autre ne marchent juste pas.</p>
<p>Histoire de simplifier les choses, on va le lancer pour un seul navigateur et prétendre que ça ne marche pas sur l&#8217;autre, pour éviter que l&#8217;utilisateur se retrouve avec un comportement &#8220;on/off&#8221; selon la personne qu&#8217;il a en face.</p>
<p>On ne va pas se baser sur les stats générales d&#8217;utilisation car on est interessé par les lecteurs qui commentent, c&#8217;est à dire ceux qui seront les premiers concernés par le projet quand on le sortira.</p>
<p>Donc petit sondage : <strong>quel navigateur utilisez-vous le plus toute la journée ?</strong></p>
<p>Un comment, une réponse : soit Firefox, soit Chrome.</p>
<p>Si autre, ce sera pour une prochaine fois ^^ (évidement on va ajouter les autres nav au fur et à mesure)</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6686&amp;md5=0f3f549f481ce778d1cd37cfc8939300" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6702
title: Bitcoin: créer un portefeuille, obtenir des bitcoins et payer
uri: Bitcoin-créer-un-portefeuille-obtenir-des-bitcoins-et-payer
url: http://sametmax.com/bitcoin-creer-un-portefeuille-obtenir-des-bitcoins-et-payer/
content:
<p>Vous avez <a href="http://sametmax.com/tag/bitcoin/">tout lu sur Bitcoin</a> et vous êtes convaincus. Tant pis si c&#8217;est instable, tant pis si ça peut s&#8217;arrêter demain, vous voulez essayer.</p>
<h2>Mais on commence par où ?</h2>
<p>D&#8217;abord, il faut se créer un portefeuille Bitcoin. Si vous voulez soutenir le mouvement Bitcoin jusqu&#8217;au bout, il est bon d&#8217;utiliser un client complet comme <a href="http://bitcoin.org/fr/telecharger">Bitcoin-Qt</a>. Malheureusement ça veut dire qu&#8217;il faut avoir 15 Go d&#8217;espace disque rien que pour le logiciel, et le laisser tourner toute la nuit la première utilisation. Dur dur, quand on débute.</p>
<p>Pour cette raison, je vais vous inviter à commencer par un truc plus simple : <a href="http://electrum.org/">Electrum</a>.</p>
<p><strong>WARNING : Bitcoin est une technologie internet. Il ne sert à rien sans Internet. Connectez-vous, et assurez vous d&#8217;être à un endroit qui ne bride pas votre connexion.</strong></p>
<p>C&#8217;est un logiciel Python qui fonctionne sur Windows, Mac et Linux. Il est encore jeune, mais plutôt bien foutu. L&#8217;installation est un peu particulière, heureusement la <a href="http://electrum.org/download.html">page d&#8217;explication</a> est bien faite.</p>
<h2>Création du portefeuille</h2>
<p>Au démarrage, le logiciel va vous dire qu&#8217;il ne trouve pas de portefeuille et va vous demander si vous voulez en créer un ou en restaurez un. Créez-en un.</p>
<p>Electrum va créer un nouveau wallet et vous afficher ce qu&#8217;on appelle une &#8220;seed&#8221; :</p>
<div id="attachment_6703" class="wp-caption aligncenter" style="width: 516px"><a href="media/ab527755.seed.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/seed.jpg"><img src="media/ab527755.seed.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/seed.jpg" alt="Capture d&#039;écran d&#039;une seed fournie par Electrum" title="Evidement, ce n&#039;est pas la seed de mon portefeuille réel, bande de brigants !" width="506" height="408" class="size-full wp-image-6703" /></a><p class="wp-caption-text">Evidement, ce n&#039;est pas la seed de mon portefeuille réel, bande de brigants !</p></div>
<p>C&#8217;est un moyen de récupérer votre portefeuille si vous le perdez. Soit vous gardez le QR code, soit vous notez les mots quelque part, avec une parfaite précision sur les lettres et l&#8217;ordre.</p>
<p>Cachez cela dans un endroit sûr. J&#8217;ai dis sûr. Pas un copier / coller sur votre dossier perso, pas sur un post-it dans votre bureau ou sac à main.</p>
<p><strong>Quiconque tombe sur cette information peut récupérer tout votre pognon.</strong></p>
<p>Copier votre seed, et appuyez sur &#8220;ok&#8221;. Electrum va vous demandez de rentrer votre seed. C&#8217;est pour voir si vous suivez :-)</p>
<p>Coller votre seed et validez.</p>
<p>On va vous demander de choisir un serveur avec une fenêtre un peu compliquée, OSEF pour le moment, faites juste &#8220;ok&#8221;.</p>
<p>Là vient la phrase fatidique : choisir un mot de passe pour votre portefeuille.</p>
<p>Choisissez un très <a href="http://sametmax.com/un-mot-de-passe-facile-a-retenir/">très bon mot de passe</a>, que vous êtes certain de retenir.</p>
<p>Et voilà, vous avez votre portefeuille.</p>
<h2>Gagner des sous</h2>
<p>Votre portefeuille est bien vide, il va falloir le nourrir.</p>
<p>Pour cela vous avez plusieurs choix, comme dans la vie réelle :</p>
<ul>
<li>Travailler pour des bitcoins. Si vous connaissez des gens qui ont des btc, vous pouvez vous faire embaucher par eux, comme dans un SEL. Si vous êtes freelance, acceptez les btc aussi en paiement. <a href="http://bitcoinrate.com/">N&#8217;oubliez pas de regardez le cours</a>. Il existe des <a href="http://forbitcoin.com/">sites d&#8217;annonces de jobs</a> pour des bitcoins, même si ça vise beaucoup les USA.</li>
<li>Vendre pour des bitcoins. Si vous connaissez des gens qui ont des bitcoins, vous pouvez leur vendre des objets. Ou simplement le faire à travers <a href="http://aubitcoin.fr/">un site de petites annonces</a> en bitcoins (il y en a de nombreux). Si vous avez un ebook ou des trucs du genre, mettez le à vendre en bitcoins. Mieux, si vous avez un commerce, affichez que vous acceptez les bitcoins.</li>
<li>Accepter les donations en bitcoins. Il suffit de mettre une adresse Bitcoin sur votre site Web si vous en avez un, et les gens pourront vous faire une donation. C&#8217;est ce que nous faisons en bas à droite du blog.</li>
</ul>
<p>En parlant d&#8217;adresse Bitcoin&#8230;</p>
<p>Si vous allez dans l&#8217;onglet &#8220;recevoir&#8221; d&#8217;Electrum, vous verrez ceci :</p>
<div id="attachment_6704" class="wp-caption aligncenter" style="width: 431px"><a href="media/77e0a9e5.receive1.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/receive1.jpg"><img src="media/77e0a9e5.receive1.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/receive1.jpg" alt="Capture d&#039;écran de l&#039;onget &quot;recevoir&quot; du logiciel electrum" title="&quot;Blog&quot; est une adresse réutilisée, &quot;vente de chiouaoua&quot; ne sera utilsée qu&#039;une fois" width="421" height="232" class="size-full wp-image-6704" /></a><p class="wp-caption-text">&quot;Blog&quot; est une adresse réutilisée, &quot;vente de chiouaoua&quot; ne sera utilsée qu&#039;une fois</p></div>
<p>A gauche, ce sont vos adresses. C&#8217;est ce qui vous permet de recevoir des sous. Donnez cette adresse à quelqu&#8217;un, et il peut vous envoyer des bitcoins.</p>
<p>A droite, c&#8217;est le nom que vous donnez à l&#8217;adresse. Seul vous le verra. C&#8217;est pour vous permettre de vous y retrouver.</p>
<p><strong>Vous avez un nombre infini d&#8217;adresses</strong>, Electrum va en créer au fur et à mesure que vous en utilisez. <strong>Chaque adresse peut être utilisée un nombre infini de fois.</strong></p>
<p>Mon conseil :</p>
<ul>
<li>Si c&#8217;est une adresse pour un don (ou une quelconque attitude permanente), utilisez toujours la même.</li>
<li>Si c&#8217;est une adresse pour une transaction dans le cadre d&#8217;une vente ou d&#8217;un travail, utilisez-en toujours une différente.</li>
</ul>
<p>La raison à cela c&#8217;est que plus vous utilisez d&#8217;adresses, plus il est difficile de faire le lien entre vous et les transactions.</p>
<p>Faites bien attention en donnant une adresse, copier bien TOUTE l&#8217;adresse. Une adresse, c&#8217;est très long, et c&#8217;est compliqué. Par exemple :</p>
<p>1MKn4yhJkpYAA4PxfFg4PVUnCmSTmWJnXp</p>
<p>Et relisez bien que vous avez posté la bonne. <strong>Les transactions Bitcoin sont irréversibles</strong>.</p>
<p>Moi je regarde les 3 premiers et les 3 derniers caractères de l&#8217;adresse pour m&#8217;assurer que je n&#8217;ai pas merdé.</p>
<h2>Acheter des sous</h2>
<p>Pour démarrer, vous n&#8217;aurez pas forcément de source de revenue Bitcoin. Peut être voudrez-vous en achetez contre des euros. Il existe des places de marché pour cela.</p>
<p>Ma préférée est <a href="https://www.bitcoin.de/en">bitcoin.de</a>, mais j&#8217;en ai changé deux fois. Je vous invite donc a en essayer plusieurs, et surtout, à <strong>ne JAMAIS laisser beaucoup de bitcoins sur le compte de ces sites</strong>. Dès qu&#8217;un échange est terminé, faites un virement vers votre portefeuille. Tout le principe de Bitcoin est de ne pas avoir de &#8220;compte en banque&#8221;.</p>
<p>De nombreuses places de marché ont connu des problèmes par le passé : attaques, bugs, incompétence, malveillance, arnaques&#8230; Vos bitcoins ne sont en sécurité que dans VOTRE portefeuille. Ou plutôt dans vos portefeuilles, quand vous en aurez beaucoup, car il ne faut pas mettre tous ses œufs dans le même panier.</p>
<p>Je ne vais pas expliquer comment fonctionne bitcoin.de : c&#8217;est très classique. Inscription, remplissage de profile, et ensuite on dit ce qu&#8217;on veut acheter ou vendre.</p>
<p>Le paiement se fait par virement SEPA, ce qui est gratuit et prend 1 minute depuis la plupart des interfaces de banque en ligne.</p>
<p>Si vous achetez, bitcoin.de va vous alerter par email quand, combien et à quel compte faire le versement. Une fois le virement reçu, votre interlocuteur valide la transaction et votre compte bitcoin.de est crédité des bitcoins. A vous de transférer les bitcoins depuis ce compte vers votre portefeuille via le menu &#8220;Deposit and disbursement of Bitcoins&#8221;.</p>
<p>Si vous vendez, il faut créditer le compte bitcoin.de avec des bitcoins. Ensuite vous serez autorisé à vendre ce montant maximum. Il faudra aussi avoir rempli vos coordonnées (RIB) bancaires dans votre profile. L&#8217;argent sera viré directement sur ce compte. N&#8217;oubliez pas de valider la transaction une fois l&#8217;argent reçue pour que votre interlocuteur soit crédité des bitcoins.</p>
<p>Commencez par de petites sommes (50 euros), ça vous permettra de vous faire la main.</p>
<p>Il existe d&#8217;autres voies plus ou moins légales pour échanger du Bitcoin contre de l&#8217;argent. Celle-ci est juste la plus simple et la plus sûre.</p>
<h2>Envoyer des sous</h2>
<p>Ça y est, vous avez du pognon dans votre portefeuille !</p>
<p>Il est temps d&#8217;aller flamber. C&#8217;est fort simple, il suffit d&#8217;aller dans l&#8217;onglet &#8220;Envoyer&#8221; d&#8217;Electrum et d&#8217;entrer l&#8217;adresse vers laquelle vous voulez envoyer des bitcoins :</p>
<div id="attachment_6705" class="wp-caption aligncenter" style="width: 431px"><a href="media/47c67e02.send1.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/send1.jpg"><img src="media/47c67e02.send1.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/send1.jpg" alt="Capture d&#039;écran de l&#039;onglet &quot;envoyer&quot; du logiciel Electrum" title="Une bonne description de la transaction est important pour quand vous ferez vos comptes plus tard" width="421" height="232" class="size-full wp-image-6705" /></a><p class="wp-caption-text">Une bonne description de la transaction est important pour quand vous ferez vos comptes plus tard</p></div>
<p><strong>ATTENTION : l&#8217;envoie et la réception des bitcoins n&#8217;est pas instantané. Cela peux prendre une dizaine de minutes. Ne paniquez pas.</strong></p>
<p>Vous noterez qu&#8217;il y a une case &#8220;frais&#8221;. Cette case est facultative, vous n&#8217;avez pas à mettre quoique ce soit dedans. Néanmoins, cette somme, qui par ailleurs est ridiculement petite, va encourager les nœuds bitcoins à traiter votre transfert en priorité. Je vous invite à toujours le faire, sinon votre virement va prendre des plombes, voir des jours, et pour 5 centimes pour 75 euros de virement, faut pas déconner.</p>
<p>Enfin, le Bitcoin est divisible, n&#8217;hésitez pas à acheter des 0.x ou x.z de bitcoins, c&#8217;est tout à fait normal.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6702&amp;md5=255e2c2ad63a56ac537fed927cbe2c6f" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6731
title: Le fichier .gitkeep
uri: Le-fichier-gitkeep
url: http://sametmax.com/le-fichier-gitkeep/
content:
<p>On ne peut pas commiter les dossiers vides avec git, si il n&#8217;y a pas de fichier dedans, git ignorera le dossier. Parfois, quand on veut partager une arborescence très précise, c&#8217;est handicapant. Il s&#8217;est donc créé une convention dans la communauté : le fichier <em>.gitkeep</em>.</p>
<p>C&#8217;est un fichier vide, nommé, comme vous pouvez l&#8217;imaginer, <em>.gitkeep</em>, et que l&#8217;on met dans chaque dossier que l&#8217;on veut garder. On ajouter le fichier à l&#8217;index, et on commit. Dès que le dossier n&#8217;est plus vide, on supprime le fichier <em>.gitkeep</em>, et on le commit.</p>
<p>Cependant on veut parfois garder un dossier vide, et qu&#8217;il n&#8217;y ait jamais de fichier dedans, comme par exemple le dossier <em>/static/</em> de Django si vous distribuez un software à base de ce framework, puisqu&#8217;il doit servir à vos utilisateurs pour y mettre <strong>leurs</strong> fichiers statiques plus tard. Il serait donc embêtant de mettre un fichier dedans par erreur et le commiter.</p>
<p>Pour éviter cela, il suffit de créer un fichier <em>.gitignore</em> dedans, et de lui donner ces règles :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">*</span>           <span style="color: #666666; font-style: italic;"># git ignore tous les fichiers</span>
<span style="color: #000000; font-weight: bold;">!</span>.gitignore <span style="color: #666666; font-style: italic;"># sauf celui-ci</span></pre></div></div>

<p>Ce qui aura pour effet d&#8217;interdire le moindre ajout de fichier du dossier en question dans Git, à part le <em>.gitignore</em>, évidement.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6731&amp;md5=7b48773738f34a48ff4758949915800c" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6725
title: Envie de meurtre
uri: Envie-de-meurtre
url: http://sametmax.com/envie-de-meurtre/
content:
<p>Oui, je tape beaucoup sur nodejs et la communauté javascript en général. Mais ils le méritent, bordel !</p>
<p>Je tombe sur un projet OpenSource qui est sorti en janvier dernier. Ils vendent leur popote &#8220;As A Service&#8221;, donc a priori, on pourrait se dire qu&#8217;ils voudraient qu&#8217;on les prennent au sérieux.</p>
<p>Ils fournissent un serveur pour se faire la main en local avant de taper dans leur API payante. Cool. Merci.</p>
<p>D&#8217;abord, il faut évidement passer par l&#8217;installation de node et tout le bordel. Bon, admettons. Même si Python est installé par défaut, il faut bien installer <a href="http://sametmax.com/votre-python-aime-les-pip/">pip</a>.</p>
<p>Mais ensuite, au lancement du serveur, rien. Il reste là, silencieusement. Pas de mode verbose, un mode debug qui ne fait absolument rien.</p>
<p>Mon code client se connecte, et puis nada. Silence radio sur leur lib client et serveur. Vide intersidéral.</p>
<p>La doc est succincte (3 pages) et rien qui ne parle du problème. Question sur la mailling list. Pas de réponse.</p>
<p>A ce stade j&#8217;en ai déjà ras le cul. Les libs node qui marchent pas et qui en plus veulent pas mettre un putain de message d&#8217;erreur, y en a déjà un paquet. C&#8217;est une épidémie dans cette communauté.</p>
<p>Mais je retrousse mes manches, et je vais voir dans le code source.</p>
<p>Et là, je tombe sur 400 lignes de ça :</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">    <span style="color: #003366; font-weight: bold;">var</span> client<span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>self._clients<span style="color: #009900;">&#91;</span>key<span style="color: #009900;">&#93;</span> <span style="color: #339933;">||</span> <span style="color: #339933;">!</span><span style="color: #009900;">&#40;</span>client <span style="color: #339933;">=</span> self._clients<span style="color: #009900;">&#91;</span>key<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>id<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>req.<span style="color: #660066;">params</span>.<span style="color: #660066;">retry</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        res.<span style="color: #660066;">send</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">401</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #006600; font-style: italic;">// Retry this request</span>
        req.<span style="color: #660066;">params</span>.<span style="color: #660066;">retry</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span>
        setTimeout<span style="color: #009900;">&#40;</span>handle<span style="color: #339933;">,</span> <span style="color: #CC0000;">25</span><span style="color: #339933;">,</span> req<span style="color: #339933;">,</span> res<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
      <span style="color: #000066; font-weight: bold;">return</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<p>C&#8217;est un appel au génocide, un style de coding comme ça ! Sérieusement, déjà Javascript est un langage moche, avec un scoping de merde, du nesting en pagaille et tout un tas de pièges qui fait que le code est dur à lire et à comprendre.</p>
<p>Mais là, vous imaginez la concentration qu&#8217;il faut pour lire ces 10 putains de lignes ? Et les remettre dans le contexte du script complet (qui au passage est commenté comme un diabétique sucre son café).</p>
<p>C&#8217;est trop dur de ne pas pondre des trucs innommables comme <code>!(client = self._clients[key][id])</code> ? Un ligne de plus a taper. Trop difficile de mettre des noms de variables complets ? <code>id</code>, mais id de quoi connard ? Je remonte tout le script pour m&#8217;en souvenir ? Et pourquoi tu assignes <code>client = self._clients</code>  si c&#8217;est pour ne pas t&#8217;en servir ? Et puis un double if imbriqué suivi d&#8217;un appel récursif asynchrone, c&#8217;est tellement fun pour suivre le workflow ! </p>
<p>400 lignes comme ça, après le dîner, ça fout la chiasse. Alors oui, c&#8217;est de l&#8217;open source, faut pas faire le difficile, etc.</p>
<p>Mais bordel, qu&#8217;on ne vienne pas me dire que c&#8217;est l&#8217;avenir. Les ex-script kiddies d&#8217;hier, codeurs PHP et VB, commencent à peine à écrire du code propre. Et là grosso modo on va se taper la vague des intégrateurs Web qui se mettent à coder parce que c&#8217;est du JS comme dans le navigateur ?</p>
<p>GGGGGGGGGGGGRRRRRRRRRRRRRRRRRRRRRRRR !</p>
<p>Je devrais faire une émission style &#8220;joueur du grenier&#8221;, mais pour le code pourri.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6725&amp;md5=d9304974a5ce847e095fa0f1fd3dd254" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6737
title: Django, une app à la fois : routes nommés et liens dynamiques
uri: Django-une-app-à-la-fois-routes-nommés-et-liens-dynamiques
url: http://sametmax.com/django-un-app-a-la-fois-routes-nommes-et-liens-dynamiques/
content:
<p>J&#8217;ai rajouté une app dans le <a href="https://github.com/sametmax/Django--an-app-at-a-time">repo</a> du <a href="http://sametmax.com/django-une-app-a-la-fois/">projet django, une app à la fois.</a></p>
<p>Cette fois je fais la démonstration des URLS nommées, qui permet d&#8217;avoir un découplage propre entre les vues, le template et les routes.</p>
<p>Comme d&#8217;hab il y a une version française et anglaise commentées, et comme d&#8217;hab, ça m&#8217;a pris 3 plombes alors que je m&#8217;étais dis que cette fois, promis, je ferai court.</p>
<p>Je sers la science et c&#8217;est ma joie.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6737&amp;md5=c9748d021b18756a6d1a0c8995389255" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6765
title: Fêtons le départ de Max
uri: Fêtons-le-départ-de-Max
url: http://sametmax.com/fetons-le-depart-de-max/
content:
<p>Je crois que tout le monde est au courant, Max quitte la bride de la France pour retrouver les bridés de Thaîlande. Il faut marquer le coup, non ?</p>
<p>Alors on a pondu un petit jeu :</p>
<p><a href="http://game.sametmax.com">Ouvrez le coffre !</a></p>
<p><strong>Le principe est simple, le premier qui arrive au bout de la série d&#8217;énigmes a gagné.</strong></p>
<p>Le jeu encourage la programmation, particulièrement Python, mais peut être résolu de plusieurs manières, certains plus élégantes que d&#8217;autres :) C&#8217;est très orienté nerd.</p>
<p>Dans tous les cas j&#8217;ai codé ça un peu à l&#8217;arrache car on a eu l&#8217;idée en milieu d&#8217;après-midi, alors si ça se trouve il y a des failles à exploiter pour gagner plus vite. Même un petit brute-force, ça se tente (même si je pense que le serveur mourra avant d&#8217;avoir progressé de 10% et que c&#8217;est celui du blog \o/).</p>
<p>Bref, y a pas de règle à part que normalement le jeu se désactive une fois que le premier joueur ouvre le coffre. Mais n’hésitez pas à mettre un com si vous trouvez un bug qui vous empêche la progression. Cela dit, si vous êtes bloqué, y a quand même plus de chance que ce soit parce que vous n&#8217;avez pas trouvé la solution. Et là, on vous aidera pas ^^</p>
<p>Sachez quand même que j&#8217;ai fais le jeu plusieurs fois, et pondu des scripts en conséquences pour tester que ça marche bien comme prévu.</p>
<p>Quand à savoir ce qu&#8217;il y a dans le coffre&#8230;</p>
<hr />
<p>Le jeu est terminé, le <a href="http://sametmax.com/code-source-du-jeu/">code source</a> est en ligne.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6765&amp;md5=e02dc044fe13016feb5af8167efeb719" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6773
title: Le coffre a été ouvert !
uri: Le-coffre-a-été-ouvert
url: http://sametmax.com/le-coffre-a-ete-ouvert/
content:
<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="420" height="315" src="//www.youtube.com/embed/69AyYUJUBTg" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<p>J&#8217;avais dosé une difficulté sans trop savoir jusqu&#8217;où aller car le niveau de prog sur le blog est plutôt disparate, et afin de laisser sa chance à tout le monde. Mais ce mail me fait assez plaisir quant au résultat.</p>
<p>Le gagnant a ouvert <a href="http://sametmax.com/fetons-le-depart-de-max/">le coffre</a> et nous a contacté à 2 heures du math :</p>
<blockquote>
<p>Salut les gars !</p>
<p>Bon visiblement j&#8217;ai réussi à pénétrer le petit coffre rouge en premier [censored].</p>
<p>Alors tout d&#8217;abord un gros merci pour le taff que vous faites sur votre blog. Je vous ai découvert y&#8217;a un peu plus d&#8217;un an en cherchant des infos sur Django et Python que je ne connaissait pas du tout à l&#8217;époque. Et depuis je ne vous lâche plus et je me régale de vos articles (bien que je fasse parti de la masse discrète en ne commentant jamais …). Un an plus tard me voilà à appliquer des techniques apprises (en partie) sur votre blog (json, pickle, etc.). </p>
<p>Première fois que je résout un challenge de ce genre, c&#8217;était bien sympathique (un peu prise de tête par moment mais quel bonheur à chaque pas réaliser), bravo pour la réalisation en tout cas !</p></blockquote>
<p>On voit les acharnés !</p>
<p>Comme pour <a href="http://sametmax.com/le-cadeau-de-noel-est-arrive/">le cadeau de la dernière fois</a>, on va lui demander d&#8217;envoyer une petite photo de ce qui l&#8217;a reçu et on la postera pour que vous découvriez tous ensemble ce qu&#8217;il y avait a gagner. Ça restera donc une surprise jusqu&#8217;au déballage (mais moi je suis jaloux parce que j&#8217;en voulais un).</p>
<p>Si notre gagnant à le courage, ce serait marrant qu&#8217;il fasse un article pour expliquer comment il a passé les énigmes, et poster son code. Tu nous le dis en comment si tu es chaud ?</p>
<p>Dans tous les cas je laisse le jeu en ligne quelques jours pour le fun, et on le retirera, puis on mettera le code source sur github.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6773&amp;md5=6d731314be281cf278597341907323b3" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6781
title: Colis envoyé !
uri: Colis-envoyé
url: http://sametmax.com/colis-envoye/
content:
<p>Le colis pour le gagnant du jeu est parti.</p>
<p>Il a écrit un article pour montrer ses codes qu&#8217;il faudra publier, et moi je posterai les sources du jeu dès que j&#8217;ai plus de temps.</p>
<p>A pluche.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6781&amp;md5=57c42c8c99386ff201446a82db75a537" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6788
title: Code source du jeu
uri: Code-source-du-jeu
url: http://sametmax.com/code-source-du-jeu/
content:
<p>Mraaaah vient d&#8217;avoir un compte sur le blog, et peut être aura-t-il le temps de publier les sources de ses solutions. En attendant, <a href="https://github.com/sametmax/crack_the_safe">voici le code source du jeu</a>.</p>
<p>En général on documente un peu le truc, on met un README, des commentaires, etc. Mais là je vais invoquer le fait que je veux vous montrer ce que ça donne un code à la vite pour justifier ma grosse flemme.  Ce code source est intéressant car il montre plusieurs choses :</p>
<ul>
<li>On peut coder en très peu de lignes un truc comme ça en Python. </li>
<li>Nous aussi on fait du code à l&#8217;arrache : ici un truc pondu en une après-midi, non commenté, écrit d&#8217;une traite.</li>
<li>Les <a href="http://sametmax.com/sept-petites-libs-qui-changent-la-vie-dun-dev-python/">petites libs</a> comme path.py ou bottle, ça aide bien.</li>
<li>Quand on fait les trucs trop vites, il y a des coquilles : dans notre cas on a une lib qui sert à rien, le check du mot de passe final sur la mauvaise fonction, etc. Et c&#8217;est pas scalable pour deux ronds.</li>
<li>Même quand on code mal en Python, ça reste assez lisible.</li>
<li>Python, c&#8217;est pas si lent : malgré un code d&#8217;init lourd et un serveur en pur Python (cherrypy) qui s&#8217;est pris vos essais de bourrins, ça démarre vite et ça a bien tourné.</li>
</ul>
<p>Vous trouverez dans le répertoire <em>scripts</em> les soluces des énigmes que j&#8217;ai utilisé pour vérifier que ça marchait. Vous verrez que là aussi, c&#8217;est du vite fait, avec parfois des trucs qui plantent tout simplement par fainéantise.</p>
<p>Pour démarrer le jeu : <code>python site.py</code> avec du 2.7.</p>
<hr />
<p>Mraaaah a publié <a href="http://sametmax.com/ouverture-du-coffre-la-methode-simple-bourine-mais-efficace/">ses solutions</a>.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6788&amp;md5=3f2c80b88c237ee79102ca57245e2860" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6789
title: Ouverture du coffre : la méthode simple, bourine, mais efficace
uri: Ouverture-du-coffre-la-méthode-simple-bourine-mais-efficace
url: http://sametmax.com/ouverture-du-coffre-la-methode-simple-bourine-mais-efficace/
content:
<p style="text-align: center;"><em><small>Ceci est un post invité de <a href="http://sametmax.com/author/MrAaaah/">MrAaaah</a> posté sous licence <a href="http://creativecommons.org/licenses/by/3.0/">creative common 3.0 unported</a>.</small></em></p>
<p>Salut à toutes et à tous c&#8217;est MrAaaah, je suis celui qui réussi à résoudre le plus rapidement les énigmes du <a href="http://sametmax.com/fetons-le-depart-de-max/">coffre secret de Sam et Max</a>, on ma demandé de vous faire un &quot;petit&quot; article expliquant un peu ma démarche et mes méthodes.</p>
<h2 id="avant-propos">Avant-propos</h2>
<p>Avant de me lancer dans la résolution des énigmes je tiens à signaler que je n&#8217;ai qu&#8217;un an de python dans les pattes, de ce fait le code peut paraitre cradoc et peut-être un poil bourrin vu que je ne connais pas encore très bien python, ses librairies et ses subtilités (ça a également été codé très vite). Je n’ai pas retouché le fonctionnement de mes scripts, j&#8217;ai juste renommé quelques variables et mis des commentaires, donc c&#8217;est du brut, y&#8217;a pas de vérif, ça plante à la fin, etc.</p>
<h2 id="yunoopen">Y U NO OPEN?</h2>
<p><a href="http://sametmax.com/ouverture-du-coffre-la-methode-simple-bourine-mais-efficace/attachment/36924691/" rel="attachment wp-att-6790"><img src="media/0f1ee8fe.36924691.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/36924691.jpg" alt="Un petit meme : &quot;Code Y U NO WORK?&quot;" title="Code Y U NO WORK?" width="400" height="300" class="aligncenter size-full wp-image-6790" /></a></p>
<p>Première énigme <a href="http://game.sametmax.com/">http://game.sametmax.com/</a> : un message, un champ d&#8217;entrée et une image. Comme beaucoup je suppose, je commence par rentrer diverses conneries dans le formulaire, toujours le même résultat : le message &#8220;<strong>I don&#8217;t GET it.</strong>&#8221;.</p>
<p>Je parcours le code source de la page à la recherche d&#8217;un éventuel script où autre indice dans le code, nada.</p>
<p>Si on regarde l&#8217;url on peut voir que le code est envoyé via la méthode <em>GET</em> : http://game.sametmax.com/<strong>?code=monnezsurtescouilles</strong>. En relisant le message de ci-dessus on peut deviner qu&#8217;il faut balancer une requête de type <em>POST</em>. Pour faire ça rien de plus simple, on sort <em>Firebug</em> (ou équivalent), on édite le code source en changeant l&#8217;attribut <strong>method</strong> du formulaire et on renvoi avec un code bidon.</p>
<p><a href="http://sametmax.com/ouverture-du-coffre-la-methode-simple-bourine-mais-efficace/fb/" rel="attachment wp-att-6796"><img src="media/3f86d5e7.fb.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/fb.png" alt="Modification de la methode d&#039;envoi d&#039;un formulaire avec Firebug." title="Firebug" width="679" height="439" class="aligncenter size-full wp-image-6796" /></a></p>
<p>Là on obtient un nouveau message : &#8220;Error log : areyouhuman&#8221;. Bon je retente des codes bidon (genre &#8220;yes&#8221;, etc.). Je cherche sur le net &#8220;areyouhuman&#8221;, mais rien de concluant.</p>
<p>Au final rien de bien complexe, mais y’a moyen de tourner un peu en rond, il suffit «juste» d&#8217;allez sur l&#8217;URL <a href="http://game.sametmax.com/areyouhuman">http://game.sametmax.com/areyouhuman</a></p>
<h2 id="areyouhuman">areyouhuman</h2>
<p>À partir de là des connaissances en Python (basiques) vont être nécessaires. (j&#8217;utilise ici Python 2.7)</p>
<p>La page nous renvoie ce qui ressemble à une définition de classe <em>NextUrlContainer</em> avec un attribut <em>next</em> suivi d&#8217;une bouillie de caractères en commentaire.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">NextUrlContainer = <span style="color: #008000;">type</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;NextUrlContainer&quot;</span>, <span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#123;</span><span style="color: #483d8b;">'__init__'</span>: <span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> s, n: <span style="color: #008000;">setattr</span><span style="color: black;">&#40;</span>s, <span style="color: #483d8b;">'next'</span>, n<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># Y2NvcHlfcmVnCl9yZWNvbnN0cnVjdG9yCnAwCihjX19tYWluX18KTmV4dFVybENvbnRhaW5lcgpw MQpjX19idWlsdGluX18Kb2JqZWN0CnAyCk50cDMKUnA0CihkcDUKUyduZXh0JwpwNgpJMjA5NzM1 MQpzYi4=</span></pre></div></div>

<p>Avec un peu de recherche on découvre que la soi-disant bouillie n&#8217;est autre que du texte encodé en <a href="https://fr.wikipedia.org/wiki/Base64">base64</a>. Une fois décodé (il y a des utilitaires en ligne qui font ça très bien), on obtient quelque chose qui nous parle un peu plus (quoique).</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">ccopy_reg
_reconstructor
p0
<span style="color: black;">&#40;</span>c__main__
NextUrlContainer
p1
c__builtin__
<span style="color: #008000;">object</span>
p2
Ntp3
Rp4
<span style="color: black;">&#40;</span>dp5
S<span style="color: #483d8b;">'next'</span>
p6
I2097351
sb.</pre></div></div>

<p>Encore un peu de recherche et je découvre que c&#8217;est un fameux <a href="http://sametmax.com/plist-pickle-hdf5-protocol-buffer-les-formats-binaires/">pickle</a>, on sort notre Python préféré.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># -*-coding:Utf-8 -*</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">base64</span>, <span style="color: #dc143c;">pickle</span>
&nbsp;
NextUrlContainer = <span style="color: #008000;">type</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;NextUrlContainer&quot;</span>, <span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#123;</span><span style="color: #483d8b;">'__init__'</span>: <span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> s, n: <span style="color: #008000;">setattr</span><span style="color: black;">&#40;</span>s, <span style="color: #483d8b;">'next'</span>, n<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
&nbsp;
b64 = <span style="color: #483d8b;">&quot;Y2NvcHlfcmVnCl9yZWNvbnN0cnVjdG9yCnAwCihjX19tYWluX18KTmV4dFVybENvbnRhaW5lcgpw MQpjX19idWlsdGluX18Kb2JqZWN0CnAyCk50cDMKUnA0CihkcDUKUyduZXh0JwpwNgpJMjA5NzM1 MQpzYi4=&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># on décode et on dépickle-ise</span>
obj = <span style="color: #dc143c;">pickle</span>.<span style="color: black;">loads</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">base64</span>.<span style="color: black;">urlsafe_b64decode</span><span style="color: black;">&#40;</span>b64<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> obj.<span style="color: black;">next</span></pre></div></div>

<p>Et on obtient un objet de type <em>NextUrlContainer</em> contenant l&#8217;id de la prochaine URL : <strong>2097351</strong>.<br />
En ce rendant sur <a href="http://game.sametmax.com/areyouhuman/2097351">http://game.sametmax.com/areyouhuman/2097351</a> on se retrouve avec de nouveau un pickle encodé en base64. Après en avoir fait deux URL à la main, on ressort Python pour automatiser tout ça.<br />
<br/></p>
<p>Notre script doit :</p>
<ul>
<li>
<p>Récupérer le contenu de la page http://game.sametmax.com/areyouhuman/:id. (j&#8217;utilise ici la librairie httplib)</p>
</li>
<li>
<p>Décoder le contenu. (base64)</p>
</li>
<li>
<p>Dépickle-iser (je ne connais pas le terme &#8220;officiel&#8221;). (pickle)</p>
</li>
<li>
<p>Récupérer le prochain id.</p>
</li>
<li>
<p>Recommencer à la première étape jusqu&#8217;à… la fin.</p>
</li>
</ul>
<p>Voilà le script utilisé. Il affiche chaque nouvel id et plante quand on arrive au bout.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># -*-coding:Utf-8 -*</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">httplib</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">base64</span>, <span style="color: #dc143c;">pickle</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># la classe donnée sur la page http://game.sametmax.com/areyouhuman</span>
NextUrlContainer = <span style="color: #008000;">type</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;NextUrlContainer&quot;</span>, <span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#123;</span><span style="color: #483d8b;">'__init__'</span>: <span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> s, n: <span style="color: #008000;">setattr</span><span style="color: black;">&#40;</span>s, <span style="color: #483d8b;">'next'</span>, n<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># initialisation de la connection</span>
connection = <span style="color: #dc143c;">httplib</span>.<span style="color: black;">HTTPConnection</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;game.sametmax.com:80&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Fait une requête sur l'URL http://game.sametmax.com/areyouhuman/:id</span>
<span style="color: #808080; font-style: italic;"># Et retourne le contenu de la page</span>
<span style="color: #ff7700;font-weight:bold;">def</span> make_request<span style="color: black;">&#40;</span><span style="color: #008000;">id</span><span style="color: black;">&#41;</span>:
    url = <span style="color: #483d8b;">&quot;/areyouhuman/%i&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">id</span>
    connection.<span style="color: black;">request</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;GET&quot;</span>, url<span style="color: black;">&#41;</span>
    response = connection.<span style="color: black;">getresponse</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> response.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;"># id de départ</span>
<span style="color: #008000;">id</span> = <span style="color: #ff4500;">2097351</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># tant que ça plante pas ça suit les liens</span>
<span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff4500;">1</span>:
    <span style="color: #808080; font-style: italic;"># récupération du pickle en base64 contenant l'id de la prochain URL</span>
    response_crypt = make_request<span style="color: black;">&#40;</span><span style="color: #008000;">id</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># on décode et on dépickle-ise</span>
    obj = <span style="color: #dc143c;">pickle</span>.<span style="color: black;">loads</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">base64</span>.<span style="color: black;">urlsafe_b64decode</span><span style="color: black;">&#40;</span>response_crypt<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># on remplace l'id courant par le prochain afin de pouvoir recommencer</span>
    <span style="color: #008000;">id</span> = obj.<span style="color: black;">next</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #008000;">id</span></pre></div></div>

<p>On le lance et ça tourne un petit bout de temps avant d&#8217;en arriver au bout. (le serveur doit adorer)</p>
<pre>
    3245669
    2993679
    1050294
    .......
    9683898
    8147905
    9664723
    wololo.zip
    Traceback (most recent call last):
      File "1_requests.py", line 27, in <module>
        response_crypt = make_request(id)
      File "1_requests.py", line 14, in make_request
        URL = "/areyouhuman/%i" % id
    TypeError: %d format: a number is required, not str
</pre>
<p>On a donc notre prochaine destination : <a href="http://game.sametmax.com/wololo.zip">http://game.sametmax.com/wololo.zip</a></p>
<h2 id="wololo">Wololo</h2>
<p><a href="http://sametmax.com/ouverture-du-coffre-la-methode-simple-bourine-mais-efficace/wololo/" rel="attachment wp-att-6797"><img src="media/0a13e849.wololo.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/wololo.jpg" alt="Petit strip humoristique en réference à AOE et ses prètres wololoteur" title="Wololo" width="600" height="405" class="size-full wp-image-6797" /></a></p>
<p>Pour pas me prendre la tête j&#8217;ai télécharger le .zip dans le même répertoire que mes scripts.</p>
<p>On commence par dézipper <em>wololo.zip</em>, on obtient <em>one_more_time_1.zip</em> que l&#8217;on dézippe, on obtient <em>one_more_time_2.zip</em> que l&#8217;on dézippe, on obtient <em>one_more_time_3.zip</em> que l&#8217;on dézippe, etc.</p>
<p>Bon par besoin de chercher très loin pour savoir quoi faire, l&#8217;algo est simple :</p>
<ul>
<li>
<p>On dézippe <em>wololo.zip</em> (zipfile)</p>
</li>
<li>
<p>Tant que ça marche</p>
</li>
<li>
<p>On dézippe le fichier venant d&#8217;être extrait</p>
</li>
</ul>
<p>Ce qui se traduit en python par :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># -*-coding:Utf-8 -*</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">zipfile</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># archive de départ</span>
archive_name = <span style="color: #483d8b;">&quot;wololo.zip&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># tant qu’il y a quelque chose à dézipper, ça tourne</span>
<span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff4500;">1</span>:
    <span style="color: #808080; font-style: italic;"># ouverture de l'archive</span>
    archive = <span style="color: #dc143c;">zipfile</span>.<span style="color: black;">ZipFile</span><span style="color: black;">&#40;</span>archive_name, <span style="color: #483d8b;">'r'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># récupération du nom du fichier contenu dans l'archive</span>
    file_to_extract = archive.<span style="color: black;">namelist</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># extraction</span>
    archive.<span style="color: black;">extract</span><span style="color: black;">&#40;</span>file_to_extract<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span> file_to_extract
&nbsp;
    <span style="color: #808080; font-style: italic;"># le fichier tout fraichement extrait sera le prochain à être dézippé</span>
    <span style="color: #808080; font-style: italic;"># (ça plantera quand y'aura plus de .zip)</span>
    archive_name = file_to_extract</pre></div></div>

<p>On exécute</p>
<pre>
one_more_time_1.zip
one_more_time_2.zip
one_more_time_3.zip
...................
one_more_time_998.zip
one_more_time_999.zip
one_more_time_1000.zip
youdiditjonhy.txt
Traceback (most recent call last):
  File "2_zips.py", line 10, in <module>
    archive = zipfile.ZipFile(archive_name, 'r')
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/zipfile.py", line 712, in __init__
    self._GetContents()
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/zipfile.py", line 746, in _GetContents
    self._RealGetContents()
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/zipfile.py", line 761, in _RealGetContents
    raise BadZipfile, "File is not a zip file"
zipfile.BadZipfile: File is not a zip file
</pre>
<p>On se retrouve donc avec un nouveau petit fichier <strong>youdiditjonhy.txt</strong> contenant le texte</p>
<pre>api.json</pre>
<p>ainsi que 1000 fichiers zip … un petit <em>rm one_more_time</em>* dans son terminal (sur Windows débrouillez-vous) pour cleaner tout ça et on repart pour l&#8217;énigme suivante.</p>
<h2 id="api.json">api.json</h2>
<p>On se rend donc sur <a href="http://game.sametmax.com/api.json">http://game.sametmax.com/api.json</a>…</p>
<p>Et on se prend ça dans la tronche :</p>

<div class="wp_syntax"><div class="code"><pre class="json" style="font-family:monospace;">{&quot;\f&quot;: [&quot;.&quot;], &quot; &quot;: [&quot;.&quot;], &quot;$&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;(&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;,&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;0&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;4&quot;: [&quot;.&quot;], &quot;8&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;&lt;&quot;: [&quot;.&quot;], &quot;@&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;D&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;H&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;L&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;P&quot;: [&quot;.&quot;], &quot;T&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;X&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;\\&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;`&quot;: [&quot;.&quot;], &quot;d&quot;: [&quot;.&quot;], &quot;h&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;l&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;p&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;t&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;x&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;|&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;\u000b&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;#&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;'&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;+&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;/&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;3&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;7&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;;&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;?&quot;: [&quot;.&quot;], &quot;C&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;G&quot;: [&quot;.&quot;], &quot;K&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;O&quot;: [&quot;.&quot;], &quot;S&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;W&quot;: [&quot;.&quot;], &quot;[&quot;: [&quot;.&quot;], &quot;_&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;c&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;g&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;k&quot;: [&quot;.&quot;], &quot;o&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;s&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;w&quot;: [&quot;.&quot;], &quot;{&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;\n&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;\&quot;&quot;: [&quot;.&quot;], &quot;&amp;&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;*&quot;: [&quot;.&quot;], &quot;.&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;2&quot;: [&quot;.&quot;], &quot;6&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;:&quot;: [&quot;.&quot;], &quot;&gt;&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;B&quot;: [&quot;.&quot;], &quot;F&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;J&quot;: [&quot;.&quot;], &quot;N&quot;: [&quot;.&quot;], &quot;R&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;V&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;Z&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;^&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;b&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;f&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;j&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;n&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;r&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;v&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;z&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;~&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;\t&quot;: [&quot;.&quot;], &quot;\r&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;!&quot;: [&quot;.&quot;], &quot;%&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;)&quot;: [&quot;.&quot;], &quot;-&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;1&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;5&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;9&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;=&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;A&quot;: [&quot;.&quot;], &quot;E&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;I&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;M&quot;: [&quot;.&quot;], &quot;Q&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;U&quot;: [&quot;.&quot;], &quot;Y&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;]&quot;: [&quot;.&quot;], &quot;a&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;e&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;i&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;m&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;q&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;u&quot;: [&quot;.&quot;, &quot;.&quot;], &quot;y&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;], &quot;}&quot;: [&quot;.&quot;, &quot;.&quot;, &quot;.&quot;]}</pre></div></div>

<div id="attachment_6798" class="wp-caption aligncenter" style="width: 410px"><a href="http://sametmax.com/ouverture-du-coffre-la-methode-simple-bourine-mais-efficace/wtf/" rel="attachment wp-att-6798"><img src="media/8f808ad6.wtf.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/wtf.jpg" alt="Sir Patrick Stewart jurant à la vu de ce fichier json" title="Wtf" width="400" height="297" class="size-full wp-image-6798" /></a><p class="wp-caption-text">Même Sir Patrick Stewart semble contrarié par ce fichier !</p></div>
<p>Bon déjà on sait que c&#8217;est du <a href="http://sametmax.com/yaml-xml-json-csv-ini-quest-ce-que-cest-et-a-quoi-ca-sert/">JSON</a>, on se fait un nouveau script pour voir ce que donne ce json en Python :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># -*-coding:Utf-8 -*</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">httplib</span>
<span style="color: #ff7700;font-weight:bold;">import</span> json
&nbsp;
<span style="color: #808080; font-style: italic;"># on récupère le json</span>
connection = <span style="color: #dc143c;">httplib</span>.<span style="color: black;">HTTPConnection</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;game.sametmax.com:80&quot;</span><span style="color: black;">&#41;</span>
url = <span style="color: #483d8b;">&quot;/api.json&quot;</span>
connection.<span style="color: black;">request</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;GET&quot;</span>, url<span style="color: black;">&#41;</span>
response = connection.<span style="color: black;">getresponse</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># on transorme en python</span>
decoded = json.<span style="color: black;">loads</span><span style="color: black;">&#40;</span>response.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> decode</pre></div></div>

<p>Bon c&#8217;est pas beaucoup mieux, on à affaire à un dictionnaire avec pour clé un caractère Unicode avec une liste de &#8216;.&#8217; plus où moins longue associé. En mettant un peu en forme ça donne un truc du genre :</p>
<pre>
Y :  . . .
Z :  . . .
[ :  .
\ :  . .
] :  .
^ :  . .
_ :  . .
` :  .
a :  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
b :  . . .
</pre>
<p>Soit pas grand-chose d&#8217;exploitable, je modifie le script pour obtenir le nombre de points associé à chaque caractère :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># -*-coding:Utf-8 -*</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">httplib</span>
<span style="color: #ff7700;font-weight:bold;">import</span> json
&nbsp;
<span style="color: #808080; font-style: italic;"># on récupère le json</span>
connection = <span style="color: #dc143c;">httplib</span>.<span style="color: black;">HTTPConnection</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;game.sametmax.com:80&quot;</span><span style="color: black;">&#41;</span>
url = <span style="color: #483d8b;">&quot;/api.json&quot;</span>
connection.<span style="color: black;">request</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;GET&quot;</span>, url<span style="color: black;">&#41;</span>
response = connection.<span style="color: black;">getresponse</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># on met ça en python</span>
decoded = json.<span style="color: black;">loads</span><span style="color: black;">&#40;</span>response.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># on passe le dico en liste pour pouvoir le trier</span>
items = decoded.<span style="color: black;">items</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
items.<span style="color: black;">sort</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> items:
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;%s : %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>i<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>, <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></div></div>

<pre>
Z : 3
[ : 1
\ : 2
] : 1
^ : 2
_ : 2
` : 1
a : 50
b : 3
</pre>
<p>À partir de là je tente de convertir des mots en remplaçant les lettres par le nombre de &#8216;.&#8217; associé, par exemple &#8220;Max&#8221; =&gt; 1503. J&#8217;arrête vite mes conneries et me rend compte qu&#8217;une grosse partie des caractères n&#8217;est associé qu&#8217;a 1,2 ou 3 points et quelques autres sont à 50, 30, 60, étrange…</p>
<p>Je garde juste les plus grosses valeurs, les tris dans l&#8217;ordre croissant, soit : 10 20 &#8230; 80. En reprenant chaque clé associée, on obtient le mot <strong>gnitaehc</strong>, soit <strong>cheating</strong> à l&#8217;envers. Peu de chance que ce soit là par hasard. </p>
<p>On se rend sur <a href="http://game.sametmax.com/cheating">http://game.sametmax.com/cheating</a>, on arrive à la fin.</p>
<h2 id="ba">↑↑↓↓←→←→BA</h2>
<p>Retour sur la page d&#8217;accueil avec cette fois-ci le Konami code en message (↑↑↓↓←→←→BA). Pas de temps à perdre, on va sur <a href="http://game.sametmax.com/konami">http://game.sametmax.com/konami</a>.</p>
<h2 id="achievementunlocked">Achievement unlocked</h2>
<p>Et c&#8217;est là que ce termine la série d&#8217;énigmes ! Au final la difficulté était plutôt bien dosée, pas trop hard pour un débutant tout en offrant du challenge et du cassage de tête.</p>
<p>J’espère avoir été clair dans mes explications, si y’a des questions sur certains point allez-y, même si ce n&#8217;est pas moi je pense qu’il y’aura toujours quelqu’un pour vous éclairer.</p>
<p>Si vous avez utilisé d&#8217;autres techniques ou s’il y a des remarques sur mon code, allez-y. Dans les commentaires de l&#8217;article original, il y&#8217;a une solution &#8220;collaborative&#8221; similaire à la mienne (bon leurs codes est quand même un peu plus propre), y&#8217;a également Recher qui nous propose d&#8217;utiliser un éditeur hexadécimal pour l&#8217;énigme du zip.</p>
<p>Je suis assez amateur de ce genre de puzzle/challenge, si ça interesse des gens il y a quelques sites bien sympa pour se prendre la tête :</p>
<ul>
<li>
<p><a href="http://www.pythonchallenge.com/">http://www.pythonchallenge.com/</a> : qui est un grand classique, très orienté python, niveau énigme c&#8217;est vraiment dans la même veine que cette ouverture de coffre, pour ma part j&#8217;avais testé il y&#8217;a quelque temps et je m&#8217;étais assez vite retrouvé coincé… (par contre il ne faut pas s&#8217;arrêter à l&#8217;aspect graphique qui fait un peu saigner les yeux…)</p>
</li>
<li>
<p><a href="http://www.newbiecontest.org/">http://www.newbiecontest.org/</a> : ce site est beaucoup plus général en proposant des épreuves de crypto, hacking, prog, logique, crackme, etc. Et y&#8217;a largement de quoi péter des plombs. La partie programation est assez interessante pour se faire un peu de python. (par contre il est necessaire de s&#8217;inscrire)</p>
</li>
<li>
<p>Y&#8217;en a plein d&#8217;autre je suppose, mais je n&#8217;ai testé que ces deux là, si vous avez quelques bonnes adresses n’hésitez pas à partager.</p>
</li>
</ul>
<p>Sur ce, bravo à ceux qui ont tenté le jeu, bon voyage à Max et encore merci à nos deux taulier !</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6789&amp;md5=da5cd4ed670922f6296380bd6ec49e67" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6880
title: Files de tâches et tâches récurrentes avec Celery
uri: Files-de-tâches-et-tâches-récurrentes-avec-Celery
url: http://sametmax.com/files-de-taches-et-taches-recurrentes-avec-celery/
content:
<p>Quand on a à traiter des choses bloquantes, avec des dépendances, des flux complexes ou des actions répétitives, créer des files d&#8217;attente peut se révéler très judicieux.</p>
<p>Par exemple lancer la génération d&#8217;un gros zip sur le clic d&#8217;un utilisateur, télécharger plein fichiers en parallèle pour son site de cul, lancer des calculs sur plusieurs machines et récupérer le résultat, encoder des videos en arrière plan, etc.</p>
<p>Le problème, c&#8217;est que fabriquer des files d&#8217;attente à la main, ça mène généralement à une grosse galère. La première boîte dans laquelle j&#8217;ai travaillé avait tout un système de queues à base de PHP + SQL fait à la main qui tapait dans du MySQL, c&#8217;était pas marrant du tout</p>
<p>Je fais une pause, et je note que le potentiel de jeux de mots sur cet article est fortement élevé. Mais je resterai fort.</p>
<p>Locking, priorité, dépendance, asynchronicité, concurrence, sérialisation, encoding, stockage, accessibilité, load balancing&#8230; Toutes ces problématiques sont bien vicieuses et chronophages. Il vaut mieux utiliser une lib solide et éprouvée.</p>
<p>Je resterai fort.</p>
<p><a href="https://pypi.python.org/pypi/kombu/2.2.0">Kombu</a> est une telle lib, mais elle est lourde et complexe à utiliser. J&#8217;avais fais le choix de la prendre pour un gros projet avec Max, je le regrette sur le long terme : c&#8217;est dur à maintenir et à faire évoluer. Le code est vraiment pas sympa.</p>
<p>Heureusement il existe une bibliothèque qui se met au dessus de Kombu pour et nous expose juste les fonctionnalités que l&#8217;on souhaite : <a href="http://www.celeryproject.org/">celery</a>.</p>
<p>Fort.</p>
<p>Celery est simple pour démarrer, mais très puissant si on rentre dans le détail, et croyez moi, le détail, on peut y rentrer très très profondément.</p>
<p>F&#8230;</p>
<h2>Installation</h2>
<p>Qui dit file d&#8217;attente, dit stockage. Il faut bien mettre les tâches quelque part et communiquer avec ce quelque part. En base de données ? Dans un gestionnaire de messages ? En mémoire ? Dans un cache ?</p>
<p>Celery résout le problème en proposant la même interface, quelque soit le support. Actuellement, on peut utiliser :</p>
<ul>
<li>RabbitMQ</li>
<li>Redis</li>
<li>MongoDB</li>
<li>Beanstalk CouchDB</li>
<li>SQLAlchemy ou l&#8217;ORM Django (et donc toutes les bases de données supportées comme Sqlite, MySQL, PostGres&#8230;)</li>
<li>Amazon SQS</li>
</ul>
<p>Dans notre exemple, nous allons le faire avec Redis car :</p>
<ul>
<li>Redis est très simple à installer et à configurer.</li>
<li>Nous on utilise déjà du Redis partout.</li>
<li>Aucun risque de locking.</li>
</ul>
<p>Pour ceux qui ont pas redis, c&#8217;est généralement dans les dépôts. Par exemple sur Ubuntu :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> <span style="color: #c20cb9; font-weight: bold;">install</span> redis-server</pre></div></div>

<p>Il n&#8217;y a rien à faire de plus, ça tourne, c&#8217;est configuré avec des valeurs par défaut qui sont saines. Je vous l&#8217;ai dis, redis, c&#8217;est fantastiquement bien foutu.</p>
<p>Ensuite on install celery et la lib d&#8217;accès à redis en Python qui porte un nom très original :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">pip <span style="color: #c20cb9; font-weight: bold;">install</span> celery redis</pre></div></div>

<p>Ca devrait compiler un peu, et comme hab avec les extensions en C, assurez vous d&#8217;avoir un compilateur et les headers en place comme indiqué dans l&#8217;article sur <a href="http://sametmax.com/votre-python-aime-les-pip/">pip</a>.</p>
<p>Ensuite on peut créer ses tâches. Créez un module, par exemple <em>tasks.py</em> :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">urllib2</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">collections</span> <span style="color: #ff7700;font-weight:bold;">import</span> Counter
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> celery <span style="color: #ff7700;font-weight:bold;">import</span> Celery
&nbsp;
<span style="color: #808080; font-style: italic;"># Configuration de celery. Ceci peut aussi se faire dans un fichier de config.</span>
<span style="color: #808080; font-style: italic;"># Ici on dit à celery que pour le module 'tasks', on va utiliser redis</span>
<span style="color: #808080; font-style: italic;"># comme broker (passeur de massage) et comme result backend (stockage du</span>
<span style="color: #808080; font-style: italic;"># resultat des tâches).</span>
celery = Celery<span style="color: black;">&#40;</span><span style="color: #483d8b;">'tasks'</span>, broker=<span style="color: #483d8b;">'redis://localhost'</span>, backend=<span style="color: #483d8b;">'redis://localhost'</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;"># Et voici notre première tâche. C'est une fonction Python normale, décorée</span>
<span style="color: #808080; font-style: italic;"># avec un decorateur de celery. Elle prend une URL, et calcule le nombre</span>
<span style="color: #808080; font-style: italic;"># de lettre &quot;e&quot; qu'il y a dans la page.</span>
@celery.<span style="color: black;">task</span>
<span style="color: #ff7700;font-weight:bold;">def</span> ecount<span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> Counter<span style="color: black;">&#40;</span><span style="color: #dc143c;">urllib2</span>.<span style="color: black;">urlopen</span><span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'e'</span><span style="color: black;">&#93;</span></pre></div></div>

<p>On lance ensuite le processus celery dans un terminal (en production, mettez ça dans supervisord ou systemd pour que ça démarre automatiquement) :</p>
<pre>
[test] sam ~/Bureau/celery_test $ celery -A tasks worker -B --loglevel=info

 -------------- celery@sam v3.0.21 (Chiastic Slide)
---- **** -----
--- * ***  * -- Linux-3.2.0-48-generic-x86_64-with-Ubuntu-12.04-precise
-- * - **** ---
- ** ---------- [config]
- ** ---------- .> broker:      redis://localhost:6379//
- ** ---------- .> app:         tasks:0x2a2fa50
- ** ---------- .> concurrency: 4 (processes)
- *** --- * --- .> events:      OFF (enable -E to monitor this worker)
-- ******* ----
--- ***** ----- [queues]
 -------------- .> celery:      exchange:celery(direct) binding:celery

[Tasks]
  . tasks.ecount

[2013-07-26 13:22:21,631: INFO/Beat] Celerybeat: Starting..
[2013-07-26 13:04:51,274: WARNING/MainProcess] celery@sam ready.
[2013-07-26 13:04:51,280: INFO/MainProcess] consumer: Connected to redis://localhost:6379//.
</pre>
<p><code>-A</code> précise le module à importer, <code>-B</code> démarre le beat (on verra ça plus tard), <code>worker</code> dit à celery que démarrer des processus de consommation de files d&#8217;attente (par défaut 4 qui travaillent en parallèle), et <code>--loglevel=info</code> va nous permettre d&#8217;avoir un affichage verbeux pour comprendre ce qui se passe.</p>
<p>Votre file d&#8217;attente est prête, et frétille d&#8217;impatience.</p>
<h2>Lancer une tâche</h2>
<p>A partir de là, vous pouvez envoyer des tâches dans la file d&#8217;attente, depuis n&#8217;importe où :</p>
<ul>
<li>Un script.</li>
<li>Un serveur Web (par exemple une vue Django).</li>
<li>Un programme sur un autre serveur (même si il faudrait alors configurer redis pour qu&#8217;il écoute sur les ports extérieurs, ce qui n&#8217;est pas le cas ici par simplicité).</li>
<li>etc</li>
</ul>
<p>Plusieurs programmes peuvent envoyer plein de tâches, en même temps, et elles vont se loger dans la file d&#8217;attente, sans bloquer le programme qui les a envoyé.</p>
<p>Par exemple, depuis le shell :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">from</span> tasks <span style="color: #ff7700;font-weight:bold;">import</span> ecount
<span style="color: #66cc66;">&gt;&gt;&gt;</span> res = ecount.<span style="color: black;">delay</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://danstonchat.com'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Ceci ne bloque pas mon shell, la ligne s&#8217;exécute immédiatement. La fonction <code>ecount</code> n&#8217;est pas appelée depuis le shell, elle est dans la file d&#8217;attente et sera appelée par un des processus (les fameux &#8216;worker&#8217;) qui consomment la queue. Du côté de la file, on peut voir dans le log :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">2013</span>-07-<span style="color: #000000;">26</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">18</span>:08,<span style="color: #000000;">609</span>: INFO<span style="color: #000000; font-weight: bold;">/</span>MainProcess<span style="color: #7a0874; font-weight: bold;">&#93;</span> Got task from broker: tasks.ecount<span style="color: #7a0874; font-weight: bold;">&#91;</span>599a52ea-ef6b-<span style="color: #000000;">4499</span>-981d-cd17fab592df<span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">2013</span>-07-<span style="color: #000000;">26</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">18</span>:09,070: INFO<span style="color: #000000; font-weight: bold;">/</span>MainProcess<span style="color: #7a0874; font-weight: bold;">&#93;</span> Task tasks.ecount<span style="color: #7a0874; font-weight: bold;">&#91;</span>599a52ea-ef6b-<span style="color: #000000;">4499</span>-981d-cd17fab592df<span style="color: #7a0874; font-weight: bold;">&#93;</span> succeeded <span style="color: #000000; font-weight: bold;">in</span> 0.446974039078s: <span style="color: #000000;">1242</span></pre></div></div>

<p>On a donc notre tâche qui a bien été traitée.</p>
<p>On peut récupérer le résultat dans le shell :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> res.<span style="color: black;">state</span>
<span style="color: #483d8b;">'PENDING'</span></pre></div></div>

<p>Ah&#8230; La tâche n&#8217;est pas encore terminée. Et un peu plus tard :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> res.<span style="color: black;">state</span>
<span style="color: #483d8b;">'SUCCESS'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> res.<span style="color: black;">result</span>
<span style="color: #ff4500;">1242</span></pre></div></div>

<p>Lancer une tâche est bien entendu peu intéressant, les listes d&#8217;attente sont vraiment sympa quand on a plein de tâches à lancer, par plein de processus différents :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">results = <span style="color: black;">&#91;</span>ecount.<span style="color: black;">delay</span><span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> url <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://google.com'</span>, <span style="color: #483d8b;">'http://sametmax.com'</span>, <span style="color: #483d8b;">'http://sebsauvage.com'</span>, <span style="color: #483d8b;">'http://multiboards.com'</span>, <span style="color: #483d8b;">'http://0bin.net'</span>, <span style="color: #483d8b;">'http://danstonchat.com'</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">2013</span>-07-<span style="color: #000000;">26</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">25</span>:<span style="color: #000000;">46</span>,<span style="color: #000000;">646</span>: INFO<span style="color: #000000; font-weight: bold;">/</span>MainProcess<span style="color: #7a0874; font-weight: bold;">&#93;</span> Got task from broker: tasks.ecount<span style="color: #7a0874; font-weight: bold;">&#91;</span>5d072a7b-29f8-4ea6-8d92-6a4c1740d724<span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">2013</span>-07-<span style="color: #000000;">26</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">25</span>:<span style="color: #000000;">46</span>,<span style="color: #000000;">649</span>: INFO<span style="color: #000000; font-weight: bold;">/</span>MainProcess<span style="color: #7a0874; font-weight: bold;">&#93;</span> Got task from broker: tasks.ecount<span style="color: #7a0874; font-weight: bold;">&#91;</span>402f6a4f-6b35-4f62-a786-9a5ba27707d2<span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">2013</span>-07-<span style="color: #000000;">26</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">25</span>:<span style="color: #000000;">46</span>,<span style="color: #000000;">650</span>: INFO<span style="color: #000000; font-weight: bold;">/</span>MainProcess<span style="color: #7a0874; font-weight: bold;">&#93;</span> Got task from broker: tasks.ecount<span style="color: #7a0874; font-weight: bold;">&#91;</span>bbe46b1b-<span style="color: #000000;">4719</span>-4c42-bd2f-21e4d72e613e<span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">2013</span>-07-<span style="color: #000000;">26</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">25</span>:<span style="color: #000000;">46</span>,<span style="color: #000000;">652</span>: INFO<span style="color: #000000; font-weight: bold;">/</span>MainProcess<span style="color: #7a0874; font-weight: bold;">&#93;</span> Got task from broker: tasks.ecount<span style="color: #7a0874; font-weight: bold;">&#91;</span>8fb35186-66e2-4eae-a40c-fc42e500ab9d<span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">2013</span>-07-<span style="color: #000000;">26</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">25</span>:<span style="color: #000000;">46</span>,<span style="color: #000000;">653</span>: INFO<span style="color: #000000; font-weight: bold;">/</span>MainProcess<span style="color: #7a0874; font-weight: bold;">&#93;</span> Got task from broker: tasks.ecount<span style="color: #7a0874; font-weight: bold;">&#91;</span>fc63f5db-8ade-<span style="color: #000000;">4383</span>-b719-c3d6390ca246<span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">2013</span>-07-<span style="color: #000000;">26</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">25</span>:<span style="color: #000000;">46</span>,<span style="color: #000000;">654</span>: INFO<span style="color: #000000; font-weight: bold;">/</span>MainProcess<span style="color: #7a0874; font-weight: bold;">&#93;</span> Got task from broker: tasks.ecount<span style="color: #7a0874; font-weight: bold;">&#91;</span>8434e21d-79ea-<span style="color: #000000;">4559</span>-a90e-92e2bc2b9dc7<span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">2013</span>-07-<span style="color: #000000;">26</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">25</span>:<span style="color: #000000;">47</span>,<span style="color: #000000;">144</span>: INFO<span style="color: #000000; font-weight: bold;">/</span>MainProcess<span style="color: #7a0874; font-weight: bold;">&#93;</span> Task tasks.ecount<span style="color: #7a0874; font-weight: bold;">&#91;</span>bbe46b1b-<span style="color: #000000;">4719</span>-4c42-bd2f-21e4d72e613e<span style="color: #7a0874; font-weight: bold;">&#93;</span> succeeded <span style="color: #000000; font-weight: bold;">in</span> 0.479865789413s: <span style="color: #000000;">27</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">2013</span>-07-<span style="color: #000000;">26</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">25</span>:<span style="color: #000000;">47</span>,<span style="color: #000000;">242</span>: INFO<span style="color: #000000; font-weight: bold;">/</span>MainProcess<span style="color: #7a0874; font-weight: bold;">&#93;</span> Task tasks.ecount<span style="color: #7a0874; font-weight: bold;">&#91;</span>5d072a7b-29f8-4ea6-8d92-6a4c1740d724<span style="color: #7a0874; font-weight: bold;">&#93;</span> succeeded <span style="color: #000000; font-weight: bold;">in</span> 0.578661203384s: <span style="color: #000000;">609</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">2013</span>-07-<span style="color: #000000;">26</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">25</span>:<span style="color: #000000;">47</span>,<span style="color: #000000;">501</span>: INFO<span style="color: #000000; font-weight: bold;">/</span>MainProcess<span style="color: #7a0874; font-weight: bold;">&#93;</span> Task tasks.ecount<span style="color: #7a0874; font-weight: bold;">&#91;</span>fc63f5db-8ade-<span style="color: #000000;">4383</span>-b719-c3d6390ca246<span style="color: #7a0874; font-weight: bold;">&#93;</span> succeeded <span style="color: #000000; font-weight: bold;">in</span> 0.35736989975s: <span style="color: #000000;">263</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">2013</span>-07-<span style="color: #000000;">26</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">25</span>:<span style="color: #000000;">47</span>,<span style="color: #000000;">645</span>: INFO<span style="color: #000000; font-weight: bold;">/</span>MainProcess<span style="color: #7a0874; font-weight: bold;">&#93;</span> Task tasks.ecount<span style="color: #7a0874; font-weight: bold;">&#91;</span>8434e21d-79ea-<span style="color: #000000;">4559</span>-a90e-92e2bc2b9dc7<span style="color: #7a0874; font-weight: bold;">&#93;</span> succeeded <span style="color: #000000; font-weight: bold;">in</span> 0.403187036514s: <span style="color: #000000;">1270</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">2013</span>-07-<span style="color: #000000;">26</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">25</span>:<span style="color: #000000;">47</span>,<span style="color: #000000;">815</span>: INFO<span style="color: #000000; font-weight: bold;">/</span>MainProcess<span style="color: #7a0874; font-weight: bold;">&#93;</span> Task tasks.ecount<span style="color: #7a0874; font-weight: bold;">&#91;</span>8fb35186-66e2-4eae-a40c-fc42e500ab9d<span style="color: #7a0874; font-weight: bold;">&#93;</span> succeeded <span style="color: #000000; font-weight: bold;">in</span> 1.14100408554s: <span style="color: #000000;">23</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">2013</span>-07-<span style="color: #000000;">26</span> <span style="color: #000000;">14</span>:<span style="color: #000000;">25</span>:<span style="color: #000000;">49</span>,010: INFO<span style="color: #000000; font-weight: bold;">/</span>MainProcess<span style="color: #7a0874; font-weight: bold;">&#93;</span> Task tasks.ecount<span style="color: #7a0874; font-weight: bold;">&#91;</span>402f6a4f-6b35-4f62-a786-9a5ba27707d2<span style="color: #7a0874; font-weight: bold;">&#93;</span> succeeded <span style="color: #000000; font-weight: bold;">in</span> 2.34633708s: <span style="color: #000000;">3158</span></pre></div></div>

<p>Car du coup on sait que ces multiples tâches ne vont pas bloquer le processus en cour, mais qu&#8217;en plus la charge sera répartie sur le nombre de workers qu&#8217;on a décidé au départ, ni plus (surcharge du serveur), ni moins (traitement trop lent).</p>
<h2>Comment je sais quand une tâche est terminée ?</h2>
<p>On peut attendre que la tâche soit terminée :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span> res.<span style="color: black;">wait</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">9999</span></pre></div></div>

<p>Mais ce n&#8217;est pas vraiment le but. On cherche avant tout à ce que les tâches soient non bloquantes, et exécutées dans un processus à part voir potentiellement distribuées sur plusieurs serveurs. </p>
<p>Par ailleurs, Celery n&#8217;est pas un remplacement d&#8217;un système de traitement asynchrone comme Tornado ou NodeJS, il n&#8217;est pas fait pour envoyer des réponses asynchrones à l&#8217;utilisateur. Il est fait pour faire des tâches en background, répartir la charge et ordonner le traitement. Bien entendu, on peut faire communiquer un système asynchrone avec celery comme <a href="https://github.com/mher/tornado-celery">ici</a> ou <a href="http://cyberfart.blogspot.fr/2012/11/tornado-celery-integration.html">ici</a>, mais c&#8217;est une autre histoire.</p>
<p>Concentrons nous sur les tâches.</p>
<p>La question de &#8220;Comment je sais quand une tâche est terminée ?&#8221; est souvent traduisible par &#8220;comment je réagis à une tâche pour lancer du code quand elle s&#8217;est terminée sans erreur ?&#8221;.</p>
<p>Et là, il y une solution toute simple :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">res = tache1.<span style="color: black;">s</span><span style="color: black;">&#40;</span>arg1, arg2<span style="color: black;">&#41;</span> | tache2.<span style="color: black;">s</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> | tache3.<span style="color: black;">s</span><span style="color: black;">&#40;</span>arg1<span style="color: black;">&#41;</span></pre></div></div>

<p>Ceci va créer une chaîne de tâches. Quand la première se termine, la deuxième se lance en recevant le résultat de la première en argument.</p>
<p><code>s()</code> fabrique une sous-tâche, c&#8217;est à dire une tâche à envoyer dans la file plus tard avec des arguments pré-enregistrés. Dans notre exemple, celery va lancer <code>tache1</code> avec deux arguments, puis si ça marche, va appeler <code>tache2</code> en lui passant le résultat de <code>tache1</code> comme argument, puis si ça marche, va appeler <code>tache3</code> avec le résultat de <code>tache2</code> en premier argument et <code>arg1</code> en second argument.</p>
<p>En fait, celery vient avec tout <a href="http://docs.celeryproject.org/en/latest/userguide/canvas.html?highlight=group">un tas d&#8217;outils</a> pour exécuter des tâches dépendantes les unes des autres : par groupes, par chaînes, par morceaux, etc. Mais de toute façon, vous pouvez appeler une tâche&#8230; à l&#8217;intérieur d&#8217;une autre tâche. Donc parti de là vous pouvez faire pas mal de choses.</p>
<h2>Comment je fais pour faire une tâche récurrente ?</h2>
<p>C&#8217;est là qu&#8217;intervient le &#8220;beat&#8221; dont j&#8217;ai parlé tout à l&#8217;heure. Avec cette option, celery va vérifier toutes les secondes si il n&#8217;y a pas une tâche répétitive à lancer, et la mettre dans une file d&#8217;attente, à la manière d&#8217;un cron.</p>
<p>Il suffit de définir une tâche comme <code>periodic_task</code> pour qu&#8217;elle soit lancée régulièrement.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">smtplib</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> celery.<span style="color: black;">schedules</span> <span style="color: #ff7700;font-weight:bold;">import</span> crontab
<span style="color: #ff7700;font-weight:bold;">from</span> celery.<span style="color: black;">decorators</span> <span style="color: #ff7700;font-weight:bold;">import</span> periodic_task
&nbsp;
<span style="color: #808080; font-style: italic;"># va executer la tâche à 5h30, 13h30 et 23h30 tous les lundi</span>
<span style="color: #808080; font-style: italic;"># run_every accepte aussi un timedelta, pour par exemple dire &quot;toutes les 10m&quot;</span>
@periodic_task<span style="color: black;">&#40;</span>run_every=crontab<span style="color: black;">&#40;</span>hour=<span style="color: #483d8b;">'5,13,23'</span>, minute=<span style="color: #ff4500;">30</span>, day_of_week=<span style="color: #483d8b;">'monday'</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> is_alive<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
        Vérifie que le blog est toujours en ligne, et si ce n'est pas le cas,
        envoie un mail en panique.
    &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">urllib2</span>.<span style="color: black;">urlopen</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://sametmax.com'</span><span style="color: black;">&#41;</span>.<span style="color: #dc143c;">code</span> <span style="color: #66cc66;">!</span>= <span style="color: #ff4500;">200</span>:
        mail = <span style="color: #483d8b;">'lesametlemax__AT__gmail.com'</span>.<span style="color: black;">replace</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'__AT__'</span>, <span style="color: #483d8b;">'@'</span><span style="color: black;">&#41;</span>
        server = <span style="color: #dc143c;">smtplib</span>.<span style="color: black;">SMTP</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'smtp.gmail.com:587'</span><span style="color: black;">&#41;</span>
        server.<span style="color: black;">starttls</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        server.<span style="color: black;">login</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'root'</span>, <span style="color: #483d8b;">'admin123'</span><span style="color: black;">&#41;</span>
        server.<span style="color: black;">sendmail</span><span style="color: black;">&#40;</span>mail, mail, msg<span style="color: black;">&#41;</span>
        server.<span style="color: black;">quit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Il y a de <a href="http://docs.celeryproject.org/en/latest/userguide/periodic-tasks.html?highlight=cron">bons exemples</a> sur la syntaxe sur <code>crontab()</code> dans la doc.</p>
<p>D&#8217;une manière générale, <a href="http://docs.celeryproject.org/en/latest/getting-started/introduction.html">la doc de Celery est très très riche</a>, donc plongez vous dedans si cet article ne répond pas à vos besoins, car si ça peut être mis dans une file, ça peut être fait par Celery.</p>
<h2>Note de fin</h2>
<p>Celery n&#8217;autoreload pas le code, donc redémarrez les workers à chaque fois que vous modifiez vos tasks.</p>
<p>Attention aussi aux tâches récurrentes, la suivante peut se lancer avant que la précédente soit terminée. C&#8217;est à vous de faire des tâches <a href="https://fr.wikipedia.org/wiki/Idempotent">idempotentes</a>, ou alors de mettre en place <a href="http://docs.celeryproject.org/en/latest/tutorials/task-cookbook.html#cookbook-task-serial">un système de locking</a>.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6880&amp;md5=b63d1026ee7b0d5a9e8f73bf0347b702" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6897
title: E-ink et confiseries
uri: E-ink-et-confiseries
url: http://sametmax.com/e-ink-et-confiseries/
content:
<p style="text-align: center;"><em><small>Ceci est un post invité de <a href="http://sametmax.com/author/MrAaaah/">MrAaaah</a> posté sous licence <a href="http://creativecommons.org/licenses/by/3.0/">creative common 3.0 unported</a>.</small></em></p>
<p>Pour conclure ma série d&#8217;articles autour du coffre secret de Sam et Max, je vais finir avec une présentation du cadeau qui était à décrocher.</p>
<p>C&#8217;est vendredi matin à l&#8217;aurore qu&#8217;une hirondelle d&#8217;Afrique m&#8217;a livré le paquet tant attendu ! </p>
<div id="attachment_6898" class="wp-caption aligncenter" style="width: 607px"><a href="http://sametmax.com/e-ink-et-confiseries/2013-07-26-10-36-32/" rel="attachment wp-att-6898"><img src="media/8aa169de.2013-07-26-10.36.32.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/2013-07-26-10.36.32.jpg" alt="Le fameux colis" title="Le fameux colis" width="597" height="800" class="size-full wp-image-6898" /></a><p class="wp-caption-text">Peu de chance que cela soit une Thaïlandaise ou un kilo de boudin</p></div>
<div id="attachment_6908" class="wp-caption aligncenter" style="width: 610px"><a href="http://sametmax.com/e-ink-et-confiseries/2013-07-26-10-38-05/" rel="attachment wp-att-6908"><img src="media/ad6647b2.2013-07-26-10.38.05.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/2013-07-26-10.38.05.jpg" alt="La Kobo et des bonbecs" title="La Kobo et des bonbecs" width="600" height="448" class="size-full wp-image-6908" /></a><p class="wp-caption-text">À l’intérieur, un (une?) Kobo mini, qui est une liseuse numérique de 5&quot; vendue par la Fnac, accompagnée de 4 petits sachets de Dragibus pour que rien ne bouge dans le colis.</p></div>
<p>N&#8217;ayant l&#8217;appareil que depuis hier et n&#8217;ayant jamais utilisé d&#8217;eReader auparavant, je n’ai pas eu le temps de tester la bête en profondeur, mais je vais tout de même essayer de vous faire un petit compte-rendu.</p>
<p>Ce qui frappe tout de suite, c&#8217;est que c&#8217;est la taille (l&#8217;écran est 4 fois plus petit qu&#8217;un iPad), on peut ainsi se demander s&#8217;il est confortable de lire sur un écran de cette taille.<br />
En fait, cela dépend du format et du type de l’ouvrage que l&#8217;on souhaite lire. Le Kobo supporte les fichiers <em>PDF</em> et les <em>epub</em> (le JPG, le PNG et le GIF aussi, mais bon …). </p>
<h2 id="lesformats">Les formats</h2>
<p>Le point fort dû <a href="https://en.wikipedia.org/wiki/Portable_Document_Format">format PDF</a> qui est de garantir une mise en page identique sur tous les OS et dans tous les logiciels est ici un gros défaut. Sachant que sur le Kobo cette mise en page est gardée et que l&#8217;on est sur un écran beaucoup plus petit qu&#8217;une page de livre, on passe son temps à zoomer et se déplacer sur le contenu ; si cette contrainte ne gêne pas trop sur smartphone ou tablette, car ces actions sont immédiates et naturelles à réaliser (où presque, selon les modèles). Dans le cas d&#8217;une liseuse, nous sommes en présence d&#8217;encre électronique avec un temps d&#8217;affichage très lent (par rapport à un écran &#8220;classique&#8221;), il faut pas loin d&#8217;une seconde pour chaque action (déplacement ou zoom) ce qui rend la navigation insupportable et pas pratique du tout.<br />
En gros c&#8217;est vraiment un format à oublier pour un appareil de cette taille. Il existe bien des convertisseurs PDF -&gt; ePub, mais ça ne ma pas donné quelque chose de concluant. Pour le PDF, un eReader de taille supérieure serait peut-être plus adapté (à tester), même si je pense qu&#8217;une tablette (type iPad) est le top (réactivité, taille, etc.)(sauf pour les yeux).</p>
<div id="attachment_6900" class="wp-caption aligncenter" style="width: 610px"><a href="http://sametmax.com/e-ink-et-confiseries/p1020645/" rel="attachment wp-att-6900"><img src="media/c9c4ec28.P1020645.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/P1020645.jpg" alt="Pdf on Kobo" title="Pdf on Kobo" width="600" height="800" class="size-full wp-image-6900" /></a><p class="wp-caption-text">Lire un pdf sur la Kobo, c&#039;est chiant …</p></div>
<p>Le <a href="https://en.wikipedia.org/wiki/EPUB">format epub</a>, lui est tout récent, car il est apparu avec ces eReader. Je n’avais jamais eu l&#8217;occasion de tester ce format et c&#8217;est tip-top pour ce genre d&#8217;appareil. L&#8217;ePUB c’est tout le contraire du format PDF, c’est libre, ouvert et surtout il laisse le soin de gérer la mise en page du contenu au logiciel, ce qui permet d&#8217;avoir accès à une table des matières, de modifier sa police, l&#8217;interlignage et tout un tas d&#8217;options relatives à la mise en page. Là où ça peu coincer, c&#8217;est pour les BD ou les livres où la mise en page n&#8217;est plus &#8220;traditionnelle&#8221;, <a href="https://fr.wikipedia.org/wiki/EPUB_%28format%29#Critiques">wiki</a> me souffle à l&#8217;oreille que le format &#8220;<em>Fixed Layout</em>&#8221; a été développé pour contrer ça, je n’ai pas testé donc je ne me prononcerais pas dessus.</p>
<div id="attachment_6901" class="wp-caption aligncenter" style="width: 610px"><a href="http://sametmax.com/e-ink-et-confiseries/p1020646/" rel="attachment wp-att-6901"><img src="media/c26404a5.P1020646.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/P1020646.jpg" alt="Les options d&#039;un epub sur la Kobo" title="Les options d&#039;un epub sur la Kobo" width="600" height="800" class="size-full wp-image-6901" /></a><p class="wp-caption-text">On peut configurer l&#039;affichage assez précisement sur les epub</p></div>
<h2 id="lengin">L&#8217;engin</h2>
<p>Bon, passons un peu à lecture et au confort. Je n’avais jamais testé d&#8217;eReader auparavant et je suis bien surpris du confort de lecture par rapport à une tablette qui t&#8217;éclaire la tronche et te crame les yeux. L&#8217;eReader simule le rendu de l&#8217;encre sur du papier, il faudra donc une source de lumière à proximité pour voir quelque chose. La résolution n’a pas l&#8217;air exceptionnelle, quand les textes sont trop petits ils sont à la limite de disparaitre, mais avec une police de taille raisonnable c&#8217;est très propre. Ça supporte aussi les images, sauf que l&#8217;écran est en noir et blanc, pour tout ce qui est schéma c&#8217;est ok, mais pour des photos ça peut vite être dégueulasse.<br />
Le confort change également beaucoup selon le type de livre. On m’a demandé si la lecture de gros pavés n’était pas trop galère sur un reader de cette taille. Je pense que pour un livre classique (roman/nouvelle) il n’y aura pas trop de problèmes. Par contre, ça risque d&#8217;être beaucoup plus chiant pour les livres contenant de nombreux schémas/dessins (genre livre technique, manuel de maths, etc), ainsi que pour des livres d&#8217;informatique contenant du code où celui-ci sera étalé sur de nombreuses pages impliquant des retours en arrière (sans parlé du nombre de colonnes).</p>
<div id="attachment_6911" class="wp-caption aligncenter" style="width: 610px"><a href="http://sametmax.com/e-ink-et-confiseries/2013-07-26-11-58-56/" rel="attachment wp-att-6911"><img src="media/fb7eb720.2013-07-26-11.58.56.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/2013-07-26-11.58.56.jpg" alt="Un livre d&#039;info sur Kobo" title="Un livre d&#039;info sur Kobo" width="600" height="448" class="size-full wp-image-6911" /></a><p class="wp-caption-text">Un petit livre sur l&#039;informatique, même avec quelques schéma, ça passe nikel</p></div>
<p>L&#8217;objet en lui même à l&#8217;air de bonne qualité, ça tient bien dans les mains et c&#8217;est bien fini. Ça tient facilement dans une poche, ça sort de veille très vite et surtout ça ne consomme rien (juste aux changements de pages).</p>
<h2 id="lemoins">Le moins</h2>
<p>S’il n&#8217;y a rien à redire sur l&#8217;appareil en lui même, c&#8217;est au niveau du contenu proposé que ça pèche. Petit exemple, avec <a href="http://www.amazon.fr/tr%C3%B4ne-fer-George-R-R-Martin/dp/2290302864/ref=sr_1_14?s=books&amp;ie=UTF8&amp;qid=1374938578&amp;sr=1-14&amp;keywords=game+of+thrones">Le trône de fer, tome 1 [Poche]</a> chez Amazon ; qu&#8217;on me vende un bouquin physique 10€ ou plus ne me dérange pas, le papier et l&#8217;encre ne se sont pas donnés, ça reste un bel objet, on peut le prêter, le revendre, en louer, etc. Mais qu&#8217;on me vende un putain d&#8217;epub au même prix, voir des fois plus chères que l&#8217;ouvrage physique, un truc doit m&#8217;échapper ! Ici, 9€ le tome 1 de GoT au format numérique et 8,10€ la version poche, euh …<br />
Bon, je ne vais pas plus loin sur ce point, il faut savoir qu’il y a aussi des bouquins gratuits (de manières légales ou pas…).</p>
<div id="attachment_6903" class="wp-caption aligncenter" style="width: 610px"><a href="http://sametmax.com/e-ink-et-confiseries/p1020641/" rel="attachment wp-att-6903"><img src="media/5ab869b4.P1020641.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/P1020641.jpg" alt="La librairie du Kobo" title="La librairie du Kobo" width="600" height="800" class="size-full wp-image-6903" /></a><p class="wp-caption-text">…</p></div>
<h2 id="conclusion">Conclusion</h2>
<p>Cette version mini est super pour stocker un tas de bouquins &#8220;traditionnels&#8221; dans sa poche (1.2 go de livre pour 134g) tout en offrant un bon confort de lecture. Pour un usage à domicile, la taille supérieure est certainement un plus. Pour les amateurs de BD&#8217;s, comics ou autre bouquin contenant plein d&#8217;images (ou du code) il faudrait tester sur une liseuse plus grosse (par contre il ne me semble pas qu&#8217;il y&#8217;ai encore de version couleur) ou alors une tablette plus classique (iPad, ou autre). Pour ceux qui veulent un test plus en détail, il y&#8217;a <a href="http://www.lesnumeriques.com/liseuse/fnac-kobo-mini-p14419/test.html#test-complet" title="un article sur lesnumériques.com">un article sur lesnumériques.com</a></p>
<p>En tout cas, merci Sam et Max c&#8217;est un chouette cadeau ! Je ne sais pas trop pour le moment quelle sera mon utilisation et si ça va devenir un objet utilisé au quotidien, mais pourquoi pas. Je ne lis plus depuis quelques années (excepté des bouquins techniques et quelques bds), ça pourrait être l&#8217;occasion de s&#8217;y remettre vu la praticité de l&#8217;objet ! (Ah et pour les dragibus, ils ce sont pris une grosse branlée)</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6897&amp;md5=13e7d7723be1328ccb2bf063f84bbd83" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6929
title: Le ratio santé / sex
uri: Le-ratio-santé-sex
url: http://sametmax.com/le-ratio-sante-sex/
content:
<p>On dit qu&#8217;avoir une activité sexuelle régulière est bon pour la santé.</p>
<p>Je dis OK.</p>
<p>Mais quel est le prix, en terme de santé, d&#8217;une activité sexuelle régulière, quand on est pas en couple ?</p>
<p>Dans mon cercle social, les opportunités de s&#8217;envoyer en l&#8217;air se font en soirée. Bien entendu, il est possible de draguer dans la rue, au super marché, au club de sport, dans une asso&#8230; Mais soyons franc, la taux de succès est bien plus important en soirée car :</p>
<ul>
<li>Les autres servent de validation sociale.</li>
<li>Il n&#8217;y a pas besoin de trouver un prétexte artificiel pour aborder un nana.</li>
<li>C&#8217;est le soir. Allez comprendre pourquoi, mais c&#8217;est beaucoup plus difficile pour une meuf de coucher le premier après-midi que le premier soir.</li>
<li>Il y a de l&#8217;alcool.</li>
<li>Et il y a du temps.</li>
</ul>
<p>Maintenant, si vous voulez avoir une vie saine, cela exclut l&#8217;alcool, la malbouffe, et le fait de se coucher tard. C&#8217;est à dire absolument tout ce qui est concentré dans une soirée.</p>
<p>Pourquoi les soirées entre amis en France impliquent la plupart du temps un manque de sommeil, la présence de psychotropes et de nourriture de provenance douteuse ? Aucune idée. Ou plutôt, trop d&#8217;idées, et ce n&#8217;est pas le but de l&#8217;article.</p>
<p>Toujours est-il, quand on est un mec (parce que oui, une nana peut draguer même à cheval sur une moto-crotte, ça marchera), c&#8217;est dans ce genre de soirée qu&#8217;on choppe le plus. Et aussi qu&#8217;on s’abime le plus.</p>
<p>Du coup, on a le choix entre se ruiner la santé pour baiser, ou ne pas baiser, ce qui n&#8217;est pas très bon pour la santé.</p>
<p>Je suis quelqu&#8217;un de sociable, sportif, je fréquente des assos&#8230; Mais dès que j&#8217;arrête de prendre de l&#8217;alcool, dès que je décide de prendre moins de biscuits apéros, dès je quitte la soirée assez tôt pour dormir correctement, c&#8217;est foutu. Pendant ces périodes là, mes opportunités de galipette plongent rejoindre Jacques Mayol.</p>
<p>Évidement, on peut ressortir le vieux discours de la modération. Sauf qu&#8217;une soirée par semaine, et boire quelque verres, même en supposant que vous arrivez à ramener une petite à la maison 1 fois sur 3 (et la plupart des mecs sont loin d&#8217;avoir ce ratio), ça vous fait une session de sport en chambre voir deux par mois. Arf.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6929&amp;md5=53a449188ebbdb25309df2663aab0846" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6955
title: Entreprendre en France, Autopsie d’un échec.
uri: Entreprendre-en-France-Autopsie-d-un-échec
url: http://sametmax.com/entreprendre-en-france-autopsie-dun-echec/
content:
<p>Tout a commencé il y a 7 ans, d&#8217;une humeur fort incompatible avec ma hiérarchie et d&#8217;un tempérament plutôt entrepreneur je décida un peu par force de me lancer dans l&#8217;aventure avec un ancien collègue de travail.</p>
<p>Pour resituer le contexte nous sommes en 2003, je bosse pour une boite spécialisée dans l&#8217;affiliation sur internet. Un patron débile parachuté dans notre service alors qu&#8217;il n&#8217;avait jamais touché une bille. Un collègue de bureau pour qui la prog n&#8217;avait pas de secret, le genre de killer avec qui on aime boire une binouse le midi en refaisant le monde de l&#8217;internet tant ses connaissances sont illimitées.<br />
Bref un job sympa car on pensait ne pas être emmerdé par le boss et pouvoir développer nos produits, les faire évoluer, conquérir le monde, vous connaissez la suite&#8230;</p>
<p>En fait non. Le boss ne comprenait rien à rien, a planté la boite et nous a fait virer. On a fait un procès qu&#8217;on a gagné. Nous voilà au chômage, en procès, mais avec des cerveaux supervitaminés.<br />
On épluche les dossiers ACCRE, les aller-retour dans les jeudis de l&#8217;entreprise, les formations données par la chambre de commerce du coin.<br />
Au passage évitez tout ça, vous n&#8217;apprendrez rien, la France est à 100 000 années lumière du désir d&#8217;entreprendre, tout est fait pour vous démoraliser.<br />
Petites anecdotes:<br />
- Lors d&#8217;une demande d&#8217;aide un bureau d&#8217;études de faisabilité nous a reçu avec un grand sourire puis nous a défoncé auprès de l&#8217;ANPE.<br />
- Des anciens &#8220;chefs d&#8217;entreprise&#8221; à la retraite bossant dans le textile version boutique du coin venant donner des conseils à des mecs qui veulent se lancer dans l&#8217;info, voilà les jeudis de l&#8217;entreprise auxquels j&#8217;ai eu droit, bref&#8230;</p>
<p>Monter une boite à deux demande de créer une SARL, ce n&#8217;est pas une micro entreprise (qui de toutes façons n&#8217;est plus vraiment avantageux car bien taxé avec CA limité, etc).<br />
Pour une SARL il faut un comptable ou faire la compta soit-même mais je ne suis pas comptable alors on sous-traite, ça fait des frais mais on est sûr que c&#8217;est bien fait (normalement) et on peut se concentrer sur la création.</p>
<p><strong>On se lance!</strong><br />
Vers 2006 on décide de se lancer, pour démarrer il a fallu quand même 20 000 € (création de société 1400€, capital de base 1000€, bureaux 700€/mois, internet pro, un peu de matos, etc&#8230;).<br />
On s&#8217;est dit qu&#8217;avec 20 000€ on tiendrait quelques temps. La grosse erreur, au bout de quelques mois le RSI qui a l&#8217;époque était l&#8217;URSSAF + CSG qui nous avait épargné jusqu&#8217;à là grâce à un dossier monté à L&#8217;ACCRE commence son racket, une note de 6000€ tombe en prévision du salaire que je ne me suis pas versé l&#8217;année d&#8217;avant car la société datait de l&#8217;année en cours (les impots calculent les prélèvements à N-1, mais quand il y a pas eu d&#8217;activité avant ils estiment un montant, ici 6000 c&#8217;est pas mal pour un début).<br />
Mon associé ne s&#8217;étant pas payé on a limité la casse. à l&#8217;époque je me payais environ 800€/mois.</p>
<p><img src="media/b6be7410.impots.jpeg" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/impots.jpeg" alt="une journée aux impôts..." title="Il reste une goutte!" width="244" height="207" class="aligncenter size-full wp-image-6958" /><br />
<strong>On arrive à monter quelques projets mais on a besoin d&#8217;un employé, ouille!</strong><br />
L&#8217;erreur ou l&#8217;horreur qu&#8217;on a pas fait là! On embauche un petit jeune, un tueur, à l&#8217;époque il m&#8217;avait codé une espèce de serveur de streaming basique en C++, il codait vite, avait les idées claires, que du bonheur, mais&#8230;</p>
<p>Coucou c&#8217;est nous les impôts!<br />
Qui dit employé dit charges, et pas dans un an! Jeune pousse on avait pas beaucoup d&#8217;argent chaque mois, alors on a négocier le SMIC avec ce jeune, j&#8217;en ai encore honte aujourd&#8217;hui, on payait un killer le SMIC sans pouvoir lui garantir d&#8217;avenir.</p>
<p><strong>Entre le marteau et l&#8217;enclumme</strong><br />
D&#8217;un côté les impôts me demandaient environ 600€ de charges pour le payer le SMIC et de l&#8217;autre le jeune devait se taper 30 bornes par jour pour venir bosser (essence, autoroute, bouffe le midi, etc). Il y avait beaucoup de tension vers la fin et nous avons finalement trouver un commun accord pour en terminer, lui ne gagnait pas assez, nous payons trop.</p>
<p><img src="media/a7c9f6ec.pistorius.jpeg" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/pistorius.jpeg" alt="C&#039;est le premier pas qui compte..." title="Qu&#039;ils disaient" width="276" height="182" class="aligncenter size-full wp-image-6960" /><br />
<strong>La persévérance</strong><br />
Les projets sont au point mort, sans employé tout devenait plus dur, il fallait faire de l&#8217;admin système, gérer des clients, essayer de trouver des partenaires, etc&#8230; Je me sépare de deux projets qui demandaient du temps pour me consacrer à un seul sur lequel j&#8217;avais bossé.</p>
<p><img src="media/6b433690.dwarf.jpeg" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/dwarf.jpeg" alt="" title="ne pas pêter..." width="300" height="168" class="aligncenter size-full wp-image-6963" /><br />
<strong>La mini success-story</strong><br />
Je me suis retrouvé tout seul, mon associé étant occupé à bosser pour une autre boîte car ayant une famille à nourrir.<br />
Pas mal de nuits blanches, des serveurs qui pétaient de partout, je n&#8217;avais jamais fait d&#8217;admin système auparavant. Des scripts qui bouffaient de la mémoire, je restais au bureau tous les week-end jusqu&#8217;à 2 heures du mat parfois.<br />
Mais mon projet me rapportait de l&#8217;argent, j&#8217;ai commencé à voyager, rencontrer des gens, ramener quelques idées, des MST, etc.</p>
<p><img src="media/00988544.garisson.jpeg" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/garisson.jpeg" alt="" title="toute tentative restera vaine." width="263" height="192" class="aligncenter size-full wp-image-6964" /><br />
<strong>L&#8217;évolution impossible</strong><br />
Bien que mon projet me rapportait je ne me payais guerre plus de 2000€/mois, l&#8217;état et le comptable se chargeaient du reste, des charges de 10000€ annuelles auxquelles on rajoutait le comptable 3000€ quand il était de bonne hummeur, les loyers des bureaux, etc&#8230;<br />
Réembaucher quelqu&#8217;un n&#8217;aurait pas été envisageable au SMIC car j&#8217;avais retenu la leçon, il aurait alors fallut sortir au moins 40000€ / ans ( salaire + charges), trouver la bonne personne, etc.<br />
J&#8217;ai donc laissé l&#8217;entreprise stagner, toujours en réparant les &#8220;fuites&#8221;, bref être l&#8217;homme à tout faire.</p>
<p><strong>L&#8217;envie de tout arrêter</strong><br />
la dernière année m&#8217;a achevé, le RSI est monté à 980€/mois alors que ma rémunération avait baissée (je dois d&#8217;ailleurs récupérer un trop perçu, on verra&#8230;). Le comptable me facturait 350€ / mois pour 3 factures envoyées par email et 3 feuilles de relevés de compte.<br />
Plus trop envie de continuer dans un pays où il ne se passe pas un mois sans qu&#8217;on apprenne qu&#8217;un dirigeant ou homme politique a gagné des millions en magouilles sans être inquiété une seconde alors que moi j&#8217;ai droit à des mises en deumeurre quand j&#8217;ai une semaine de retard sur le paiement d&#8217;un acompte de TVA de quelques centaines d&#8217;euros&#8230;</p>
<p><img src="media/db4706ce.slaves.jpeg" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/slaves.jpeg" alt="" title="On fait quoi samedi soir ?" width="293" height="172" class="aligncenter size-full wp-image-6965" /><br />
<strong>Autour de moi, des esclaves</strong><br />
Point important qui m&#8217;a poussé à fermer la boite et à <a href="http://sametmax.com/max-se-barre/">quitter le pays</a>, la sensation d&#8217;être entouré d&#8217;esclaves.<br />
En effet beaucoup de mes amis sont aigris, moroses, n&#8217;ont pas vraiment de vision d&#8217;avenir, ils veulent juste arriver à finir le mois, attendent le samedi pour sortir car ils bossent pas le lendemain, veulent pas sortir en semaine, ne me parlent que de série TV ou de leurs gosses qu&#8217;il faut emmener à dysneyland mais ça coûte cher, tu comprends&#8230;</p>
<p><img src="media/11a27db4.abnormal.jpeg" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/abnormal.jpeg" alt="" title="Tout est normal" width="265" height="190" class="aligncenter size-full wp-image-6966" /><br />
<strong>Non je ne comprends pas</strong><br />
Je ne comprends pas ce monde en général, ce pays en particulier où on doit à tout prix avoir un iPhone, une caisse à crédit, un écran oled à crédit, un appartement à crédit, bref une vie à crédit.<br />
Pourquoi je continuerais dans un pays ou un système où je ne me reconnais pas ? Cela pourrait faire l&#8217;objet d&#8217;un autre article d&#8217;ailleurs.</p>
<p><strong>Bon ok j&#8217;arrête. Ha oui mais non monsieur faut encore payer.</strong><br />
Alors voilà après cette aventure je décide de fermer mon entreprise et de prendre le large. Je change de comptable au passage et en trouve un moins cher et plus cool.<br />
Il veut bien récupérer mon dossier (oui entre eux, les comptables se piquent pas toujours les clients, ils doivent faire une lettre, déontologie, tout ça&#8230;) mais me dit qu&#8217;il va falloir payer pour fermer l&#8217;entreprise. J&#8217;ai été surpris, la société est saine, jamais eu de défaut de paiement pourtant.<br />
Oui mais j&#8217;avais oublié que l&#8217;état se sert à l&#8217;entrée ET à la sortie. Il faut y inclure aussi les greffiers et autres administrateurs (journaux de publications), c&#8217;est une machine bien rodée.<br />
Au final pour fermer cette SARL cela m&#8217;a coûté 3174€, c&#8217;est pas mal quand même pour une TPE.<br />
&#8220;honoraires juridiques&#8221; &#8211; 400€ (sans précision)<br />
&#8220;annonce dans un journal de clôture&#8221; &#8211; 200€<br />
&#8220;annonce dans un journal de dissolution&#8221; &#8211; 120€<br />
&#8220;greffe&#8221; &#8211; 215 €<br />
&#8220;frais d&#8217;enregistrement au SIE&#8221; &#8211; 415 €<br />
&#8220;bilan comptable année en cours&#8221; &#8211; 700 €<br />
etc&#8230;<br />
Faites donc attention à avoir encore de l&#8217;argent sur le compte si vous décidez de fermer votre entreprise. Et encore là c&#8217;est dans le cas d&#8217;une petite entreprise saine sans passif.</p>
<p><strong>Conclusion</strong><br />
Tout n&#8217;a pas été négatif, je vais essayer de résumer ce que j&#8217;en ai retenu:</p>
<p><strong>Bon:</strong><br />
- J&#8217;ai bossé avec 2 personnes surdouées en info et j&#8217;ai beaucoup appris.<br />
- La liberté de bosser à l&#8217;heure qu&#8217;on veut.<br />
- L&#8217;excitation de mettre au jour des projets avec des associés, d&#8217;entreprendre ensembles.<br />
- Je comprends les patrons qui râlent pour augmenter les employés (sans toutefois les excuser)<br />
- ça m&#8217;a permis de rencontrer Sam (un ancien stagiaire de la boite d&#8217;à côté), j&#8217;allais pas l&#8217;oublier celui-là même si j&#8217;aurais pu le rencontrer ailleurs.<br />
- J&#8217;ai passé de bons moments sur des projets funs et beaucoup appris avec mes collaborateurs.</p>
<p><strong>Moins bon:</strong><br />
- j&#8217;ai compris que si un employé n&#8217;a pas à mangé le midi il va travailler moins bien.<br />
- L&#8217;Etat est là pour encaisser, L&#8217;Etat est là pour encaisser, L&#8217;Etat est là pour encaisser&#8230;<br />
- La France est une jungle en administratif et c&#8217;est ce qui va la perdre (la perd déjà en fait)<br />
- La France a pour but de tuer les TPE et PME, je ne vois pas comment il pourrait en être autrement, <a href="http://www.lesechos.fr/06/04/2011/LesEchos/20906-120-ECH_total-ne-paie-toujours-pas-d-impot-sur-les-societes.htm">Total paye 0€ d&#8217;impôts</a>, moi j&#8217;étais taxé à 60-70%.</p>
<p>PS: Je précise que j&#8217;aurais pu continuer à payer et me verser un salaire correct, mais je ne veux plus que mon argent aille <a href="http://www.lexpress.fr/actualite/societe/justice/affaire-karachi-edouard-balladur-soupconne-de-detournement-de-fonds-publics_1268775.html">là</a>, <a href="http://www.lepoint.fr/politique/proces-andrieux-un-an-de-prison-ferme-22-05-2013-1670921_20.php">là</a> ou encore <a href="http://www.newsring.fr/actualite/1003235-detournement-de-fonds-publics-jean-noel-guerini-mis-en-examen">là</a>.<br />
Je ne veux plus attendre le week-end pour sortir boire un verre.<br />
Je ne veux pas vivre à crédit.</p>
<p>PS: ne comparez pas cette expérience à des entreprises comme Meetic, là je parle de petite structure. Merci ;)</p>
<p>Et puis merde! Je suis jeune, je veux être libre et voir le monde ! :)</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6955&amp;md5=d1946e7f43e3309c0453b4776553c03b" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6987
title: Variables d’environnement utilisées par Python
uri: Variables-d-environnement-utilisées-par-Python
url: http://sametmax.com/variables-denvironnement-utilisees-par-python/
content:
<p>Avant même l&#8217;utilisation d&#8217;options, de fichiers de conf, et outils installés, les variables d&#8217;environnement sont un moyen pratique de configurer un programme. Il s&#8217;agit simplement d&#8217;une variable globale accessible dans le shell courant.</p>
<p>Par exemple, sous bash, pour créer une variable, il suffit de faire :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #007800;">NOMDEVARIABLE</span>=<span style="color: #ff0000;">'valeur'</span> <span style="color: #666666; font-style: italic;"># mettre la variable à la bonne valeur</span>
$ <span style="color: #7a0874; font-weight: bold;">export</span> NOMDEVARIABLE <span style="color: #666666; font-style: italic;"># rendre la variable globale</span></pre></div></div>

<p>La convention est de mettre leur nom en majuscule.</p>
<p>Et pour afficher la variable, il suffit de faire :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$NOMDEVARIABLE</span>
valeur</pre></div></div>

<p>Pourquoi c&#8217;est pratique ? Et bien parce qu&#8217;un programme comme Python va aussi aller regarder dans ces variables d&#8217;environnement pour se configurer. Donc, si vous settez la variable avec le bon nom dans votre shell et que vous lancez l&#8217;interpréteur Python, vous pouvez démarrer ce dernier avec un comportement différent, comme le ferait une option ou un fichier de config. La différence ? La variable est valable pour toute la session de shell, donc même si vous ressortez de l&#8217;interpréteur Python, et que vous le relancez, tant que vous êtes dans la même session de shell, la configuration reste la même.</p>
<h2>Variables attendues</h2>
<p><code>PYTHONSTARTUP</code>: un module à exécuter au démarrage de Python.</p>
<p>Pratique si vous savez que vous allez utiliser souvent le même code dans votre prochaine session de travail avec le shell. Par exemple, je crée un module <em>/tmp/imports.py</em> et je met dedans :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> json
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">pickle</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">datetime</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">datetime</span></pre></div></div>

<p>Ensuite, je set ma variable :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #007800;">PYTHONSTARTUP</span>=<span style="color: #ff0000;">'/tmp/imports.py'</span> 
$ <span style="color: #7a0874; font-weight: bold;">export</span> PYTHONSTARTUP</pre></div></div>

<p>Et en lançant l&#8217;interpréteur, même en sortant et en le relançant 50 fois de suite, je n&#8217;ai pas à importer ces modules.</p>
<p><code>PYTHONPATH</code> : une liste de dossiers séparés par &#8216;:&#8217; qui va être ajouté à sys.path</p>
<p>Vous savez qu&#8217;il y a des packages qui ne sont pas dans le PYTHON PATH, donc non importables. Mais pour le moment, vous voulez les utiliser quand même pour faire des tests vite fait (vous corrigerez le problème plus tard ^^).</p>
<p>Facile:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #007800;">PYTHONPATH</span>=<span style="color: #ff0000;">'/home/sam/un_dossier_qui_contient_mes_libs:/home/sam/projects/autre_projet'</span>
<span style="color: #7a0874; font-weight: bold;">export</span> <span style="color: #007800;">$PYTHONPATH</span></pre></div></div>

<p>Et voilà, tout ce qui est dans ces deux dossiers est importable.</p>
<p>Il y a encore :</p>
<p><code>PYTHONHOME</code> : choisir un autre dossier dans lequel chercher l&#8217;interpréteur Python.<br />
<code>PYTHONCASEOK</code> : ingorer la casse dans le nom des modules sous Windows<br />
<code>PYTHONIOENCODING</code> : forcer un encoding par défaut pour stdin/stdout/stderr<br />
<code>PYTHONHASHSEED</code> : changer la seed hash() (renforce la sécurité de la VM)</p>
<h2>Variables d&#8217;environnement permanentes</h2>
<p>Les programmes Python utilisent beaucoup les variables d&#8217;environnement : Django, Celery, nose, virtualenv, pip&#8230; Tous peuvent être <strong>aussi</strong> configurés avec ces variables.</p>
<p>Parfois, on voudra que cette variable soit accessible depuis tous les shells, et même après le reboot. Bref, rendre la configuration permanente.</p>
<p>Il y a plusieurs solutions. L&#8217;une est de mettre la déclaration de la variable dans le script de démarrage de votre shell, par exemple sous bash, de mettre la variable dans <em>.bashrc</em>.</p>
<p>Ainsi, j&#8217;ai des entrées comme celle-ci dans <a href="sametmax.com/a-linterieur-de-mon-bashrc/">mon .bashrc</a> :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># évite à pip de télécharger plusieurs fois la même lib à la réinstallation</span>
<span style="color: #007800;">PIP_DOWNLOAD_CACHE</span>=<span style="color: #ff0000;">'/opt/pip-cache'</span>;
<span style="color: #7a0874; font-weight: bold;">export</span> PIP_DOWNLOAD_CACHE;</pre></div></div>

<p>Une autre est de la mettre dans un hook, c&#8217;est à dire un script exécuté à un moment donné par un programme. De nombreux programmes ont des hooks, et il y a des exemples sur le blog pour <a href="http://sametmax.com/les-hooks-de-virtualenv-exemple-postactivate-pour-les-settings-de-django/">virtualenv</a> et <a href="http://sametmax.com/purger-les-fichiers-pyc-et-un-hook-git-en-bonus/">git</a>.</p>
<h2>Variables d&#8217;environnement personnalisées</h2>
<p>Vos propres programmes peuvent lire (pour se configurer) et écrire (pour configurer d&#8217;autres programme ou forcer leur propre configuration en cas de multiprocessing) des variables d&#8217;environnement. Il suffit de faire :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span>
<span style="color: black;">&#123;</span><span style="color: #483d8b;">'LC_NUMERIC'</span>: <span style="color: #483d8b;">'fr_FR.UTF-8'</span>, <span style="color: #483d8b;">'gs_max_changes'</span>: <span style="color: #483d8b;">'99'</span>, <span style="color: #483d8b;">'scmbDir'</span>: <span style="color: #483d8b;">'/home/sam/.scm_breeze'</span>, <span style="color: #483d8b;">'GNOME_DESKTOP_SESSION_ID'</span>: <span style="color: #483d8b;">'this-is-deprecated'</span>, <span style="color: #483d8b;">'AUTOJUMP_DATA_DIR'</span>: <span style="color: #483d8b;">'/home/sam/.local/share/autojump'</span>, <span style="color: #483d8b;">'LC_IDENTIFICATION'</span>: <span style="color: #483d8b;">'fr_FR.UTF-8'</span>, <span style="color: #483d8b;">'XDG_CURRENT_DESKTOP'</span>: <span style="color: #483d8b;">'Unity'</span>, <span style="color: #483d8b;">'GNOME_KEYRING_PID'</span>: <span style="color: #483d8b;">'2787'</span>, <span style="color: #483d8b;">'LOGNAME'</span>: <span style="color: #483d8b;">'sam'</span>, <span style="color: #483d8b;">'USER'</span>: <span style="color: #483d8b;">'sam'</span>, <span style="color: #483d8b;">'PROMPT_COMMAND'</span>: <span style="color: #483d8b;">'set_bash_prompt;preexec_invoke_cmd'</span>, <span style="color: #483d8b;">'PATH'</span>: <span style="color: #483d8b;">'/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games'</span>, <span style="color: #483d8b;">'LC_PAPER'</span>: <span style="color: #483d8b;">'fr_FR.UTF-8'</span>, <span style="color: #483d8b;">'GNOME_KEYRING_CONTROL'</span>: <span style="color: #483d8b;">'/home/sam/.cache/keyring-1rkOf1'</span>, <span style="color: #483d8b;">'design_av_dirs'</span>: <span style="color: #483d8b;">'Animations Videos Flash Music Samples'</span>, <span style="color: #483d8b;">'DISPLAY'</span>: <span style="color: #483d8b;">':0'</span>, <span style="color: #483d8b;">'SSH_AGENT_PID'</span>: <span style="color: #483d8b;">'2849'</span>, <span style="color: #483d8b;">'LANG'</span>: <span style="color: #483d8b;">'fr_FR.UTF-8'</span>, <span style="color: #483d8b;">'TERM'</span>: <span style="color: #483d8b;">'xterm'</span>, <span style="color: #483d8b;">'SHELL'</span>: <span style="color: #483d8b;">'/bin/bash'</span>, <span style="color: #483d8b;">'XDG_SESSION_PATH'</span>: <span style="color: #483d8b;">'/org/freedesktop/DisplayManager/Session0'</span>, <span style="color: #483d8b;">'XDG_SESSION_COOKIE'</span>: <span style="color: #483d8b;">'ccef8e8a757563a3c14c304f00000003-1375177738.724796-1812587231'</span>, <span style="color: #483d8b;">'LANGUAGE'</span>: <span style="color: #483d8b;">'fr_FR:fr_CA:en'</span>, <span style="color: #483d8b;">'SESSION_MANAGER'</span>: <span style="color: #483d8b;">'local/sam:@/tmp/.ICE-unix/2798,unix/sam:/tmp/.ICE-unix/2798'</span>, <span style="color: #483d8b;">'LC_MONETARY'</span>: <span style="color: #483d8b;">'fr_FR.UTF-8'</span>, <span style="color: #483d8b;">'LESSCLOSE'</span>: <span style="color: #483d8b;">'/usr/bin/lesspipe %s %s'</span>, <span style="color: #483d8b;">'MANDATORY_PATH'</span>: <span style="color: #483d8b;">'/usr/share/gconf/ubuntu.mandatory.path'</span>, <span style="color: #483d8b;">'DBUS_SESSION_BUS_ADDRESS'</span>: <span style="color: #483d8b;">'unix:abstract=/tmp/dbus-4sjzHNl8JS,guid=6ea6a72c49faf1630800018'</span>, <span style="color: #483d8b;">'VIRTUALENVWRAPPER_LOG_DIR'</span>: <span style="color: #483d8b;">'/home/sam/.virtualenvs'</span>, <span style="color: #483d8b;">'COMPIZ_CONFIG_PROFILE'</span>: <span style="color: #483d8b;">'ubuntu'</span>, <span style="color: #483d8b;">'EDITOR'</span>: <span style="color: #483d8b;">'/usr/bin/textadept'</span>, <span style="color: #483d8b;">'DESKTOP_AUTOSTART_ID'</span>: <span style="color: #483d8b;">'10b40d4ebf3d1cf3fd700000027980010'</span>, <span style="color: #483d8b;">'GPG_AGENT_INFO'</span>: <span style="color: #483d8b;">'/home/sam/.cache/keyring-1rkOf1/gpg:0:1'</span>, <span style="color: #483d8b;">'HOME'</span>: <span style="color: #483d8b;">'/home/sam'</span>, <span style="color: #483d8b;">'WORKON_HOME'</span>: <span style="color: #483d8b;">'/home/sam/.virtualenvs'</span>, <span style="color: #483d8b;">'SHLVL'</span>: <span style="color: #483d8b;">'1'</span>, <span style="color: #483d8b;">'SSH_AUTH_SOCK'</span>: <span style="color: #483d8b;">'/home/sam/.cache/keyring-1rkOf1/ssh'</span>, <span style="color: #483d8b;">'VIRTUALENVWRAPPER_HOOK_DIR'</span>: <span style="color: #483d8b;">'/home/sam/.virtualenvs'</span>, <span style="color: #483d8b;">'LC_ADDRESS'</span>: <span style="color: #483d8b;">'fr_FR.UTF-8'</span>, <span style="color: #483d8b;">'COMP_WORDBREAKS'</span>: <span style="color: #483d8b;">' <span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;<span style="color: #000099; font-weight: bold;">\'</span>&gt;&lt;;|&amp;(:'</span>, <span style="color: #483d8b;">'root_design_dir'</span>: <span style="color: #483d8b;">'/home/sam/Dropbox/Design'</span>, <span style="color: #483d8b;">'GDMSESSION'</span>: <span style="color: #483d8b;">'ubuntu'</span>, <span style="color: #483d8b;">'project_design_dir'</span>: <span style="color: #483d8b;">'design_assets'</span>, <span style="color: #483d8b;">'git_status_command'</span>: <span style="color: #483d8b;">'git_status_shortcuts'</span>, <span style="color: #483d8b;">'XDG_SEAT_PATH'</span>: <span style="color: #483d8b;">'/org/freedesktop/DisplayManager/Seat0'</span>, <span style="color: #483d8b;">'LC_ALL'</span>: <span style="color: #483d8b;">'fr_FR.UTF-8'</span>, <span style="color: #483d8b;">'LESSOPEN'</span>: <span style="color: #483d8b;">'| /usr/bin/lesspipe %s'</span>, <span style="color: #483d8b;">'git_env_char'</span>: <span style="color: #483d8b;">'e'</span>, <span style="color: #483d8b;">'_'</span>: <span style="color: #483d8b;">'/usr/bin/python'</span>, <span style="color: #483d8b;">'DEFAULTS_PATH'</span>: <span style="color: #483d8b;">'/usr/share/gconf/ubuntu.default.path'</span>, <span style="color: #483d8b;">'VIRTUALENVWRAPPER_PROJECT_FILENAME'</span>: <span style="color: #483d8b;">'.project'</span>, <span style="color: #483d8b;">'DESKTOP_SESSION'</span>: <span style="color: #483d8b;">'ubuntu'</span>, <span style="color: #483d8b;">'GIT_REPO_DIR'</span>: <span style="color: #483d8b;">'/home/sam/Work'</span>, <span style="color: #483d8b;">'XDG_CONFIG_DIRS'</span>: <span style="color: #483d8b;">'/etc/xdg/xdg-ubuntu:/etc/xdg'</span>, <span style="color: #483d8b;">'GTK_MODULES'</span>: <span style="color: #483d8b;">'canberra-gtk-module:canberra-gtk-module'</span>, <span style="color: #483d8b;">'UBUNTU_MENUPROXY'</span>: <span style="color: #483d8b;">'libappmenu.so'</span>, <span style="color: #483d8b;">'AUTOJUMP_HOME'</span>: <span style="color: #483d8b;">'/home/sam'</span>, <span style="color: #483d8b;">'LC_TELEPHONE'</span>: <span style="color: #483d8b;">'fr_FR.UTF-8'</span>, <span style="color: #483d8b;">'XAUTHORITY'</span>: <span style="color: #483d8b;">'/home/sam/.Xauthority'</span>, <span style="color: #483d8b;">'LC_MEASUREMENT'</span>: <span style="color: #483d8b;">'fr_FR.UTF-8'</span>, <span style="color: #483d8b;">'PWD'</span>: <span style="color: #483d8b;">'/home/sam'</span>, <span style="color: #483d8b;">'PIP_DOWNLOAD_CACHE'</span>: <span style="color: #483d8b;">'/opt/pip-cache'</span>, <span style="color: #483d8b;">'design_ext_dirs'</span>: <span style="color: #483d8b;">'Fonts IconSets'</span>, <span style="color: #483d8b;">'ga_auto_remove'</span>: <span style="color: #483d8b;">'yes'</span>, <span style="color: #483d8b;">'LC_NAME'</span>: <span style="color: #483d8b;">'fr_FR.UTF-8'</span>, <span style="color: #483d8b;">'design_base_dirs'</span>: <span style="color: #483d8b;">'Images Backgrounds Logos Icons Mockups Screenshots'</span>, <span style="color: #483d8b;">'LC_TIME'</span>: <span style="color: #483d8b;">'fr_FR.UTF-8'</span>, <span style="color: #483d8b;">'LS_COLORS'</span>: <span style="color: #483d8b;">'rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:'</span>, <span style="color: #483d8b;">'XDG_DATA_DIRS'</span>: <span style="color: #483d8b;">'/usr/share/ubuntu:/usr/share/gnome:/usr/local/share/:/usr/share/'</span>, <span style="color: #483d8b;">'GIT_REPOS'</span>: <span style="color: #483d8b;">''</span><span style="color: black;">&#125;</span></pre></div></div>

<p>C&#8217;est un simple dico dans lequel vous pouvez lire et écrire. Comme vous pouvez le voir, il ne s&#8217;agit pas juste des variables qui concernent Python mais de toutes celle de la session, donc attention, de grands pouvoirs impliquent de grandes possibilités de merder.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6987&amp;md5=cc6648dda499cd40749c5bdfbe37e2e2" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6991
title: FIRST !
uri: FIRST
url: http://sametmax.com/first/
content:
<p>Cherchant un post pas trop long à faire car j&#8217;ai été malade comme un chien depuis hier, je m&#8217;étais chauffé pour faire une intro au module <a href="http://docs.python.org/2/library/array.html">array</a>. Et puis, changeant d&#8217;avis par flemme, j&#8217;ouvre le code de <a href="http://sametmax.com/batbelt-la-lib-des-petits-outils-python-qui-vont-bien/">batbelt</a>, et je cherche un petit snippet que je n&#8217;ai pas présenté.</p>
<p>Bonne pêche !</p>
<p>Voici des fonctions qui s&#8217;utilisent sur des itérables, n&#8217;importe lequel, même un dont la taille est inconnu ou infini. La première retourne le premier élément, et, si l&#8217;itérable est vide, elle retourne une valeur par défaut :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> first<span style="color: black;">&#40;</span>iterable, default=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> iterable:
        <span style="color: #ff7700;font-weight:bold;">return</span> x
    <span style="color: #ff7700;font-weight:bold;">return</span> default</pre></div></div>

<p>C&#8217;est une sorte de [0], mais valable pour tous les itérables, par juste les indexables comme les tuples, les strings ou les listes. Et en prime, pas besoin de faire un <code>try / catch</code> dessus puisqu&#8217;il permet une valeur par défaut :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> first<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">0</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> first<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>, <span style="color: #483d8b;">'flammkuchen'</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'flammkuchen'</span></pre></div></div>

<p>Le second est aussi sympathique, il fait la même chose, mais retourne l&#8217;élément seulement si il est vrai :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> first_true<span style="color: black;">&#40;</span>iterable, key=<span style="color: #ff7700;font-weight:bold;">lambda</span> x: x, default=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> iterable:
        <span style="color: #ff7700;font-weight:bold;">if</span> key<span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">return</span> x
    <span style="color: #ff7700;font-weight:bold;">return</span> default</pre></div></div>

<p><code>key</code> fonctionne comme pour la fonction <code>sorted()</code>, à savoir que c&#8217;est une injection de dépendance. C&#8217;est cette fonction qui va déterminer si l&#8217;élément est vrai ou non. Par défaut la fonction retourne l&#8217;élément tel quel, et le fait qu&#8217;il soit vrai ou non sera donc déterminé par son contexte booléen :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> first_true<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">1</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> first_true<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> first_true<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>, <span style="color: #ff7700;font-weight:bold;">lambda</span> x: x<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> first_true<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>, <span style="color: #ff7700;font-weight:bold;">lambda</span> x: x<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>, <span style="color: #483d8b;">'socca'</span><span style="color: black;">&#41;</span>
u<span style="color: #483d8b;">'socca'</span></pre></div></div>

<p>Ce petit article m&#8217;a fait réaliser qu&#8217;on pourrait sans problème fusionner les deux en faisant :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> first<span style="color: black;">&#40;</span>iterable, key=<span style="color: #ff7700;font-weight:bold;">lambda</span> x: <span style="color: #008000;">True</span>, default=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> iterable:
        <span style="color: #ff7700;font-weight:bold;">if</span> key<span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">return</span> x
    <span style="color: #ff7700;font-weight:bold;">return</span> default</pre></div></div>

<p>Mais j&#8217;ai pas la foi de faire un commit ce soir, donc fuck.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6991&amp;md5=f155fd4a2123613ca95a3d7778623717" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


