# articles

feed_id: http://sametmax.com/?p=4521
title: Si vous ne savez pas ce que contient une variable, vous ne comprenez pas le programme
uri: Si-vous-ne-savez-pas-ce-que-contient-une-variable-vous-ne-comprenez-p
url:
http://sametmax.com/si-vous-ne-savez-pas-ce-que-contient-une-variable-vous-ne-comprenez-pas-le-programme/

content:
<p>L&#8217;immense majorité des questions qu&#8217;on me pose sur le fonctionnement d&#8217;un programme (ou sur des détails dans les tutos) peut être résolu d&#8217;une seule manière. </p>
<p>En sachant ce qu&#8217;il y a dans les variables.</p>
<p>Un ordinateur est une machine à états. Les variables représentent cet état. Le seul moyen de comprendre ce que fait un programme, c&#8217;est de savoir à quel moment il est dans quel état.</p>
<p>Quand vous ne comprenez pas ce que fait un programme, la première et plus importante question à vous poser et donc :</p>
<p><strong>Que contient cette variable ?</strong></p>
<h2>Répondre à la question</h2>
<p>La beauté de Python, c&#8217;est qu&#8217;il vous permet de très facilement répondre à cette question par vous même. Tout ce que vous avez à faire c&#8217;est copier le code, le mettre dans un fichier (ou un shell), et le lancer.</p>
<p><strong>Ne restez pas passif devant un tuto.</strong> Vous n&#8217;en comprendrez que la moitié (au mieux).</p>
<p>Un tuto, une doc, un cours, un snippet ne se lit pas, il se travaille. </p>
<p>Voici tout ce que vous pouvez faire à une variable pour obtenir des informations sur elle :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> i = <span style="color: #ff4500;">1</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># afficher la variable</span>
<span style="color: #ff4500;">1</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #008000;">type</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># afficher son type</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: black;">&#40;</span>i.__class__<span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># afficher la classe dont elle est issue</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: black;">&#40;</span>i.__class__.__name__<span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># affiche le nom de sa classe</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #008000;">dir</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># afficher les méthodes de cet objet</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'__abs__'</span>, <span style="color: #483d8b;">'__add__'</span>, <span style="color: #483d8b;">'__and__'</span>, <span style="color: #483d8b;">'__class__'</span>, <span style="color: #483d8b;">'__cmp__'</span>, <span style="color: #483d8b;">'__coerce__'</span>, <span style="color: #483d8b;">'__delattr__'</span>, <span style="color: #483d8b;">'__div__'</span>, <span style="color: #483d8b;">'__divmod__'</span>, <span style="color: #483d8b;">'__doc__'</span>, <span style="color: #483d8b;">'__float__'</span>, <span style="color: #483d8b;">'__floordiv__'</span>, <span style="color: #483d8b;">'__format__'</span>, <span style="color: #483d8b;">'__getattribute__'</span>, <span style="color: #483d8b;">'__getnewargs__'</span>, <span style="color: #483d8b;">'__hash__'</span>, <span style="color: #483d8b;">'__hex__'</span>, <span style="color: #483d8b;">'__index__'</span>, <span style="color: #483d8b;">'__init__'</span>, <span style="color: #483d8b;">'__int__'</span>, <span style="color: #483d8b;">'__invert__'</span>, <span style="color: #483d8b;">'__long__'</span>, <span style="color: #483d8b;">'__lshift__'</span>, <span style="color: #483d8b;">'__mod__'</span>, <span style="color: #483d8b;">'__mul__'</span>, <span style="color: #483d8b;">'__neg__'</span>, <span style="color: #483d8b;">'__new__'</span>, <span style="color: #483d8b;">'__nonzero__'</span>, <span style="color: #483d8b;">'__oct__'</span>, <span style="color: #483d8b;">'__or__'</span>, <span style="color: #483d8b;">'__pos__'</span>, <span style="color: #483d8b;">'__pow__'</span>, <span style="color: #483d8b;">'__radd__'</span>, <span style="color: #483d8b;">'__rand__'</span>, <span style="color: #483d8b;">'__rdiv__'</span>, <span style="color: #483d8b;">'__rdivmod__'</span>, <span style="color: #483d8b;">'__reduce__'</span>, <span style="color: #483d8b;">'__reduce_ex__'</span>, <span style="color: #483d8b;">'__repr__'</span>, <span style="color: #483d8b;">'__rfloordiv__'</span>, <span style="color: #483d8b;">'__rlshift__'</span>, <span style="color: #483d8b;">'__rmod__'</span>, <span style="color: #483d8b;">'__rmul__'</span>, <span style="color: #483d8b;">'__ror__'</span>, <span style="color: #483d8b;">'__rpow__'</span>, <span style="color: #483d8b;">'__rrshift__'</span>, <span style="color: #483d8b;">'__rshift__'</span>, <span style="color: #483d8b;">'__rsub__'</span>, <span style="color: #483d8b;">'__rtruediv__'</span>, <span style="color: #483d8b;">'__rxor__'</span>, <span style="color: #483d8b;">'__setattr__'</span>, <span style="color: #483d8b;">'__sizeof__'</span>, <span style="color: #483d8b;">'__str__'</span>, <span style="color: #483d8b;">'__sub__'</span>, <span style="color: #483d8b;">'__subclasshook__'</span>, <span style="color: #483d8b;">'__truediv__'</span>, <span style="color: #483d8b;">'__trunc__'</span>, <span style="color: #483d8b;">'__xor__'</span>, <span style="color: #483d8b;">'bit_length'</span>, <span style="color: #483d8b;">'conjugate'</span>, <span style="color: #483d8b;">'denominator'</span>, <span style="color: #483d8b;">'imag'</span>, <span style="color: #483d8b;">'numerator'</span>, <span style="color: #483d8b;">'real'</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">help</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># aide sur cet objet</span>
Help on <span style="color: #008000;">int</span> <span style="color: #008000;">object</span>:
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>
 |  <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#91;</span>, base<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span> -<span style="color: #66cc66;">&gt;</span> integer
 |  
 |  Convert a <span style="color: #dc143c;">string</span> <span style="color: #ff7700;font-weight:bold;">or</span> number to an integer, <span style="color: #ff7700;font-weight:bold;">if</span> possible.  <span style="color: black;">A</span> floating point
 |  argument will be truncated towards zero <span style="color: black;">&#40;</span>this does <span style="color: #ff7700;font-weight:bold;">not</span> include a <span style="color: #dc143c;">string</span>
 |  representation of a floating point number<span style="color: #66cc66;">!</span><span style="color: black;">&#41;</span>  When converting a <span style="color: #dc143c;">string</span>, use
 |  the optional base.  <span style="color: black;">It</span> <span style="color: #ff7700;font-weight:bold;">is</span> an error to supply a base when converting a
 |  non-<span style="color: #dc143c;">string</span>.  <span style="color: black;">If</span> base <span style="color: #ff7700;font-weight:bold;">is</span> zero, the proper base <span style="color: #ff7700;font-weight:bold;">is</span> guessed based on the
 |  <span style="color: #dc143c;">string</span> content.  <span style="color: black;">If</span> the argument <span style="color: #ff7700;font-weight:bold;">is</span> outside the integer <span style="color: #008000;">range</span> a
 |  <span style="color: #008000;">long</span> <span style="color: #008000;">object</span> will be returned instead.
 |  
 |  Methods defined here:
 |  
 |  <span style="color: #0000cd;">__abs__</span><span style="color: black;">&#40;</span>...<span style="color: black;">&#41;</span>
 |      x.<span style="color: #0000cd;">__abs__</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&lt;</span>==<span style="color: #66cc66;">&gt;</span> <span style="color: #008000;">abs</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>
...</pre></div></div>

<p>Ces informations répondent à la question &#8220;qu&#8217;est-ce que c&#8217;est&#8221;, &#8220;comment c&#8217;est configuré&#8221; et &#8220;qu&#8217;est-ce que ça peut faire&#8221;.</p>
<p>C&#8217;est très important. Vous ne pouvez pas comprendre ce que fait un programme sans ces informations.</p>
<h2>En Python une variable peut contenir n&#8217;importe quoi</h2>
<p>J&#8217;ai dis <strong>n&#8217;importe quoi</strong>.</p>
<p>Pas juste les types de base :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> i = <span style="color: #483d8b;">'a'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>i<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> i = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>i<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> i = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>type <span style="color: #483d8b;">'list'</span><span style="color: #66cc66;">&gt;</span></pre></div></div>

<p>Ni même juste des résultats de fonctions :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> i = <span style="color: #dc143c;">test</span><span style="color: black;">&#40;</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>i<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></pre></div></div>

<p>Non. Les variables Python peuvent contenir <strong>les fonctions elles-même</strong> !</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><span style="color: black;">&#40;</span><span style="color: #dc143c;">test</span><span style="color: black;">&#41;</span>
<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> i = <span style="color: #dc143c;">test</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> i<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">1</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>type <span style="color: #483d8b;">'function'</span><span style="color: #66cc66;">&gt;</span></pre></div></div>

<p>Et là ça devient important de savoir de quoi on parle :</p>

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

<p>Mais les variables peuvent aussi contenir des instances de vos 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;">class</span> Essai<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> i = Essai<span style="color: black;">&#40;</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>i<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>class <span style="color: #483d8b;">'__main__.Essai'</span><span style="color: #66cc66;">&gt;</span></pre></div></div>

<p>Sauf que les variables peuvent aussi contenir <strong>les classes elles-même</strong> !</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><span style="color: black;">&#40;</span>Essai<span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># les classes sont de type 'type'. Funky !</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> i = Essai <span style="color: #808080; font-style: italic;"># ceci n'est PAS une instance. Ce n'est PAS Essai().</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>Essai<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> i.__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> i.__name__
<span style="color: #483d8b;">'Essai'</span></pre></div></div>

<p>Les fonctions et les classes ne sont pas juste des noms en Python. Ce sont des choses que vous pouvez manipuler. Donc on les retrouve dans des variables.   </p>
<p>Donc vous n&#8217;avez pas le choix. Vous devez savoir de quoi on parle. Et il faut donc bien comprendre ce qu&#8217;est un type, et qu&#8217;est-ce qui est de quel type :</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><span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># str est une classe</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: #008000;">type</span><span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># le résultat de l'appel de str est une string</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: #008000;">type</span><span style="color: black;">&#40;</span>Essai<span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># Essai est une classe</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: #008000;">type</span><span style="color: black;">&#40;</span>Essai<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># le résultat de l'appel de Essai est un objet Essai</span>
<span style="color: #66cc66;">&lt;</span>class <span style="color: #483d8b;">'__main__.Essai'</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'1'</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># '1' est une string</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: #008000;">type</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># 1 est un int</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: #008000;">type</span><span style="color: black;">&#40;</span><span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>type <span style="color: #483d8b;">'bool'</span><span style="color: #66cc66;">&gt;</span> <span style="color: #808080; font-style: italic;"># True est un boolean</span></pre></div></div>

<p>Si vous ne comprenez pas les types, vous ne pouvez PAS comprendre un programme. </p>
<p>Ce n&#8217;est pas honteux. Arrêtez d&#8217;essayer un truc impossible, c&#8217;est tout. Revenez en arrière. Allez apprendre ce qu&#8217;est un type x ou z. </p>
<p>Puis retournez essayer de comprendre le programme. </p>
<p>Il n&#8217;y a PAS d&#8217;alternative.</p>
<p> <strong>Quand vous lisez un programme, vous devez savoir ce qu&#8217;il y a dans une variable</strong> :</p>
<ul>
<li>quel est son type ?</li>
<li>quelle est sa valeur ?</li>
<li>qu&#8217;est-ce que je peux faire avec (méthodes, attributs, etc) ?</li>
</ul>
<h2>Pdb à la rescousse</h2>
<p>Donc quand vous lisez un tuto, vous allez copier / coller du code. Vous allez le lancer. Si vous ne le faites pas, vous ne comprendrez pas.</p>
<p>Maintenant, dans un premier temps vous allez utiliser des print.</p>
<p><code>print type(truc)<br />
print truc.__class__<br />
print dir(truc)</code></p>
<p>Et pour les fonctions et les classes :</p>
<p><code>print truc.__name__</code></p>
<p>Mais on peut faire mieux. Utilisez le debugger de Python intégré : PDB. J&#8217;ai écrit <a href="http://sametmax.com/debugger-en-python-les-bases-de-pdb/">un bon article sur la question</a>, mais pour résumer, quand vous voulez avoir des informations sur une variable dans un programme, juste avant la variable faites :</p>
<p><code>import ipdb; ipdb.set_trace()</code></p>
<p>Puis lancez le programme. Un shell va s&#8217;ouvrir, bloquant le programme à cet endroit. Et vous pourrez manipuler la variable <strong>à ce moment du programme</strong>.</p>
<p>Pour quitter, entrez <code>q</code>.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=4521&amp;md5=fa08fd4047dfedc71f94709a1a26542f" 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=4452
uri: nginx-emerg-worker_processes-directive-is-not-allowed-here-in
title:
nginx: [emerg] “worker_processes” directive is not allowed here in /usr/local/nginx/conf/nginx.conf:3

url:
http://sametmax.com/nginx-emerg-worker_processes-directive-is-not-allowed-here-in-usrlocalnginxconfnginx-conf3/

content:
<p>Cette erreur arrive quand la directive &#8220;worker_processes&#8221; est incluse une deuxième fois. Typiquement cela arrive quand on a <code>include *.conf</code> dans son <em>nginx.conf</em> et que cela inclut <em>nginx.conf</em> lui même. </p>
<p>Il faut donc être spécifique sur les fichiers à inclure <code>include site.conf</code> ou déplacer <em>nginx.conf</em> dans un autre dossier que celui des sous fichiers de configuration.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=4452&amp;md5=5d3c98eeb2873b16e81bd8bfb5f0d65a" 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=4543
title: Demandez leur de garder un accessoire
uri: Demandez-leur-de-garder-un-accessoire
url: http://sametmax.com/demandez-leur-de-garder-un-accessoire/
content:
<p>Le cul, c&#8217;est fait pour être fun. C&#8217;est la dinette des adultes.</p>
<p>Mais trop de mecs n&#8217;osent pas demander des variantes de peur de sortir un truc con et péter l&#8217;ambiance. C&#8217;est vrai que ça peut dépendre de beaucoup de paramètres, et si vous êtes en mode vache maigre depuis fort fort longtemps, c&#8217;est pas le moment de suggérer une brouette pékinoise déguisés en kapo nazi. On sait jamais.</p>
<div id="attachment_4545" class="wp-caption aligncenter" style="width: 410px"><a href="media/aa38a031.tumblr_ln5ialxYvD1qlgyozo1_400.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/tumblr_ln5ialxYvD1qlgyozo1_400.jpg"><img class="size-full wp-image-4545" title="La référence offensante à une communauté, checked." src="media/aa38a031.tumblr_ln5ialxYvD1qlgyozo1_400.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/tumblr_ln5ialxYvD1qlgyozo1_400.jpg" alt="Photo d'une nazi sexy" width="400" height="500" /></a><p class="wp-caption-text">La référence offensante à une communauté, checked.</p></div>
<p>Pour vous exercer à faire des demandes dans l&#8217;action, commencez par un truc simple, neutre et marrant : demandez leur de garder un accessoire. Vous ne risquez pas grand chose, si elle le porte déjà, c&#8217;est qu&#8217;elle se sent pas idiote avec.</p>
<p>L&#8217;idée est donc d&#8217;exprimer, en une phrase courte et simple (et toujours avec le sourir, on baise, on est pas en cours de latin) le désir qu&#8217;elle garde :</p>
<ol>
<li>son collier</li>
<li>sa ceinture</li>
<li>ses chaussures à talons</li>
<li>la réponse D</li>
</ol>
<div id="attachment_4544" class="wp-caption aligncenter" style="width: 425px"><a href="media/9cd43a96.nude_girl_gold_belt_B-753723.jpeg" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/nude_girl_gold_belt_B-753723.jpeg"><img class=" wp-image-4544   " title="Avec une ceinture bien large, on peut s'en servir comme des rênes en levrette" src="media/9cd43a96.nude_girl_gold_belt_B-753723.jpeg" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/nude_girl_gold_belt_B-753723.jpeg" alt="Photo d'une femme nue portant juste une ceinture large" width="415" height="233" /></a><p class="wp-caption-text">Avec une ceinture bien large, on peut s&#39;en servir comme des rênes en levrette</p></div>
<p>Plus l’accessoire est proéminent (un gros collier de perle est plus fun qu&#8217;une chaînette en argent, une ceinture large avec une énorme boucle est plus cool qu&#8217;un lacet, des talons girafes, plus marrantes que &#8230; bref, vous avez compris)&#8230;</p>
<p>Si vous êtes vraiment pas à l&#8217;aise, faites encore plus simple. Demandez-lui de garder juste le haut ou la minijupe, ou les bas.</p>
<div id="attachment_4546" class="wp-caption aligncenter" style="width: 310px"><a href="media/78818ded.blonde_drew_in_short_jean_skirt_closepics_6544.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/blonde_drew_in_short_jean_skirt_closepics_6544.jpg"><img class="size-full wp-image-4546" title="Après tout le trop &quot;girl next door&quot; est aussi bon qu'un autre" src="media/78818ded.blonde_drew_in_short_jean_skirt_closepics_6544.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/blonde_drew_in_short_jean_skirt_closepics_6544.jpg" alt="Photo d'une femme nue avec seulement sa mini-jupe" width="300" height="450" /></a><p class="wp-caption-text">Après tout le trip &quot;girl next door&quot; est aussi bon qu&#39;un autre</p></div>
<p>Le faire régulièrement va amener de nombreux avantages :</p>
<ul>
<li>ça introduit un peu de changement.</li>
<li>on peut jouer avec l&#8217;accessoire : lever la croupe par la ceinture, prendre contre le mur via la minijupe, plaquer sur le lit avec le collier, écarter les jambes par les talons, etc).</li>
<li>vous apprenez à découvrir ce que vous aimez, érotiquement. Même si ça reste très basique.</li>
<li>vous apprenez à gérer : les demandes de truc spéciaux, la communication en pleine action et le changement de contexte. Comme il y a mille manières de casser le mood en le faisant mal, autant pratiquer.</li>
</ul>
<div id="attachment_4552" class="wp-caption aligncenter" style="width: 600px"><a href="media/b50be56b.28271.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/28271.jpg"><img class="size-full wp-image-4552" title="Les talons incitent à la cambrure indispensable pour la majorité des prises par l'arrière. Sinon, ben, ça s'emboîte mal. L'anatomie, tout ça." src="media/b50be56b.28271.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/28271.jpg" alt="Photo d'une femme nue avec des talons aiguilles" width="590" height="400" /></a><p class="wp-caption-text">Les talons incitent à la cambrure indispensable pour la majorité des prises par l&#39;arrière. Sinon, ben, ça s&#39;emboîte mal. L&#39;anatomie, tout ça.</p></div>
<p>Bref, c&#8217;est un truc simple, à la portée de tout le monde, qui ne peut avoir que des bénéfices. Et surtout, il y a peu de nanas qui vous enverront sur les roses (ce qui n&#8217;est pas le cas de baiser en extérieur, aller dans un club échangiste, utiliser des toys et accessoires non cosmétiques, faire de jeux de rôles, etc).</p>
<p>C&#8217;est safe and fun, comme les préservatifs lumineux. Ou pas.</p>
<div id="attachment_4547" class="wp-caption aligncenter" style="width: 560px"><a href="media/86689d21.collier-perle.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/collier-perle.jpg"><img class="size-full wp-image-4547" title="Une fois que tout le monde est à l'aise, on peut se lancer dans le combo" src="media/86689d21.collier-perle.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/collier-perle.jpg" alt="Photo d'une jeune fille nue avec un collier de perle et des bas" width="550" height="822" /></a><p class="wp-caption-text">Une fois que tout le monde est à l&#39;aise, on peut se lancer dans le combo. Bon en même temps aucune meuf se balade avec ça. Si vous les voulez, faudra probablement les acheter vous-même.</p></div>
<p>&nbsp;</p>
<p>&nbsp;</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=4543&amp;md5=d73750e99066085e59fc02a53fe5d12f" 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=4556
title: Quelqu’un peut-il m’expliquer cet étrange phénomène mailistique ?
uri: Quelqu-un-peut-il-m-expliquer-cet-étrange-phénomène-mailistique
url: http://sametmax.com/quelquun-peut-il-mexpliquer-cet-etrange-phenomene-mailistique/
content:
<p>J&#8217;ai une adresse email en nomprenom@gmail.com (hé oui, <a href="http://sametmax.com/quitter-google-recherche-email-et-chat/">il m&#8217;en reste quelques unes</a>&#8230; Il faut dire que j&#8217;ai 7 emails, sans compter les alias, les antispam et les comptes bidons).</p>
<p>Par erreur, je m&#8217;inscris sur un service avec nom<span style="color: #ff0000;"><strong>.</strong></span>prenom@gmail.com. Notez le point, que mon adresse n&#8217;a PAS. Qu&#8217;elle n&#8217;a jamais eu. Je reçois régulièrement des mails à cette adresse SANS le point.</p>
<p>Malgré cela, je reçois le mail de confirmation d&#8217;inscription à nomprenom@gmail.com (la bonne, sans le point).</p>
<p>Dans le message, il y a clairement :</p>
<blockquote><p>has received a request to create a user account using your email address (nom<strong>.</strong>prenom@gmail.com).</p></blockquote>
<p>Je check les sources:</p>
<pre>Delivered-To: nom.prenom@gmail.com
Received: by IP_ADDRESS with SMTP id u10csp168283wja;
        Thu, 14 Feb 2013 05:48:57 -0800 (PST)
X-Received: by IP_ADDRESS with SMTP id xl7mr4158572pbc.167.1360849736470;
        Thu, 14 Feb 2013 05:48:56 -0800 (PST)
Return-Path: &lt;register@service.org&gt;
Received: from subdomaine.service.org (vbox17.service.org. [IP_ADDRESS])
        by mx.google.com with ESMTP id k8si8969185pax.IP_ADDRESS.05.48.55;
        Thu, 14 Feb 2013 05:48:56 -0800 (PST)
Received-SPF: pass (google.com: domain of register@service.org designates IP_ADDRESS as permitted sender) client-ip=IP_ADDRESS;
Authentication-Results: mx.google.com;
       spf=pass (google.com: domain of register@service.org designates IP_ADDRESS as permitted sender) smtp.mail=register@service.org
Received: from localhost (localhost.localdomain [IP_ADDRESS])
    by subdomaine.service.org (Postfix) with ESMTP id 94EBC769B5
    for &lt;nom.prenom@gmail.com&gt;; Thu, 14 Feb 2013 13:48:55 +0000 (UTC)
X-Virus-Scanned: by amavisd-new at service.org
Received: from subdomaine.service.org ([IP_ADDRESS])
    by localhost (subdomaine.service.org [IP_ADDRESS]) (amavisd-new, port 10024)
    with ESMTP id FybIuo+abpEQ for &lt;nom.prenom@gmail.com&gt;;
    Thu, 14 Feb 2013 13:48:55 +0000 (UTC)
Received: from register-web.service.org (register-web-back [IP_ADDRESS])
    by subdomaine.service.org (Postfix) with ESMTP id 7A92976993
    for &lt;nom.prenom@gmail.com&gt;; Thu, 14 Feb 2013 13:48:55 +0000 (UTC)
Received: by register-web.service.org (Postfix, from userid 502)
    id 7695FEE8F3; Thu, 14 Feb 2013 13:48:54 +0000 (UTC)
From: register@service.org
To: nom.prenom@gmail.com</pre>
<p>Donc l&#8217;email a bien été envoyé à l&#8217;adresse AVEC le point.</p>
<p>WTF ?</p>
<p>&nbsp;</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=4556&amp;md5=5106b6114e2cf355a0343cbe73ea46aa" 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=4529
title: Quelques commandes Git qu’elles sont bien
uri: Quelques-commandes-Git-qu-elles-sont-biens
url: http://sametmax.com/quelques-commandes-git-quelles-sont-biens/
content:
<p>Parce que quand y a plus de git, y en a encore.</p>
<h2>Ajout interactif</h2>
<p>Vous avez fait plusieurs modifications sur un fichier, mais vous voulez seulement en commiter une partie.</p>
<p><code>git add -p</code></p>
<h2>Récupérer un fichier d&#8217;une autre branche</h2>
<p>Vous avez une modif sur une autre branche, et vous voulez juste celle là.</p>
<p><code>git checkout-- checmin/vers/fichier</code></p>
<h2>Ne jamais commiter les changements d&#8217;un fichier</h2>
<p>C&#8217;est un peu un.gitignore, mais pour un fichier qui est déjà dans le repo. Cette commande demande à git d&#8217;ignorer toute modification d&#8217;un fichier, même si il est déjà suivi.<br />
<code><br />
git update-index --assume-unchanged fichier</code></p>
<h2>Créer une branche sans historique</h2>
<p>Parceque fois, vous avez juste besoin de repartir à zéro, mais garder le même repo.</p>
<p><code>git checkout --orphan</code></p>
<h2>Vérifier ce qu&#8217;on va commiter</h2>
<p>Vous avez fait plein de add, mais vous voulez voir le diff de ce qui va être commité.</p>
<p><code>git diff --staged</code></p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=4529&amp;md5=37e0982348f4f35c82e10b9e7aabcc35" 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=4572
title: Union d’un ensemble d’intervalles
uri: Union-d-un-ensemble-d-intervalles
url: http://sametmax.com/union-dun-ensemble-dintervalles/
content:
<blockquote><p>Ceci est un post invité de <a href="http://recher.wordpress.com" target="_blank">Réchèr</a> posté sous licence <a href="http://creativecommons.org/licenses/by/3.0/" target="_blank">creative common 3.0 unported.</a></p></blockquote>
<p>Kikoo amis matheux ou pas. Aujourd&#8217;hui, on va se faire un petit algo de derrière les fagots. Vous n&#8217;en aurez peut-être jamais besoin dans le monde réel, mais, qui a dit qu&#8217;on allait se contenter uniquement de ce dont on a besoin ? De plus, je présenterais, à la fin, une astuce générique d&#8217;algorithmiciens.</p>
<h2>Pré-requis</h2>
<ul>
<li>Connaître très vaguement la notion des O(n²), O(truc), &#8230; qui définissent le temps d&#8217;exécution d&#8217;un algorithme en fonction de la quantité de données à traiter. (Si ça vous parle pas c&#8217;est pas grave).
</li>
<li>Savoir que le pluriel d&#8217;intervalle n&#8217;est pas &#8220;intervaux&#8221;.</li>
</ul>
<p>Petite précision : pour définir des intervalles d&#8217;entiers, j&#8217;emploierais la convention pythonienne : le dernier élément n&#8217;est pas inclus. C&#8217;est à dire que [2, 7] correspond à 5 éléments : 2, 3, 4, 5, 6. </p>
<h2>Énoncé</h2>
<p>Soit une liste de couple de nombres, représentant des intervalles. Ils sont tout en vrac, y&#8217;en a qui se chevauchent, d&#8217;autres qui s&#8217;inclusent, etc. Bref, l&#8217;ensemble fait penser à une partouse animale multi-espèces. </p>
<p>exemple : [ [2, 7], [3, 7], [1, 5], [9, 10], [8, 9] ]<br />
<a href="media/f11f868a.intervalle-1.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/intervalle-1.png"><img src="media/f11f868a.intervalle-1.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/intervalle-1.png" alt="Les crochets d&#039;intervalles ont une tronche bizarre. C&#039;est pour bien montrer que le dernier élément n&#039;est pas inclus." title="Les crochets d&#039;intervalles ont une tronche bizarre. C&#039;est pour bien montrer que le dernier élément n&#039;est pas inclus." width="455" height="255" class="alignnone size-full wp-image-4575" /></a></p>
<p>Vous voulez une méthode pour rassembler tout ça, et obtenir une liste d&#8217;intervalles, triée, sans chevauchement, correspondant à la fusion de tous les intervalles de départ. En maths, on appelle cette opération une union. En partouse animale multi-espèces, on appelle aussi ça une union, mais ce n&#8217;est pas le sujet.</p>
<p>résultat souhaité : [ [1, 7], [8, 10] ]<br />
<a href="media/4eebe746.intervalle-2.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/intervalle-2.png"><img src="media/4eebe746.intervalle-2.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/intervalle-2.png" alt="Toujours cet éternel problème de nombre de poteaux versus nombre d&#039;intervalles. Je suis sûr que si on était dans un univers non-eucliden on serait pas emmerdé avec ce genre de détail à la con." title="Toujours cet éternel problème de nombre de poteaux versus nombre d&#039;intervalles. Je suis sûr que si on était dans un univers non-eucliden on serait pas emmerdé avec ce genre de détail à la con." width="449" height="160" class="alignnone size-full wp-image-4577" /></a></p>
<h2>Solutions auxquelles on pense en premier</h2>
<h3>Le bourrin pas-à-pas</h3>
<p>On récupère le début d&#8217;intervalle le plus à gauche, et la fin la plus à droite. On boucle entre ces deux valeurs. À chaque itération, on effectue le traitement suivant : </p>
<ul>
<li>Vérifier si la valeur courante est dans au moins un intervalle. </li>
<li>Si oui, et que juste avant on était dans aucun intervalle, alors on marque cette valeur comme un début d&#8217;intervalle.
</li>
<li>Si non, et que juste avant on était dans au moins un intervalle, alors on marque cette valeur comme une fin d&#8217;intervalle.</li>
</ul>
<h4>Désavantages</h4>
<p>Si, au départ, on a deux intervalles très éloignés, par exemple [0, 2] et [1000000, 1000002] on va faire une boucle de 1000002 itérations. Pour traiter 2 intervalles, c&#8217;est un peu lourd.</p>
<p>Ça ne marche qu&#8217;avec des entiers. Si on a des intervalles de réels, on itère comment ? En avançant de 0.0000000001 en 0.0000000001 ? Même problème avec des intervalles de date-heure.</p>
<h3>Le bourrin cumulatif</h3>
<p>On crée une liste géante de booléens, tous à False, qui s&#8217;étend du premier début d&#8217;intervalle à la fin du dernier. Chaque booléen indiquera si le nombre correspondant se trouve dans au moins un intervalle. On met les bons booléens à True en parcourant les intervalles de la liste initiale. Puis, on construit la liste finale d&#8217;intervalles, en se basant sur les booléens.</p>
<h4>Désavantages</h4>
<p>Si on a en entrée un million de fois l&#8217;intervalle [10, 210], on va mettre un million de fois à True la même suite de 200 booléens. 200 millions d&#8217;opérations pour ressortir un unique intervalle [10, 210].</p>
<p>Même problème que précédemment. Ça ne marche qu&#8217;avec des nombres entiers.</p>
<p><a href="media/a3c7c4a7.881911164.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/881911164.jpg"><img src="media/a3c7c4a7.881911164.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/881911164.jpg" alt="Du bourrin et du cumulatif : serait-ce l&#039;occasion d&#039;invoquer une grand-mère à moustache ?" title="Du bourrin et du cumulatif : serait-ce l&#039;occasion d&#039;invoquer une grand-mère à moustache ?" width="210" height="300" class="alignnone size-full wp-image-4579" /></a></p>
<h3>L&#8217;enfileur de perles</h3>
<p>On a d&#8217;un côté la liste finale des intervalles (initialisée à vide), et de l&#8217;autre, la liste initiale, en bordel. On passe les intervalles d&#8217;une liste à l&#8217;autre, un par un, en testant les cas suivants :</p>
<ul>
<li>Le début et la fin de l&#8217;intervalle en cours n&#8217;est dans aucun intervalle final -> ça fait un nouvel intervalle final.
</li>
<li>Le début est dans un intervalle final, mais pas la fin -> ça rallonge l&#8217;interval final existant.</li>
<li>La fin est dans un intervalle final, mais pas le début -> ça rallonge l&#8217;intervalle final existant, mais par l&#8217;autre côté.</li>
<li>La fin et le début sont dans le même intervalle final -> l&#8217;intervalle en cours ne sert à rien.</li>
<li>La fin et le début sont dans deux intervalles finaux différents. -> il faut fusionner les deux intervalles finaux.</li>
</ul>
<p>Et en plus de tout ça, il faut également tester s&#8217;il n&#8217;y a pas des intervalles finaux entièrement inclus dans l&#8217;intervalle en cours. Auquel cas, ils ne servent plus à rien, et doivent être enlevé de la liste.</p>
<h4>Désavantages</h4>
<p>Une bonne grosse prise de tête à coder tous les cas possibles, sans rien oublier, sans bug. </p>
<p>Le fait de chercher si un nombre se trouve dans une liste d&#8217;intervalles, fut-elle triée, est une opération qui prend un certain temps. Ça peut s&#8217;optimiser avec de la dichotomie ou des trucs du genre, mais quand même. </p>
<p>Par contre, cette algo marche avec des nombres réels et des date-heure. Youpi.</p>
<p><a href="media/7c67aa15.JB333.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/JB333.jpg"><img src="media/7c67aa15.JB333.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/JB333.jpg" alt="Je pige même pas comment ce jouet est censé fonctionner. Faut mettre les perles dans le trou de la machine ? Comment le trou de perle se met en face du fil ? Est-ce que ça serait pas encore plus galère qu&#039;à la main ?" title="Je pige même pas comment ce jouet est censé fonctionner. Faut mettre les perles dans le trou de la machine ? Comment le trou de perle se met en face du fil ? Est-ce que ça serait pas encore plus galère qu&#039;à la main ?" width="359" height="275" class="alignnone size-full wp-image-4581" /></a></p>
<h2>Et si on arrêtait les conneries ?</h2>
<p>Dans ces premières solutions, on considère les intervalles comme des objets immuables. Il faut en traiter un entièrement avant de passer au suivant. Mais on peut aussi les voir comme deux événements distincts (un début et une fin), que l&#8217;on peut dissocier totalement, et traiter dans leur ordre d&#8217;arrivée. On ne sera plus capable de retrouver quel début correspond à quelle fin, mais ça on s&#8217;en fout, y&#8217;a rien qui ressemble plus à un intervalle qu&#8217;un autre intervalle.</p>
<p>Imaginez un petit bonhomme (ou une petite bonne femme, respectons la parité). Au départ, il est au niveau du sol. Il avance vers la droite. Quand il rencontre un début d&#8217;intervalle, il monte sur un mur d&#8217;un étage. Quand il rencontre une fin, il descend d&#8217;un étage. Il peut être sur plusieurs étages superposés. Au fur et à mesure qu&#8217;il se déplace, on note les endroits où il se retrouve sur le sol. Ces endroits correspondent à des zones sans aucun intervalle. </p>
<p><a href="media/b828d0f1.jill-of-the-jungle_3crop.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/jill-of-the-jungle_3crop.png"><img src="media/b828d0f1.jill-of-the-jungle_3crop.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/jill-of-the-jungle_3crop.png" alt="Je vous laisse retrouver de quel jeu vidéo est tiré ce screenshot. Je l&#039;avais beaucoup aimé. Je trouvais l&#039;univers très onirique, et très &quot;compte de fée mais pas cucul, parce que y&#039;a quand même dedans des aventures qui poutrent de la rascasse particulaire avec un chandelier dans la véranda.&quot;" title="Je vous laisse retrouver de quel jeu vidéo est tiré ce screenshot. Je l&#039;avais beaucoup aimé. Je trouvais l&#039;univers très onirique, et très &quot;compte de fée mais pas cucul, parce que y&#039;a quand même dedans des aventures qui poutrent de la rascasse particulaire avec un chandelier dans la véranda.&quot;" width="258" height="138" class="alignnone size-full wp-image-4582" /></a></p>
<p><a href="media/584ce9c5.gfs_29955_2_14_mid.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/gfs_29955_2_14_mid.jpg"><img src="media/584ce9c5.gfs_29955_2_14_mid.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/gfs_29955_2_14_mid.jpg" alt="Mes parents n&#039;arrêtaient pas de me dire que mes jeux se ressemblaient tous. Puis ils m&#039;emmenaient visiter des églises et des châteaux qui se ressemblaient tous. Bizarre..." title="Mes parents n&#039;arrêtaient pas de me dire que mes jeux se ressemblaient tous. Puis ils m&#039;emmenaient visiter des églises et des châteaux qui se ressemblaient tous. Bizarre..." width="270" height="169" class="alignnone size-full wp-image-4583" /></a></p>
<h3>Le code</h3>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> tri_bonhomme_sur_un_mur<span style="color: black;">&#40;</span>list_intervalle_en_bordel<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; Effectue une union de tous les intervalles indiqués en paramètre.
&nbsp;
    Données d'entrée : une liste de liste de deux éléments, représentant
    des intervalles.
     - Le type des éléments n'est pas imposé. Il faut juste qu'on puisse 
       les ordonner et les trier. 
     - Dans chaque liste de deux éléments, le premier doit être plus 
       petit que le second. 
    La fonction ne vérifie pas ces contraintes. Si elles ne sont pas 
    respectées, le comportement est indéterminé. Ça peut planter, 
    ça peut renvoyer un résultat faux sans avertissement, etc.
&nbsp;
    Sortie : une liste de liste de deux éléments, unionnisée et triée
    comme il faut.
    &quot;&quot;&quot;</span>
    <span style="color: #808080; font-style: italic;"># On extrait tous les débuts d'intervalles, et toutes les fins.</span>
    list_debut = <span style="color: black;">&#91;</span> interv<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> <span style="color: #ff7700;font-weight:bold;">for</span> interv <span style="color: #ff7700;font-weight:bold;">in</span> list_intervalle_en_bordel <span style="color: black;">&#93;</span>
    list_fin = <span style="color: black;">&#91;</span> interv<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span> <span style="color: #ff7700;font-weight:bold;">for</span> interv <span style="color: #ff7700;font-weight:bold;">in</span> list_intervalle_en_bordel <span style="color: black;">&#93;</span>
    <span style="color: #808080; font-style: italic;"># On les trie, pour pouvoir les traiter de gauche à droite.</span>
    list_debut.<span style="color: black;">sort</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    list_fin.<span style="color: black;">sort</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># Cette liste contiendra les intervalles unionnisés et triés.</span>
    list_intervalle_final = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
    <span style="color: #808080; font-style: italic;"># indique le nombre d'invervalle superposés dans lesquels on se trouve</span>
    <span style="color: #808080; font-style: italic;"># actuellement. (C'est à dire : le nombre d'étages sur lequel</span>
    <span style="color: #808080; font-style: italic;"># marche le bonhomme).</span>
    nb_superposition = <span style="color: #ff4500;">0</span>
    <span style="color: #808080; font-style: italic;"># Lorsqu'on est dans un ou plusieurs intervalles superposés, on doit</span>
    <span style="color: #808080; font-style: italic;"># se souvenir à quelle position on est entré dans le premier.</span>
    <span style="color: #808080; font-style: italic;"># Cela permettra de créer l'intervalle final, lorsqu'on sera </span>
    <span style="color: #808080; font-style: italic;"># complètement sorti de la superposition en cours.</span>
    debut_intervalle_courant = <span style="color: #ff4500;">0</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># C'est parti ! Le petit bonhomme avance. On lui fait traiter les</span>
    <span style="color: #808080; font-style: italic;"># événements d'entrée et de sortie d'intervalle au fur et à mesure </span>
    <span style="color: #808080; font-style: italic;"># qu'ils arrivent.</span>
    <span style="color: #ff7700;font-weight:bold;">while</span> list_debut:
        <span style="color: #808080; font-style: italic;"># Le premier élément de list_debut, c'est le premier début </span>
        <span style="color: #808080; font-style: italic;"># d'intervalle qu'on rencontrera. Le premier élément de list_fin,</span>
        <span style="color: #808080; font-style: italic;"># c'est la première fin d'intervalle qu'on rencontrera. On </span>
        <span style="color: #808080; font-style: italic;"># détermine, parmi ces deux événements, lequel on rencontrera en </span>
        <span style="color: #808080; font-style: italic;"># tout premier.</span>
        <span style="color: #808080; font-style: italic;">#</span>
        <span style="color: #808080; font-style: italic;"># La fonction cmp renvoie -1, 0, ou 1, selon la comparaison </span>
        <span style="color: #808080; font-style: italic;"># effectuée entre les deux valeurs passées en paramètre.</span>
        <span style="color: #808080; font-style: italic;"># Faire un petit help(cmp) pour connaître les détails.</span>
        ordre_debut_fin = <span style="color: #008000;">cmp</span><span style="color: black;">&#40;</span>list_debut<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>, list_fin<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: #ff7700;font-weight:bold;">if</span> ordre_debut_fin == -<span style="color: #ff4500;">1</span>:
            <span style="color: #808080; font-style: italic;"># L'événement rencontré est un début d'intervalle.</span>
            <span style="color: #808080; font-style: italic;"># On enlève l'événement de la liste, puisqu'on va le traiter,</span>
            <span style="color: #808080; font-style: italic;"># là, tout de suite.</span>
            pos_debut = list_debut.<span style="color: black;">pop</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> nb_superposition == <span style="color: #ff4500;">0</span>:
                <span style="color: #808080; font-style: italic;"># On était dans aucun intervalle, et on vient d'en </span>
                <span style="color: #808080; font-style: italic;"># rencontrer un. Dans la liste finale d'intervalles, </span>
                <span style="color: #808080; font-style: italic;"># ça va donc compter comme un début. On retient </span>
                <span style="color: #808080; font-style: italic;"># cette info.</span>
                debut_intervalle_courant = pos_debut
            <span style="color: #808080; font-style: italic;"># Dans tous les cas, on ajoute une superposition d'intervalle</span>
            <span style="color: #808080; font-style: italic;"># (le bonhomme monte d'un étage).</span>
            nb_superposition += <span style="color: #ff4500;">1</span>
        <span style="color: #ff7700;font-weight:bold;">elif</span> ordre_debut_fin == +<span style="color: #ff4500;">1</span>:
            <span style="color: #808080; font-style: italic;"># L'événement rencontré est une fin d'intervalle.</span>
            <span style="color: #808080; font-style: italic;"># On l'enlève de la liste.</span>
            pos_fin = list_fin.<span style="color: black;">pop</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
            <span style="color: #808080; font-style: italic;"># On enlève une superposition d'intervalle.</span>
            nb_superposition -= <span style="color: #ff4500;">1</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> nb_superposition == <span style="color: #ff4500;">0</span>:
                <span style="color: #808080; font-style: italic;"># Après avoir enlevé la superposition, on se retrouve</span>
                <span style="color: #808080; font-style: italic;"># avec 0 intervalle superposé. </span>
                <span style="color: #808080; font-style: italic;"># (Le bonhomme est redescendu jusqu'au niveau du sol).</span>
                <span style="color: #808080; font-style: italic;"># Il faut donc enregistrer ça comme une fin d'intervalle </span>
                <span style="color: #808080; font-style: italic;"># final. Tant qu'on y est, on crée tout de suite ce nouvel</span>
                <span style="color: #808080; font-style: italic;"># intervalle final et on le met dans la liste.</span>
                nouvel_intervalle = <span style="color: black;">&#40;</span>debut_intervalle_courant, pos_fin<span style="color: black;">&#41;</span>
                list_intervalle_final.<span style="color: black;">append</span><span style="color: black;">&#40;</span>nouvel_intervalle<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            <span style="color: #808080; font-style: italic;"># On rencontre à la fois un début et une fin d'intervalle.</span>
            <span style="color: #808080; font-style: italic;"># Rien de spécial à faire. Faut juste virer les 2 événements </span>
            <span style="color: #808080; font-style: italic;"># traités de leur liste respectives.</span>
            list_debut.<span style="color: black;">pop</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
            list_fin.<span style="color: black;">pop</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Durant toute cette boucle, la variable nb_superposition augmente</span>
        <span style="color: #808080; font-style: italic;"># et diminue. Mais elle n'est jamais censée devenir négative.</span>
        <span style="color: #808080; font-style: italic;"># Si ça arrive, c'est que les données d'entrées sont mal foutues.</span>
        <span style="color: #808080; font-style: italic;"># On entre dans un cas d'indétermination. </span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Arrivé à la fin de la boucle, il peut rester, ou pas des éléments</span>
    <span style="color: #808080; font-style: italic;"># dans list_fin. Ce qui est sûr, c'est que list_debut se vide</span>
    <span style="color: #808080; font-style: italic;"># avant list_fin. Si ce n'est pas le cas, c'est encore un cas</span>
    <span style="color: #808080; font-style: italic;"># d'indétermination.</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> list_fin:
        <span style="color: #808080; font-style: italic;"># On a passé tous les débuts d'intervalle, mais il reste des</span>
        <span style="color: #808080; font-style: italic;"># fins. Ça veut dire qu'on est encore dans un ou plusieurs</span>
        <span style="color: #808080; font-style: italic;"># intervalles. On devrait normalement avoir :</span>
        <span style="color: #808080; font-style: italic;"># len(list_fin) == nb_superposition. Si c'est pas le cas, c'est</span>
        <span style="color: #808080; font-style: italic;"># un cas d'indétermination.</span>
        <span style="color: #808080; font-style: italic;">#</span>
        <span style="color: #808080; font-style: italic;"># On pourrait traiter les événements de fin d'intervalle un par un,</span>
        <span style="color: #808080; font-style: italic;"># et diminuer progressivement nb_superposition. Mais on s'en fout,</span>
        <span style="color: #808080; font-style: italic;"># c'est pas nécessaire. On prend juste la fin d'intervalle qui </span>
        <span style="color: #808080; font-style: italic;"># supprimera la dernière superposition (c'est à dire la dernière</span>
        <span style="color: #808080; font-style: italic;"># fin d'intervalle), et on construit un dernier intervalle final</span>
        <span style="color: #808080; font-style: italic;"># avec ça.</span>
        pos_fin = list_fin<span style="color: black;">&#91;</span>-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
        nouvel_intervalle = <span style="color: black;">&#40;</span>debut_intervalle_courant, pos_fin<span style="color: black;">&#41;</span>
        list_intervalle_final.<span style="color: black;">append</span><span style="color: black;">&#40;</span>nouvel_intervalle<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> list_intervalle_final</pre></div></div>

<h3>Les avantages (parce que y&#8217;a aucun désavantages)</h3>
<p>Ça marche avec des réels, des dates, et de manière générale, <a href="http://sametmax.com/ordonner-en-python/" target="_blank">tout ce qu&#8217;on peut trier</a>.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span>tri_bonhomme_sur_un_mur<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span> <span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">7</span><span style="color: black;">&#93;</span>, <span style="color: black;">&#91;</span><span style="color: #ff4500;">3</span>, <span style="color: #ff4500;">7</span><span style="color: black;">&#93;</span>, <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">5</span><span style="color: black;">&#93;</span>, <span style="color: black;">&#91;</span><span style="color: #ff4500;">9</span>, <span style="color: #ff4500;">10</span><span style="color: black;">&#93;</span>, <span style="color: black;">&#91;</span><span style="color: #ff4500;">8</span>, <span style="color: #ff4500;">9</span><span style="color: black;">&#93;</span> <span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">7</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#40;</span><span style="color: #ff4500;">8</span>, <span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Testez pas ça chez vous ! Ça prend trois plombes ! Mettez juste 1000.</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span>tri_bonhomme_sur_un_mur<span style="color: black;">&#40;</span> <span style="color: black;">&#91;</span> <span style="color: black;">&#91;</span><span style="color: #ff4500;">10</span>, <span style="color: #ff4500;">210</span><span style="color: black;">&#93;</span>, <span style="color: black;">&#93;</span> <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">1000000</span> <span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span>, <span style="color: #ff4500;">210</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Voyons voir ce que ça donne avec des réels </span>
<span style="color: #808080; font-style: italic;"># (dont certains sont négatifs, tant qu'à faire).</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span>tri_bonhomme_sur_un_mur<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span> 
    <span style="color: black;">&#91;</span>-<span style="color: #ff4500;">7.2</span>, -<span style="color: #ff4500;">6.9</span><span style="color: black;">&#93;</span>, <span style="color: black;">&#91;</span>-<span style="color: #ff4500;">8.4</span>, -<span style="color: #ff4500;">5.3</span><span style="color: black;">&#93;</span>, <span style="color: black;">&#91;</span>-<span style="color: #ff4500;">10.5</span>, -<span style="color: #ff4500;">5.25</span><span style="color: black;">&#93;</span>, 
    <span style="color: black;">&#91;</span>-<span style="color: #ff4500;">1.7</span>, <span style="color: #ff4500;">0.01</span><span style="color: black;">&#93;</span>, <span style="color: black;">&#91;</span><span style="color: #ff4500;">0.0</span>, <span style="color: #ff4500;">4.0</span><span style="color: black;">&#93;</span>, 
    <span style="color: black;">&#91;</span><span style="color: #ff4500;">12.125</span>, <span style="color: #ff4500;">13.9</span>, <span style="color: black;">&#93;</span>, <span style="color: black;">&#91;</span><span style="color: #ff4500;">13.9</span>, <span style="color: #ff4500;">15.0</span><span style="color: black;">&#93;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: black;">&#40;</span>-<span style="color: #ff4500;">10.5</span>, -<span style="color: #ff4500;">5.25</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#40;</span>-<span style="color: #ff4500;">1.7</span>, <span style="color: #ff4500;">4.0</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#40;</span><span style="color: #ff4500;">12.125</span>, <span style="color: #ff4500;">15.0</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>    
&nbsp;
<span style="color: #808080; font-style: italic;"># et avec des dates</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span>from <span style="color: #dc143c;">datetime</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">datetime</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span>tri_bonhomme_sur_un_mur<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>
    <span style="color: black;">&#91;</span><span style="color: #dc143c;">datetime</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2012</span>, <span style="color: #ff4500;">12</span>, <span style="color: #ff4500;">21</span>, <span style="color: #ff4500;">16</span>, <span style="color: #ff4500;">54</span><span style="color: black;">&#41;</span>, 
     <span style="color: #dc143c;">datetime</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2013</span>, 02, <span style="color: #ff4500;">16</span>, <span style="color: #ff4500;">12</span>, <span style="color: #ff4500;">59</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>, 
    <span style="color: black;">&#91;</span><span style="color: #dc143c;">datetime</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2013</span>, 02, <span style="color: #ff4500;">14</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>, 
     <span style="color: #dc143c;">datetime</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2069</span>, 01, 01, <span style="color: #ff4500;">13</span>, <span style="color: #ff4500;">37</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#93;</span> <span style="color: black;">&#93;</span> <span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">datetime</span>.<span style="color: #dc143c;">datetime</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2012</span>, <span style="color: #ff4500;">12</span>, <span style="color: #ff4500;">21</span>, <span style="color: #ff4500;">16</span>, <span style="color: #ff4500;">54</span><span style="color: black;">&#41;</span>,
  <span style="color: #dc143c;">datetime</span>.<span style="color: #dc143c;">datetime</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2069</span>, <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">13</span>, <span style="color: #ff4500;">37</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span></pre></div></div>

<p>En ajoutant à peine 2-3 lignes de code à la fonction, on peut récupérer le nombre maximal d&#8217;intervalles superposés.</p>
<p>En re-ajoutant quelques autres lignes, on peut récupérer les zones dans lesquelles ce maximum est atteint. Ce qui pourrait servir pour effectuer l&#8217;opération mathématique d&#8217;intersection. (Je vous laisse chercher ça par vous mêmes).</p>
<p>L&#8217;algorithme est principalement constitué d&#8217;une bi-boucle, c&#8217;est à dire une boucle unique, qui avance dans deux listes différentes (je viens d&#8217;inventer ce terme, ne m&#8217;embêtez pas). C&#8217;est encore plus simple que deux boucles imbriquées. Le nombre d&#8217;itérations à effectuer est égal au nombre d&#8217;intervalle multiplié par deux, c&#8217;est tout. Dans tous les cas limites présentés ci-dessus, ça fait une solution acceptable, demandant un temps d&#8217;exécution peu pharaonique.</p>
<p><a href="media/c564e643.resize.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/resize.jpg"><img src="media/c564e643.resize.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/resize.jpg" alt="Exemple de deux bi-boucles imbriquées au niveau de la vis. Cette image vous a été offerte par les Scissor Sisters." title="Exemple de deux bi-boucles imbriquées au niveau de la vis. Cette image vous a été offerte par les Scissor Sisters." width="370" height="370" class="alignnone size-full wp-image-4587" /></a></p>
<h2>Mais ou est passé la complexité ?</h2>
<p>Les premières solutions avaient l&#8217;air de demander énormément de temps d&#8217;exécution, surtout avec beaucoup d&#8217;intervalles en entrée. Ça ne semble pas être le cas pour la solution du &#8220;bonhomme sur un mur&#8221;. Pourtant, la complexité d&#8217;une tâche, ça ne disparaît pas comme par magie. Y&#8217;aurait-il une entourloupe quelque part ?</p>
<p>Il y en a une. Ce sont les deux opérations de tri effectuées au début de la fonction. Un tri, ce n&#8217;est pas anodin, et son temps d&#8217;exécution peut augmenter très beaucoup et très vite. La complexité n&#8217;a pas disparue, on n&#8217;a fait que la déplacer vers des tris. Alors finalement, ma solution n&#8217;est pas si bien que ça ?</p>
<p>Eh bien si. Parce que le tri, même s&#8217;il reste coûteux en temps et en ressource, est un problème archi-connu, archi-réglé, et archi-optimisé. Le python, comme beaucoup d&#8217;autres langages, profite pleinement du travail réalisé par des centaines de matheux algorithmologues, qui se sont masturbés l&#8217;esprit sur des centaines de méthodes de tri différentes.</p>
<div id="attachment_4589" class="wp-caption alignnone" style="width: 510px"><a href="media/256cffb1.P1060165-resize1.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/P1060165-resize1.jpg"><img src="media/256cffb1.P1060165-resize1.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/P1060165-resize1.jpg" alt="Y&#039;a des fois, on sait que l&#039;image dont on a besoin ne sera pas trouvable sur l&#039;internet. Alors on est obligé de la créer soi-même. (Mais je me suis fait aider)." title="Y&#039;a des fois, on sait que l&#039;image dont on a besoin ne sera pas trouvable sur l&#039;internet. Alors on est obligé de la créer soi-même. (Mais je me suis fait aider)." width="500" height="375" class="size-full wp-image-4589" /></a><p class="wp-caption-text">Photo prise dans le bureau d&#039;un chercheur en algorithmologie.</p></div>
<p>C&#8217;est ça l&#8217;astuce générique dont je vous parlais au début. Face à un nouveau problème, le matheux <del datetime="2013-02-17T02:34:17+00:00">sort son zguègue</del> tente de trouver des équivalents à un ou plusieurs problèmes connus, que lui et ses amis matheux ont déjà réglés. C&#8217;est souvent bien plus simple que de tenter de régler le problème directement, en partant de rien. </p>
<p><em>&#8220;Un nain éjacule bien plus loin lorsqu&#8217;il est perché sur les épaules d&#8217;un géant.&#8221;</em> Et pour respecter la parité, j&#8217;ajouterais qu&#8217;une naine femme-fontainise bien plus loin lorqu&#8217;elle est perchée sur les épaules d&#8217;une géante.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=4572&amp;md5=480b1322728e3af4fe96d5ab208a3186" 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=4562
title: Pourquoi il faut spécifier l’exception qu’on gère
uri: Pourquoi-il-faut-spécifier-l-exception-qu-on-gère
url: http://sametmax.com/pourquoi-il-faut-specifier-lexception-quon-gere/
content:
<p>On utilise beaucoup la gestion des exceptions en Python, mais le langage permet de faire des trucs apocryphes comme:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">try</span>:
    <span style="color: #808080; font-style: italic;"># un code qui va chier des bulles</span>
<span style="color: #ff7700;font-weight:bold;">except</span>: <span style="color: #808080; font-style: italic;"># je les attrappe tous, comme les pokemons</span>
    <span style="color: #ff7700;font-weight:bold;">pass</span></pre></div></div>

<p>Ceci n&#8217;est ni plus ni moins que l&#8217;équivalent de <code>@</code> pour silent les erreurs en PHP.</p>
<p>C&#8217;est caca.</p>
<p>Et la raison pour laquelle j&#8217;oppose une aversion si mesurée mais néanmoins portée par des arguments forts, c&#8217;est que c&#8217;est le grand kiff de Max d&#8217;en mettre partout, et que la semaine dernière ça lui a valu un debuggage en prod.</p>
<p>Depuis le dernier déploiement, les logs d&#8217;un des workers d&#8217;un serveur d&#8217;encoding affichaient en boucle :</p>
<blockquote><p>&#8220;Error accessing Database, check your connexion&#8221;</p></blockquote>
<p>Du coup Max a cherché d&#8217;ou venait ce problème de database par les cas usuels : port ? Permission ? Network ? Mise à jour de lib de l&#8217;ORM ? Daemonisation ?</p>
<p>Le snippet qui provoquait ce message était (en simplifié) :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">try</span>:
    new_model = Model.<span style="color: black;">objects</span>.<span style="color: black;">create</span><span style="color: black;">&#40;</span>params<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">except</span>:
    <span style="color: #008000;">self</span>.<span style="color: black;">logger</span>.<span style="color: black;">error</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Error accessing Database, check your connexion&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># + trucs pour gérer le bouzin</span></pre></div></div>

<p>La raison du <code>try</code> / <code>except</code> est que parfois, sur ce serveur, et seulement sur ce serveur, la connection avec la DB distante droppait. Bug aléatoire ou de config ? Parfois il est plus simple de ne pas résoudre le problème et laisser le truc foirer de temps en temps, et juste garder un recovery. Ça évite un spécial case pour un seul serveur, et ça évite de migrer le serveur.</p>
<p>Sauf que ce <code>try</code> / <code>except</code> était générique, et il attrapait tout, même les rhumes. </p>
<p>Je lui ai demandé de virer le <code>try</code> / <code>except</code> pour voir ce qui se passait vraiment, et&#8230;</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">raise</span> MissingDependency<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;The 'solr' backend requires the installation of 'pysolr'. Please refer to the documentation.&quot;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Le truc qui n&#8217;a RIEN à voir avec la base de données. Solr est notre moteur de recherche, et c&#8217;est juste qu&#8217;à la création d&#8217;un objet de modèle Django, un signal est propagé pour mettre à jour l&#8217;index de Solr. Le nouveau déploiement était incomplet : il manquait une lib. La lib était importée à ce moment là, ça levait une exception, qui était attrapée bêtement par le <code>try</code>/<code>except</code> générique.</p>
<p>Bref, le code a été remplacé par</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">try</span>:
    new_model = Model.<span style="color: black;">objects</span>.<span style="color: black;">create</span><span style="color: black;">&#40;</span>params<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">except</span> DataBaseError:
    <span style="color: #008000;">self</span>.<span style="color: black;">logger</span>.<span style="color: black;">error</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Error accessing Database, check your connexion&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># + trucs pour gérer le bouzin</span></pre></div></div>

<p>Si on l&#8217;avait eu depuis le début, l&#8217;erreur aurait été apparente tout de suite et rapidement corrigée.</p>
<p>Ne faites JAMAIS de <code>try</code>/<code>except</code> sans préciser l&#8217;exception que vous allez gérer. La seule raison pour laquelle cette feature existe, c&#8217;est qu&#8217;elle est pratique à utiliser dans un shell. En fait, même <code>DataBaseError</code> est trop générique comme Exception si vous voulez vraiment un controle fin.</p>
<p>Notez également qu&#8217;un <code>except: pass</code> est rarement une bonne idée. Au moins prenez le temps de logger ce qui se passe dans la clause <code>except</code>. Un bon log, c&#8217;est le début du bonheur.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=4562&amp;md5=c0408d44a8ce24c5b0e338660c03bb92" 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=4623
title: Tout ce que vous vouliez savoir sur les URLs Web, sans jamais oser le demander
uri: Tout-ce-que-vous-vouliez-savoir-sur-les-URLs-Web-sans-jamais-oser-le
url: http://sametmax.com/tout-ce-que-vous-vouliez-savoir-sur-les-urls-web-sans-jamais-oser-le-demander/
content:
<p>Tout ce que vous vouliez savoir sur les URLs Web, sans jamais oser le demander</p>
<p>Tuto plus long que prévu, donc un peu de zizik:</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="560" height="315" src="http://www.youtube.com/embed/pFxLm3UEjxY" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<p>De plus en plus de gens se servent des URLs, et de moins en moins savent ce qu&#8217;elles veulent dire. Cela inclut des développeurs.</p>
<p>Avec les sites en Ajax et les navigateurs qui cachent la moitié des adresses, ça va pas s&#8217;arranger.</p>
<h2>Principe de base du fonctionnement d&#8217;une URL</h2>
<p>URL veut dire <a href="https://en.wikipedia.org/wiki/Url">Uniform Ressource Locator</a>, c&#8217;est à dire qu&#8217;il s&#8217;agit d&#8217;une manière de localiser quelque chose sur un réseau. Normalement, à une URL correspond une ressource, c&#8217;est à dire que si vous utilisez la même URL deux fois, vous devez accéder deux fois à la même information.</p>
<p>Bref, en gros une URL est une adresse unique, avec un format standardisé.</p>
<p>L&#8217;URL la plus simple qu&#8217;on puisse rencontrer est celle-ci :</p>
<p><code>http://monsite.com/</code></p>
<p>Elle contient quatre parties :</p>
<div id="attachment_4626" class="wp-caption aligncenter" style="width: 512px"><a href="media/68d5ce27.quatres_parties.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/quatres_parties.png"><img class=" wp-image-4626   " title="Ce ne sont pas les termes officiels, je vulgarise mon bon." src="media/68d5ce27.quatres_parties.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/quatres_parties.png" alt="Découpage d'une URI" width="502" height="169" /></a><p class="wp-caption-text">Ce ne sont pas les termes officiels, je vulgarise mon bon.</p></div>
<h3>Le procotole</h3>
<p>Il indique sur quel type de réseau et dans quel langage les informations seront. Il n&#8217;y a pas moyen de &#8220;deviner&#8221; ce que ça sera. Il faut savoir à quel nom de protocole correspond quoi. Le plus connu est le protocole HTTP, c&#8217;est celui que nous utilisons pour transmettre des pages Web non sécurisées. Mais il en existe bien d&#8217;autres : ftp, files, irc&#8230; Si on n&#8217;a pas le bon protocole, on ne peut pas lire l&#8217;information.</p>
<p>Aujourd&#8217;hui les logiciels (comme les navigateurs Web) masquent souvent le protocole, car on utilise souvent les mêmes : ftp pour un client FTP, http / https pour une navigateur, git pour un client git, etc.</p>
<p>Néanmoins sur un logiciel qui gère plusieurs protocoles (encore une fois comme un navigateur Web), il lui faut absolument connaitre le protocole, sinon il ne saura pas quoi faire de l&#8217;URL. Une URL avec le protocole FTP ne se traite pas comme une URL avec le protocole HTTP. Le fait que le logiciel masque le protocole ne veut donc pas dire qu&#8217;il a disparu, jusque qu&#8217;il est caché à l&#8217;utilisateur pour les cas les plus courants. Mais il est toujours là, il est indispensable.</p>
<h3>Le contexte</h3>
<p>Pour lire une URL, on a besoin d&#8217;un point de départ. L&#8217;URL est en effet un chemin qui part d&#8217;un point. Le début de l&#8217;URL donne cette information.</p>
<p><code>//</code> signifie qu&#8217;on est dans une URL absolue (nous verrons ce que ça veut dire plus bas), et que le point de départ est le &#8220;lieu&#8221; qu&#8217;on va spécifier juste après.</p>
<h3>Le lieu</h3>
<p>Le &#8220;lieu&#8221; entre guillemet car il n&#8217;y a pas de notion spatiale. C&#8217;est un nom qui permet à la machine de savoir sur quelle partie du réseau se situe la ressource.</p>
<h3>Le chemin</h3>
<p>Après le &#8220;lieu&#8221;, on précise un chemin vers la ressource, c&#8217;est à dire comment, en partant du point de départ, on va aller vers l&#8217;information. Le chemin le plus simple est &#8220;<code>/</code>&#8220;, c&#8217;est à dire &#8220;au tout début&#8221;. Nous verrons les chemins plus en détail.</p>
<h2>Informations implicites</h2>
<p>Souvent on voit (particulièrement sur le Web), des URLs ainsi:</p>
<ul>
<li><code>http://monsite.com</code> (pas de &#8216;<code>/</code>&#8216; à la fin)</li>
<li><code>monsite.com/</code> (pas de protocole)</li>
<li><code>monsite.com</code> (ni protocole ni chemin)</li>
</ul>
<p>Ce ne sont pas des URLs complètes. Mais comme l&#8217;usage le plus courant pour une URL de nos jours est une URL Web, et qu&#8217;un site Web a généralement sa page d’accueil sur &#8220;<code>/</code>&#8220;, et qu&#8217;il est accessible en HTTP, on fait l&#8217;amalgame. Notez bien que ce sont des suppositions (justifiées, la plupart du temps), mais que ça peut tout à fait ne pas marcher.</p>
<h2>Les noms de domaine</h2>
<p>Les URLs pour le Web, qui sont celles qui vont le plus nous intéresser aujourd&#8217;hui, utilisent comme indicateur de &#8220;lieu&#8221; sur le réseau un nom de domaine :</p>
<div id="attachment_4628" class="wp-caption aligncenter" style="width: 512px"><a href="media/21cc5b64.ndd.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/ndd.png"><img src="media/21cc5b64.ndd.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/ndd.png" alt="Un nom de domaine dans une URL" title="Le nom de domaine tel que vous le voyez ici est spécifique à une partie d&#039;internet." width="502" height="118" class="size-full wp-image-4628" /></a><p class="wp-caption-text">Le nom de domaine tel que vous le voyez ici est spécifique à une partie d&#039;internet.</p></div>
<p>Tous les &#8220;lieux&#8221; de toutes les URLs ne sont pas des noms de domaines, mais sur le Web, c&#8217;est ce que l&#8217;on utilise.</p>
<p>Un nom de domaine est en fait un surnom qu&#8217;on a donné à une une adresse IP sur le Web. L&#8217;adresse IP, c&#8217;est un tas de chiffres qui permettent à la machines d&#8217;en retrouver une autre.</p>
<p>Par exemple, en ce moment Google se trouve à l&#8217;adresse : <a href="http://74.125.230.247">http://74.125.230.247</a>. Mais ce n&#8217;est pas très pratique pour les humains. On a donc des noms des domaine, des &#8220;surnoms&#8221;, pour ces adresses IP.</p>
<p>Google.fr est le nom de domaine, qui, en ce moment, est le &#8220;surnom&#8221; de 74.125.230.247. Quand vous demandez à votre navigateur Web d&#8217;aller sur google.fr, il va chercher quelle adresse IP se cache derrière ce nom de domaine (via une autre machine qu&#8217;on appelle un DNS), et il va aller chercher l&#8217;information sur <code>74.125.230.247</code> pour vous.</p>
<p>Quand on a une adresse :</p>
<p><code>http://google.fr/<br />
</code><br />
Cela veut dire :</p>
<ul>
<li>ceci est une URL d&#8217;une ressource accessible avec le protocole HTTP</li>
<li>le point de départ se fait sur le nom de domaine <code>google.fr</code></li>
<li>l&#8217;arrivée se fait au point de départ</li>
</ul>
<p>Mais les noms de domaines, eux-même, sont découpés en plusieurs morceaux :</p>
<div id="attachment_4629" class="wp-caption aligncenter" style="width: 509px"><a href="media/24b2515f.ndd_details.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/ndd_details.png"><img src="media/24b2515f.ndd_details.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/ndd_details.png" alt="Détail du découpage d&#039;un nom de domaine" title="Un nom de domaine se lit de droite à gauche, comme en arabe" width="499" height="142" class="size-full wp-image-4629" /></a><p class="wp-caption-text">Un nom de domaine se lit de droit à gauche, comme en arabe</p></div>
<p>Tout à droite, il y a le TLD (Top Level Domain). C&#8217;est un nom de domaine court, qui représente l&#8217;entité juridique qui gère cette partie du réseau. Généralement c&#8217;est un pays, mais pas forcément (<code>.eu</code>, <code>.com</code>, <code>.net</code>, <code>.org</code>, ne représentent pas des pays). Aujourd&#8217;hui, le TLD ne veut plus dire grand chose et on le choisit surtout soit pour sa sonorité, soit pour sa popularité, soit par les règles qui lui sont liés. En effet, il y a des obligations légales liées à chaque TLD pour la personne qui possède le nom de domaine.</p>
<p>Aucune personne ne possède de TLD, ils sont gérés par des entités juridiques, généralement des États.</p>
<p>Ensuite, plus à gauche, il y a le nom de domaine de deuxième niveau. C&#8217;est généralement ce qu&#8217;on considère être le &#8220;nom&#8221; du site Web. C&#8217;est le Google de Google.fr, le <code>sametmax</code> de <code>sametmax.com</code>, etc.</p>
<p>C&#8217;est aussi le nom que le propriétaire du site loue en payant un loyer régulier pour garder le droit d&#8217;avoir ce &#8220;surnom&#8221; pour sa machine.</p>
<p>Ensuite, on peut rajouter autant de &#8220;sous-domaines&#8221; que l&#8217;on veut :</p>
<p><code>toto.sametmax.com</code><br />
<code>supercalifragilisticexpialidocious.toto.sametmax.com</code></p>
<p>Tout ce qui est le plus à gauche du ndd de 2e niveau est un sous-domaine. Ils sont rajoutés par le propriétaire du site. On peut en faire autant qu&#8217;on veut. Les imbriquer autant qu&#8217;on veut. Les webmasters les utilisent surtout pour une question d&#8217;organisation.</p>
<p>Donc <code>mail.opera.com</code> se lit : site sur le TLD <code>.com</code>, qui s&#8217;appelle &#8220;<code>opera</code>&#8220;, et nous sommes sur la sous-partie &#8220;<code>mail</code>&#8221; du site d&#8217;opera.</p>
<p>Le sous-domaine le plus célèbre est &#8220;<code>www</code>&#8221; comme dans <code>http://www.afpy.org/</code>. &#8220;<code>www</code>&#8221; est juste une vieille convention. C&#8217;est un sous-domaine comme un autre. Ça ne veut rien dire en particulier, juste qu&#8217;on est dans la partie &#8220;<code>www</code>&#8221; du site en question.</p>
<p>On se sert souvent des sous-domaines pour faire des sous-sites ou des services annexes / connexes : les apis, les serveurs de contenu statiques (images, fichiers), les serveurs de streaming, etc.</p>
<p><strong>Attention à une exception notable !</strong></p>
<p>Certaines entités n&#8217;ont pas donné accès au domaine de second niveau à la population. C&#8217;est le cas de l&#8217;Angleterre. Si vous voulez achetez un nom de domaine en <code>.uk</code>, vous ne pouvez pas. Vous pouvez uniquement acheter un sous-domaine du domaine de second niveau &#8220;<code>co</code>&#8220;. Ce qui explique que les sites Web britanniques ont des adresses du genre : <code>http://www.bbc.co.uk/</code>.</p>
<h2>Chemins dans les Urls</h2>
<p>On a vu le point de départ, mais on a pas vu ensuite le chemin. Quand on est sur <code>//nomdedomaine.tld</code>, <code>//</code> signifie qu&#8217;on part de ce site, mais ensuite, on va où pour trouver l&#8217;info ?</p>
<p>C&#8217;est le chemin qui donne cette indication.</p>
<p>Le chemin est une succession de noms et de &#8220;<code>/</code>&#8220;. Un slash veut juste dire &#8220;dans&#8221;.</p>
<p>Si vous avez :</p>
<p><code>sametmax.com/</code></p>
<p>Ça veut dire &#8220;dans sametmax.com&#8221;.</p>
<p>Si vous avez :</p>
<p><code>http://sametmax.com/contactez-nous/</code></p>
<p>Ça veut dire &#8220;dans sametmax.com&#8221; puis &#8220;dans contactez-nous&#8221;.</p>
<p>On peut avoir des chemins très complexes comme :</p>
<p><code>http://cdn.unsite.com/media/images/d540/4da2/af28/758f8336-d540-4da2-af28-dc858d2fa1a6/75x75.jpg</code></p>
<p>Qui veut dire que la ressource &#8220;<code>75x75.jpg</code>&#8221; (qui est ici une image) est dans &#8220;<code>758f8336-d540-4da2-af28-dc858d2fa1a6</code>&#8221; qui est dans &#8220;<code>af28</code>&#8221; qui est dans &#8220;<code>4da2</code>&#8221; qui est dans &#8220;<code>d540</code>&#8221; qui est dans &#8220;<code>images</code>&#8221; qui est dans &#8220;<code>media</code>&#8221; sur le site <code>cdn.unsite.com</code>.</p>
<p>Ce qu&#8217;est réellement &#8220;<code>d540</code>&#8221; ou &#8220;<code>758f8336-d540-4da2-af28-dc858d2fa1a6</code>&#8221; derrière ? Peut être un dossier. Peut être une entrée dans une base de données. Peut être juste une configuration dans un fichier. Vous ne pouvez pas savoir. Tout ce que vous pouvez savoir c&#8217;est que ceci contient cela.</p>
<h2>Les URLs relatives</h2>
<p>Cette partie est plus intéressante pour les développeur de site Web.</p>
<p>Quand vous créez des liens dans votre site, vers d&#8217;autres parties de votre site, vous n&#8217;avez pas besoin d&#8217;écrire toute l&#8217;URL.</p>
<p>Quand on ne part de nul part, on a besoin d&#8217;une URL dite &#8220;absolue&#8221;, c&#8217;est à dire qu&#8217;elle vous donne le point de départ.</p>
<p>C&#8217;est le but de &#8220;//lieu&#8221;.</p>
<p>Mais quand votre client (par exemple le navigateur Web), sait d&#8217;où vous partez, on peut utiliser des URLs relatives, c&#8217;est à dire des URLS qui peuvent omettre des informations.</p>
<p>Par exemple, si l&#8217;utilisateur est DEJA sur <code>http://sametmax.com/</code> et que vous voulez lui faire un lien qui va vers <code>http://sametmax.com/tag/python/</code>, vous pouvez faire ceci:</p>
<p><code>href="//sametmax.com/tag/python/"</code></p>
<p>Vous omettez le protocole. C&#8217;est tout à fait valide. Si le site est en HTTPS, ça restera en HTTPS. Si il est en HTTP, ça restera en HTTP.</p>
<p>Vous pouvez aussi carrément faire ceci :</p>
<p><code>href="/tag/python/"</code></p>
<p>Vous ommettez le nom de domaine.</p>
<p>Une adresse très courante sur le logo d&#8217;un site :</p>
<p><code>href="/"</code></p>
<p>Ça revient à la page d&#8217;acceuil.</p>
<p>Il existe deux autres notations pour les URLS relatives :</p>
<ul>
<li><code>.</code> (le point) : là où ou est</li>
<li><code>..</code> (le double point) : remonter d&#8217;un niveau par rapport à là où on est</li>
</ul>
<p>Le premier est très utilisé dans les formulaires :</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;form action=&quot;.&quot;&gt;</pre></div></div>

<p>Puisque la plupart du temps, on veut envoyer les informations sur la page en cours.</p>
<p>Le second est utilisé pour remonter dans l’arborescence du site sans se soucier de là où on est. Par exemple si on est sur :</p>
<p><code>http://sametmax.com/cours-et-tutos/les-articles-pour-apprendre-python-dans-le-bon-ordre/</code></p>
<p>Alors :</p>
<p><code>href="http://sametmax.com/cours-et-tutos/les-articles-pour-apprendre-python-dans-le-bon-ordre/../"</code></p>
<p>Ou plus simplement :</p>
<p><code>href=".."</code></p>
<p>Va vous emmener sur</p>
<p><code>http://sametmax.com/cours-et-tutos/</code></p>
<p>Et on peut les cumuler :</p>
<p><code>href="http://sametmax.com/cours-et-tutos/les-articles-pour-apprendre-python-dans-le-bon-ordre/../../"</code></p>
<p>Ou</p>
<p><code>href="../../"</code></p>
<p>Va vous emmener sur la page d’accueil (<code>/</code>).</p>
<h2>Paramètres et ancres</h2>
<p>Si les URLs sont si puissantes, c&#8217;est parce qu&#8217;elle sont très complètes.</p>
<p>Notamment, on peut aussi spécifier que l&#8217;on vise une partie d&#8217;une ressource en particulier, avec ce qu&#8217;on appelle l&#8217;ancre (ou hash en anglais).</p>
<p>Par exemple, sur une page Web, le hash permet de dire que l&#8217;URL vise une partie de la page Web :</p>
<p><code><a href="https://en.wikipedia.org/wiki/Hashish#History">https://en.wikipedia.org/wiki/Hashish#History</a></code></p>
<p>Le hash, c&#8217;est tout ce qu&#8217;il y à partir du &#8220;<code>#</code>&#8220;. Il se met APRÈS le chemin. Ici, c&#8217;est &#8220;<code>#History</code>&#8220;. Si vous cliquez sur le lien, vous verrez que vous arriverez directement à la partie &#8220;History&#8221; de la page.</p>
<p>Autre chose : on peut passer des paramètres à une URL. Les paramètres se mettent APRÈS le chemin mais AVANT le hash (qu&#8217;il existe ou non), et consiste en tout ce qu&#8217;il y a à partir du &#8220;?&#8221; :</p>
<p><code><a href="https://duckduckgo.com/?q=choucroute">https://duckduckgo.com/?q=choucroute</a></code></p>
<p>Ici, les paramètres sont <code>q=choucroute</code>.</p>
<p>Les paramètres servent à passer des informations supplémentaires avec l&#8217;URL, pour quelque chose qui n&#8217;a pas été prévu par le format URL. Dans notre exemple, il permet de spécifier à DuckDuck go qu&#8217;on cherche le mot &#8220;choucroute&#8221;.</p>
<p>Les paramètres ne sont pas standardisés, ils sont différents pour chaque service qui expose ses ressources via une URL, et donc dans le cas du Web, pour chaque site.</p>
<p>On peut lire les paramètres ainsi :</p>
<p><code>?nom=valeur&#038;autre_param=autre_valeur&#038;troisieme_param=valeur</code></p>
<p>Chaque paramètre a un nom et sa valeur, et chaque couple &#8220;nom&#8221; / &#8220;valeur&#8221; est séparé par le signe &#8220;<code>&#038;</code>&#8220;.</p>
<p>Il est courant d&#8217;appeler cette partie de l&#8217;URL une &#8220;query string&#8221;.</p>
<h2>La totale</h2>
<p>On peut tout mélanger bien sûr !</p>
<p>Exemple :</p>
<p><a href="http://www.siteduzero.com/forum/sujet/entrainez-vous-sur-le-langage-python-54161?page=2#message-5579148">http://www.siteduzero.com/forum/sujet/entrainez-vous-sur-le-langage-python-54161?page=2#message-5579148</a></p>
<ul>
<li>Protocole : http</li>
<li>Nom de domaine :
<ul>
<li>TLD : com</li>
<li>Nom du site : siteduzero</li>
<li>Sous-domaine: www</li>
</ul>
<li>Chemin : /forum/sujet/entrainez-vous-sur-le-langage-python-54161</li>
</li>
<li>Paramètres : ?page=2</li>
<li>Ancre : #message-5579148</li>
</ul>
<p>En fait on peut même mélanger beaucoup plus. Les urls peuvent contenir des noms d&#8217;utilisateur, des mots de passe et tout un tas d&#8217;autres informations. </p>
<p>Du fait de cette richesse, on utilise généralement des bibliothèques dédiées pour les analyser. Par exemple en Python:</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> <span style="color: #dc143c;">urlparse</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">urlparse</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> url = <span style="color: #dc143c;">urlparse</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://www.siteduzero.com/forum/sujet/entrainez-vous-sur-le-langage-python-54161?page=2#message-5579148'</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> url.<span style="color: black;">path</span>
<span style="color: #483d8b;">'/forum/sujet/entrainez-vous-sur-le-langage-python-54161'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> url.<span style="color: black;">query</span>
<span style="color: #483d8b;">'page=2'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> url.<span style="color: black;">fragment</span> <span style="color: #808080; font-style: italic;"># hash</span>
<span style="color: #483d8b;">'message-5579148'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> url.<span style="color: black;">netloc</span> <span style="color: #808080; font-style: italic;"># nom de domaine</span>
<span style="color: #483d8b;">'www.siteduzero.com'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> url.<span style="color: black;">scheme</span> <span style="color: #808080; font-style: italic;"># protocole</span>
<span style="color: #483d8b;">'http'</span></pre></div></div>

<h2>URL, URI et URN</h2>
<p>Les puristes vont vous emmerder avec la notion d&#8217;URI et d&#8217;URN.</p>
<p>Pour faire simple :</p>
<p>Une URL est une URI.<br />
Une URN est une URI.</p>
<p>Personne ne se sert des URN à part quelques obscurs programmeurs Java et XML (ce qui est souvent la même chose).</p>
<p>Vous utilisez des URLs. Le monde entier utilise des URLs. Le Web marche avec des URLs.</p>
<p>Les URIs et URNs peuvent aller se faire foutre.</p>
<h2>La notion de ressource</h2>
<p>Une URL identifie &#8220;où&#8221; est une &#8220;ressource&#8221;.</p>
<p>Mais c&#8217;est où &#8220;où&#8221; ? Et c&#8217;est quoi une &#8220;ressource&#8221; ?</p>
<p>C&#8217;est une très bonne question, et qui n&#8217;a pas de bonne réponse.</p>
<p>Où, ça peut être n&#8217;importe où. Les &#8220;ressources&#8221; (sur le Web, des pages Web le plus souvent), peuvent être sur une machine quelque part, ou ne pas exister, et être juste créées quand vous les demandez.</p>
<p>C&#8217;est un concept abstrait. On IMAGINE qu&#8217;il y a &#8220;un truc&#8221; à &#8220;un endroit&#8221;. Mais ni le truc, ni l&#8217;endroit n&#8217;existent. C&#8217;est une convention pour que vous et moi, quand on parle d&#8217;une vidéo, une page Web, un document PDF, un rapport&#8230; On puisse parler de la même chose. On utilise donc l&#8217;URL, qui est l&#8217;&#8221;endroit&#8221; où ça se trouve, pour en parler. Parce que c&#8217;est la seule manière d&#8217;être à peu prêt certain qu&#8217;on parle de la même chose.</p>
<p>En pratique, une URL peut pointer sur une ressource de n&#8217;importe quelle nature :</p>
<ul>
<li>une page HTML : <a href="http://www.epbot.com/2012/08/lady-vadore-at-star-wars-celebration.html">http://www.epbot.com/2012/08/lady-vadore-at-star-wars-celebration.html</a></li>
<li>un document PDF : <a href="media/d3fb09fa.python_notes.pdf" data-original-source="http://sametmax.com/tout-ce-que-vous-vouliez-savoir-sur-les-urls-web-sans-jamais-oser-le-demander/www.irem.sciences.univ-nantes.fr/Calcul/python_notes.pdf">www.irem.sciences.univ-nantes.fr/Calcul/python_notes.pdf</a></li>
<li>une image : <a href="media/c2243539.wtfm_cf7237e5-a580-4e22-a42a-f8597dd6c60b.jpg" data-original-source="http://www.warriordudimanche.net/data/images/wtfm_cf7237e5-a580-4e22-a42a-f8597dd6c60b.jpg">http://www.warriordudimanche.net/data/images/wtfm_cf7237e5-a580-4e22-a42a-f8597dd6c60b.jpg</a></li>
<li>une video : <a href="http://www.youtube.com/embed/HA7F4zB95y0">http://www.youtube.com/embed/HA7F4zB95y0</a></li>
</ul>
<p>C&#8217;est le serveur (dans notre cas) le site qui décide ce que signifie &#8220;où&#8221; et ce que sera &#8220;quoi&#8221;. Mais au final, sur un réseau TOUT est URL. Absolument tout.</p>
<p>En fait, derrière, la ressource peut très bien changer (résultat du moteur de recherche, page de profile, etc). Donc une ressource, c&#8217;est un truc mouvant.</p>
<hr />
<p>PS: putain quand je me suis lancé dans la rédaction de l&#8217;article, je m&#8217;attendais pas à passer la matinée dessus. C&#8217;est dingue tout ce qu&#8217;il y a à savoir sur une si petite notion. Toute l&#8217;informatique est comme ça : c&#8217;est pas compliqué, mais y a tellement de trucs à savoir. Faut pas s&#8217;étonner que les non geeks ont de plus en plus de mal à suivre. Ils ont autre chose à foutre que de lire 1500 pages de manuel pour envoyer une photo de leur cul à leur voisin.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=4623&amp;md5=ba4917d378b1a453baca850e1392153b" 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=4461
title: ‘Redis’ object has no attribute ‘connection’
uri: Redis-object-has-no-attribute-connection
url: http://sametmax.com/redis-object-has-no-attribute-connection/
content:
<p>Solution très conne à un problème très con.</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> <span style="color: #660033;">--upgrade</span> redis django-redis-cache django-redis-sessions</pre></div></div>

<p>L&#8217;api de la lib Python Redis a changé, et si vous utilisez des libs qui en dépendent, certains seront plus à jour. C&#8217;est balot, mais ça nous a turlupiné.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=4461&amp;md5=a27e0482fcc22272d4d312eb95d4a1a6" 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=3909
title: Nan mais c’est #old ça
uri: Nan-mais-c-est-old-ça
url: http://sametmax.com/nan-mais-cest-old-ca/
content:
<p>Régulièrement je poste des trucs que des gens ont déjà vu, et PoliceAuxFrontières, y a toujours un gros lourd dans le lot, souvent sur Twitter d&#8217;ailleurs, pour dire que c&#8217;est #old.</p>
<p>Quand quelqu&#8217;un joue la modération en disant que oh, hein, hey, l&#8217;agresseur se défend avec des arguments super massues tels que :</p>
<blockquote><p>
Ça a fait un peu le buzz quand ça été annoncé donc oui c&#8217;est old, 8 mois c&#8217;est beaucoup.</p></blockquote>
<p>Oui, on me l&#8217;a sortie celle là.</p>
<p>Je résume. </p>
<p>Quand ça fait du buzz, c&#8217;est intéressant et on peut en parler (indépendamment de ses qualités intrinsèques), et après, on peut plus (tout ce qui le rendait intéressant a disparu). 8 mois, c&#8217;est tellement vieux putain. C&#8217;est au moins, ouah, il y a une demi saison de The Big Bang Theory. </p>
<p>À l&#8217;époque j&#8217;étais une personne complètement différente. J&#8217;ai changé maintenant. Le nouveau moi, plus mature, plus homme. Otez de ma vue ce meme de chaton qui fait LOL, c&#8217;est so last year, maintenant il doit faire &#8220;tabernacle&#8221;. Non, trop tard, ne le twittez pas, c&#8217;est déjà passé !</p>
<p>Chère petite masse gluante des internets, vous avez bien conscience que la MAJORITÉ des choses que vous voyez sur le net a déjà été vue ailleurs ? Déjà dans la littérature, le théâtre, le cinéma, la peinture, la science et les groupes de potes à la récré, pour commencer.</p>
<p>Ensuite, que quelque chose ait déjà été vu ne périme pas une info. Ce qui périme une info, c&#8217;est qu&#8217;elle ne puisse plus servir à personne.</p>
<p>Maintenant, les gens sur imgur, bashfr, lisant des blogs, ou même les gens sur twitters, sont, je le rappelle, une minorité. Bienvenue dans le monde réel, Néo.</p>
<p>Donc si VOUS en avez entendu parler, il y a fort à parier que la majorité de l&#8217;espèce humaine n&#8217;en a pas encore entendu parler. Mais quand bien même c&#8217;est un truc réutilisé, ne faites pas chier le monde. Si ça ne vous intéresse pas, fermez votre gueule, et allez voir ailleurs.</p>
<p>Putain, internet c&#8217;est grand, et le reste du Web est à un clic de là. Donc plutôt que de gâcher l’électricité, le temps CPU, l&#8217;usure des cables et du clavier nécessaire à faire un commentaire bouseux qui met en avant que vous avez vu le truc déjà une fois, cassez-vous.</p>
<p>Y a déjà assez de bruit sur le net entre les &#8220;first&#8221;, &#8220;so gayyyy&#8221; et autres posts de remplissage. Donc votre #old, on s&#8217;en branle :</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="510" height="400" src="http://xhamster.com/xembed.php?video=672817" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<p>Merci</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=3909&amp;md5=99fd21639466fff7718cb76de2d22fe1" 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=4379
title: La virgule n’est pas un opérateur en Python
uri: La-virgule-n-est-pas-un-opérateur-en-Python
url: http://sametmax.com/la-virgule-nest-pas-un-operateur-en-python/
content:
<p>Premiers tutos, et vous apprenez l&#8217;existence du tuple :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">t = <span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> t
<span style="color: #808080; font-style: italic;">## (1, 2)</span>
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>t<span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## &lt;type 'tuple'&gt;</span></pre></div></div>

<p>Puis en creusant un peu, vous apprenez qu&#8217;un tuple, en fait, c&#8217;est juste une série d&#8217;objets séparés par des virgules :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">t = <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>
<span style="color: #ff7700;font-weight:bold;">print</span> t
<span style="color: #808080; font-style: italic;">## (1, 2)</span></pre></div></div>

<p>Les parenthèses sont optionnelles pour créer un tuple.</p>
<p>Du coup si on rajoute l&#8217;<a href="http://sametmax.com/operateur-splat-ou-etoile-en-python/">unpacking</a> :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">a, b = <span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> a
<span style="color: #808080; font-style: italic;">## 1</span>
<span style="color: #ff7700;font-weight:bold;">print</span> b
<span style="color: #808080; font-style: italic;">## 2</span></pre></div></div>

<p>Du coup on peut faire des fonctions qui semblent (mais c&#8217;est une illusion), <a href="http://sametmax.com/ce-que-vous-ne-saviez-pas-sur-les-collections-en-python/">retourner plusieurs valeurs</a> à la fois :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## (1, 2)</span>
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## &lt;type 'tuple'&gt;</span>
a, b = foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> a
<span style="color: #808080; font-style: italic;">## 1</span>
<span style="color: #ff7700;font-weight:bold;">print</span> b
<span style="color: #808080; font-style: italic;">## 2</span></pre></div></div>

<p>Mais un jour, au lieu de faire ça :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">t = <span style="color: #483d8b;">&quot;a&quot;</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;b&quot;</span>, <span style="color: #483d8b;">&quot;a&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> t
<span style="color: #808080; font-style: italic;">## True</span></pre></div></div>

<p>Vous faites ça</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">t = <span style="color: #483d8b;">&quot;a&quot;</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #483d8b;">&quot;b&quot;</span>, <span style="color: #483d8b;">&quot;a&quot;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> t
<span style="color: #808080; font-style: italic;">## (False, 'a')</span></pre></div></div>

<p>Enfer, damnation et baba au rhum !</p>
<p>Ce n&#8217;est pas du tout ce que vous attendiez !</p>
<p>La raison à cela est que la virgule en Python n&#8217;est pas un opérateur, c&#8217;est un simple séparateur. Votre expression a donc été analysée comme :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;a&quot;</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #483d8b;">&quot;b&quot;</span><span style="color: black;">&#41;</span>, <span style="color: #483d8b;">&quot;a&quot;</span></pre></div></div>

<p>C&#8217;est pour cela qu&#8217;utiliser les parenthèses est recommandé avec les tuples : pour clarifier la priorisation des opérations. Car comme la virgule n&#8217;est pas un opérateur, elle n&#8217;a pas de priorité définie comme pour *, /, and et or, et c&#8217;est un peu la fête du slip.</p>
<p>Moralité : à part pour l&#8217;unpacking, utilisez toujours des parenthèses dans vos tuples.</p>
<p>Ça vous évitera des aventures du genre :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">s = <span style="color: #483d8b;">&quot;Ceci est un %s %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #483d8b;">&quot;test&quot;</span>, <span style="color: #483d8b;">&quot;idiot&quot;</span>
<span style="color: #808080; font-style: italic;">## TypeError: not enough arguments for format string</span>
<span style="color: #ff7700;font-weight:bold;">print</span> s
&nbsp;
s = <span style="color: #483d8b;">&quot;Ceci est un %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #483d8b;">&quot;test&quot;</span>, <span style="color: #483d8b;">&quot;idiot&quot;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> s
<span style="color: #808080; font-style: italic;">## ('Ceci est un test', 'idiot')</span>
&nbsp;
s = <span style="color: #483d8b;">&quot;Ceci est un %s %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;test&quot;</span>, <span style="color: #483d8b;">&quot;idiot&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> s
<span style="color: #808080; font-style: italic;">## Ceci est un test idiot</span></pre></div></div>

<hr />
<a href="https://github.com/sametmax/codes-des-articles/blob/master/2013/fev/virgule_pas_un_operateur.py">Télécharger le code source de ce tuto</a></p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=4379&amp;md5=f416f3697e1f70f30638ca8c359666d6" 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=4670
title: Pourquoi ça a tranché, chérie
uri: Pourquoi-ça-a-tranché-chérie
url: http://sametmax.com/pourquoi-ca-a-tranche-cherie/
content:
<p>Juste un petit mot en passant pour expliquer le couac d&#8217;hier (et aussi parcequ&#8217;on se casse au ski donc les articles attendront) : notre hébergeur, leaseweb (et pas online.net qui était l&#8217;ancien hébergeur du blog), a eu quelques problèmes sur son réseau.</p>
<p>Comme ce sont des machines virtuelles, le problème s&#8217;est manifesté à notre niveau sous la forme d&#8217;un iowait de plus de 90% à la cause impossible à diagnostiquer et qui impliquait de fortes lenteurs sur le blog (et tous nos autres sites) jusqu&#8217;à ce qu&#8217;on force un reboot (juste sur le blog :-p).</p>
<p>C&#8217;était une mauvaise idée, puisque le serveur est devenu injoignable (alors que les autres tournaient mal, mais tournaient).</p>
<p>Au final, leaseweb à bien réagi en communiquant rapidement sur le problème et en remettant le truc d&#8217;équerre rapidement.</p>
<p>Ça nous a permis de réaliser que bien qu&#8217;on ait un backup du blog, on avait pas de backup de <a href="http://0bin.net">0bin</a>. C&#8217;est maintenant chose faite.</p>
<p>Comme on critique beaucoup Twitter en ce moment, au moins un point positif c&#8217;est que quand on se pête la gueule, on peut continuer à communiquer par ce genre de services tiers. Le could-social-over-hyper-3.0 n&#8217;a pas que du mauvais.</p>
<p>@+ dans le bus</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=4670&amp;md5=185ebdcd3bf5c9fab1d129d94d3b20f3" 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=5111
title: Quelques changements sur le blog
uri: Quelques-changements-sur-le-blog
url: http://sametmax.com/quelques-changements-sur-le-blog/
content:
<p>Suite à une demande d&#8217;un lecteur acharné, les tutos Python vont changer de format.</p>
<p>Si le code est un peu long, il sera maintenant noté dans la mesure du possible sous la forme:</p>
<p><code>expression<br />
## resultat</code></p>
<p>et non plus</p>
<p><code>>>> expression<br />
resultat</code></p>
<p>De manière à ce que ce soit facile à copier / coller pour jouer avec.</p>
<p>Et l&#8217;intégralité du code du tuto sera mis sur ce <a href="https://github.com/sametmax/codes-des-articles/">repo git</a>.</p>
<p>Vous pouvez déjà voir le résultat de ces changements sur le <a href="http://sametmax.com/la-virgule-nest-pas-un-operateur-en-python/">dernier tuto.</a></p>
<p>Au passage, vous avez du remarqué que pour les gros tutos de temps en temps on met des videos de musique. C&#8217;est aléatoire, la musique n&#8217;a pas de thème précis, c&#8217;est selon l&#8217;humeur.</p>
<p>La plantage de vendredi m&#8217;a aussi fait prendre conscience que ce blog ne durera pas toujours, et que quand on arrêtera d&#8217;écrire dedans, se serait bête de perdre tout son contenu. Je voudrais donc faire un dump statique du site à mettre en téléchargement à dispo.</p>
<p>Pour le moment j&#8217;ai essayé <a href="http://www.httrack.com/">htttrack</a>, mais il a un million d&#8217;options et avait pas finit après 3 heures. Puis divers <a href="http://wordpress.org/extend/plugins/static-html-output-plugin/">plugins wordpress</a> qui marchent tous moins bien les uns que les autres. Le dump SQL demanderait trop de nettoyage manuel. Le dump XML pareil, il contient les mails des posteurs de comment, et je ne veux pas divulguer vos adresses à qui que ce soit.</p>
<p>Bref, si vous avez une suggestion pour une &#8220;one command => mirror site&#8221;, faites pêter.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5111&amp;md5=874a94cccfdd4ee11fe118f5fddc5749" 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=5117
title: Téléchargez le blog en entier pour le lire hors ligne
uri: Téléchargez-le-blog-en-entier-pour-le-lire-hors-ligne
url: http://sametmax.com/telechargez-le-blog-en-entier-pour-le-lire-hors-ligne/
content:
<p>Voilà, c&#8217;est dumpé, avec un simple :</p>
<p><code>wget -m -k -p -c -E http://sametmax.com</code></p>
<p>(d&#8217;ailleurs si vous voulez faire votre propre miroir du site vous pouvez faire pareil. Hier apparemment y a eu pas mal d&#8217;essais car nos stats ont bien monté pour un dimanche)</p>
<p>J&#8217;ai mis tout ça sur <a href="https://github.com/sametmax/miroir-du-blog">Github</a>, mais si vous aimez pas Git vous pouvez télécharger <a href="https://github.com/sametmax/miroir-du-blog/archive/master.zip">le zip</a>.</p>
<p>Je n&#8217;ai pas mis de process automatique pour le faire, donc on refera un dump quand on y pensera.</p>
<p>On a mis tout ça sous <a href="http://creativecommons.org/licenses/by/3.0/">Creative Common Unported</a>, ce qui signifie que vous pouvez le réutiliser pour un cours, dans un bouquin et même le réadapter à votre sauce, le traduire en Klingon et le publier en morse.</p>
<p>Y a un paquet de trucs mine de rien, et pas seulement nos articles mais aussi de très très bons commentaires et des posts invités.</p>
<p>J&#8217;en profite donc pour remercier :</p>
<ul>
<li>Les gars qui ont pris le temps de poster des comments avec des infos, liens, corrections, et points de vues. Ça a apporté une grande valeur ajoutée au contenu et tout le monde en profite. Pour un blog à l&#8217;arrache, gratos dans un coin du net, ça claque d&#8217;avoir ce niveau de qualité.</li>
<li>Les correcteurs <strong>foxmask</strong>, <strong>kontre</strong> et <strong>fero14041</strong>. Ils sont un peu comme les bassistes d&#8217;un groupe de jazz. À l&#8217;arrière plan, mais la musique serait vachement moins bonne sans eux.</li>
<li>Les posteurs invités <strong>poulpe</strong>, <strong>recher</strong> et <strong>cortex</strong> qui ont apporté de la variété sur le blog, mais surtout qui l&#8217;ont fait avec des articles travaillés. Franchement les gars, vous vous êtes touchés.</li>
<li>D&#8217;autres internautes qui nous relaient comme <a href="http://lehollandaisvolant.net/">Timo</a> ou <a href="http://www.sebsauvage.net/">Seb</a> (mais aussi <a href="http://recher.wordpress.com/">Recher</a>, <a href="http://www.korezian.net/">Jeek</a>, <a href="http://www.hautefeuille.eu/">julien</a>, <a href="http://blog.howtommy.net/">Tommy</a>&#8230;). Au passage merci 1000 fois pour l&#8217;<a href="http://sebsauvage.net/streisand.me/sametmax/">autoblog</a> que Seb a mis en place car du coup ça faisait roue secours pendant que le blog était down vendredi.</li>
</ul>
<p>Du coup on a pas mal de choses sur le repo git maintenant:</p>
<ul>
<li><a href="https://github.com/sametmax/VizHash.js">Vizhash.js</a></li>
<li><a href="https://github.com/sametmax/jQuery-Visual-Password">jQuery Visual Password</a></li>
<li><a href="https://github.com/sametmax/django-quicky">Django Quicky</a> (qui a choppé plein de correctifs dernièrement)</li>
<li><a href="https://github.com/sametmax/0bin">Zerobin</a> (qui a une mise à jour qui permet d&#8217;uploader les images)</li>
</ul>
<p>Et bien sûr le tout nouveau repo du <a href="https://github.com/sametmax/codes-des-articles">code des articles</a> qui est un peu vide pour le moment. Donc ma question la suivante : est-ce que vous préférez qu&#8217;on remplisse le repo au fur et à mesure des nouveaux articles, ou alors que régulièrement on dépoussière un ancien article et qu&#8217;on le mette au <a href="http://sametmax.com/quelques-changements-sur-le-blog/">nouveau format</a> ?</p>
<p>Sachant que mine de rien des anciens articles sur <a href="http://sametmax.com/cours-et-tutos/les-articles-pour-apprendre-python-dans-le-bon-ordre/">Python</a> et <a href="http://sametmax.com/cours-et-tutos/les-articles-pour-apprendre-django-dans-le-bon-ordre/">Django</a>, on commence à en avoir une chiée.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5117&amp;md5=76640aee81e42784cd7a59cdfea49255" 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=5127
title: Exemples de bons codes Python
uri: Exemples-de-bons-codes-Python
url: http://sametmax.com/exemples-de-bons-codes-python/
content:
<p>Yeah, on a des fannnnnnns !</p>
<blockquote><p>Ça fait quelques semaines que je me suis mis à python. J&#8217;ai commencé par des scripts (tendance sysadmin oblige) puis je me suis lancé dans des choses un (petit) peu plus importantes, notamment influencé par les cours sur la POO. Je tiens d&#8217;ailleurs à vous féliciter sur ce point, même le site du zéro n&#8217;avait jamais réussi à me les faire vraiment comprendre. Et donc, comme tout débutant qui se respecte j&#8217;essaie de faire de mon petit programme un chef d&#8217;œuvre de perfection (et il y a du boulot).</p>
<p>Le truc, c&#8217;est que je ne connais rien aux bonnes pratiques en python (comment commenter utilement les fonctions, les conventions de nommage, les jolies façons de coder, etc&#8230;). Je suis à la recherche d&#8217;exemples sûrs.</p>
<p>Connaissez-vous des librairies ou applications au code exemplaire dont je pourrais m&#8217;inspirer tant au niveau du code lui-même que de l&#8217;API ou de la doc ?</p>
<p>(Allez, vous devez bien en avoir à l&#8217;esprit ^^)</p>
<p>Bref, merci (si c&#8217;est pas pour ça c&#8217;est pour le reste) et bonne soirée !</p></blockquote>
<p>Cher [censored],</p>
<p>Être placé au dessus du site du zéro provoque chez moi une érection incontrôlée. Merci.</p>
<p>Bonne nouvelle, il n&#8217;existe rien de tel que le code parfait, et des tas d&#8217;excellents dev font de la merde quotidiennement, ce qui permet de relativiser face à son niveau.</p>
<p>Maintenant, si je devais donner des exemples de code et doc dont on peut s&#8217;inspirer, je dirais :</p>
<ul>
<li>les modules <a href="https://github.com/sametmax/Bat-belt/blob/master/batbelt/strings.py">strings</a> et <a href="https://github.com/sametmax/Bat-belt/blob/master/batbelt/structs.py">structs</a> de batbelt sont faciles pour commencer et propres. Le reste est moins bon car la lib est encore en alpha (mais intéressante si tu as le temps) et il n&#8217;y a pas de doc. La <a href="https://0bin.readthedocs.org/en/latest/">doc</a> de zerobin en revanche est très bonne pour les utilisateurs (mais le code, bien que pas mauvais, n&#8217;est pas un exemple de best practice).</li>
<li><a href="https://github.com/jaraco/path.py">path.py</a> a un code est très accessible qui tient dans un seul fichier, mais on peut passer beaucoup de temps dessus. Il est plein de subtilités. Les tests unitaires aussi sont simples à aborder.</li>
<li><a href="https://github.com/coleifer/peewee/blob/master/peewee.py">peewee</a> a un code compliqué et abstrait mais très propre. Bien si on veut travailler ses connaissances sur l&#8217;architecture de code.</li>
<li> <a href="https://github.com/kennethreitz/requests">requests</a>. Niveau avancé, mais très abordable pour un si gros projet. Excellent pour voir comment s&#8217;articule un gros truc en plein de tout petits morceaux bien techniques. La doc technique est d&#8217;un bon niveau.</li>
<li>bottle : ne regarde surtout pas le code. Mais leur <a href="http://bottlepy.org/docs/dev/">doc technique</a> est exceptionelle.</li>
<li>le module CSV de la lib standard. Il est dans ton install Python (chez moi dans /usr/lib/python2.7/csv.py). Pas mal pour voir comment ça marche en interne, et c&#8217;est un petit module pas prise de tête. Ça permet aussi de voir que ceux qui suivent les meilleurs pratiques sont pas forcément ceux qui les prêchent.</li>
</ul>
<p>Petit rappel ceci dit : même un bon code a toujours des lacunes. Si tu prends n&#8217;importe quel bout de ces libs et le mets sur un forum, tu auras toujours un râleur pour venir débattre sur ce qu&#8217;il aurait valu mieux faire.</p>
<p>De plus, d&#8217;une manière générale, les gens qui publient de bons code font des trucs un peu plus compliqués qu&#8217;un simple script. Donc tu auras toujours à froncer un peu les sourcils pour comprendre. C&#8217;est normal, ne perd pas courage.</p>
<p>A éviter niveau code : django, bottle, twisted et les frameworks web en général. Les gros projets avec des bindings C de types sqlalchemy, qt, wx , etc. Car là on rentre dans un autre monde.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5127&amp;md5=c43159b2b3c9b31e25e96435c35b9e9d" 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=5136
uri: 2013-02-27-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 6.

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-6/

content:
<p>J&#8217;avais autant envie de me taper la rédaction d&#8217;un article que d&#8217;un handjob par Reiden par temps d&#8217;orage, alors je vous met la musique appropriée.</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="420" height="315" src="http://www.youtube.com/embed/egne2ZCMM_0" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<p>Prérequis :</p>
<ul>
<li>Avoir compris 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-5/">partie précédente</a>.</li>
<li>Avoir un peu de temps devant soi parce que ça va être long et vous allez bouffer des lignes de code par bottes de 12. Vous êtes prévenus.</li>
</ul>
<h2>Méthodes magiques</h2>
<p>Python ajoute à la POO quelques goodies, et notamment les méthodes appelées automatiquement. Vous savez, celles qui sont nommées avec deux doubles underscores comme ça : <code>def __methode__(self)</code>. On les nomme parfois les &#8220;méthodes magiques&#8221;.</p>
<p>Vous avez vu <code>__init__</code>, et j&#8217;ai fais un article sur <a href="http://sametmax.com/la-difference-entre-__new__-et-__init__-en-python/">__new__</a>. Mais il y en a d&#8217;autres. Un paquet d&#8217;autres.</p>
<h2>__del__, le coquinou</h2>
<p><code>__del__</code> est sémantiquement l&#8217;inverse de <code>__init__</code>, c&#8217;est une méthode appelée quand l&#8217;objet est détruit.</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;">time</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Action<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;">__del__</span><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: #483d8b;">&quot;C'est finiiiiiiiiii&quot;</span>
&nbsp;
&nbsp;
a = Action<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">del</span> a
<span style="color: #808080; font-style: italic;">## C'est finiiiiiiiiii</span>
&nbsp;
<span style="color: #dc143c;">time</span>.<span style="color: black;">sleep</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span></pre></div></div>

<p>On l&#8217;utilise pour faire des nettoyages une fois qu&#8217;un objet n&#8217;est plus utile comme fermer les sockets, les fichiers, etc.</p>
<p>Mais il y a un piège.</p>
<p>Le mot clé <code>del</code> en Python ne détruit pas un objet. Il ne fait que détruire la référence. C&#8217;est l&#8217;interpréteur Python qui compte les références des objets, et quand un objet n&#8217;a plus de référence pointant vers lui, il est marqué pour la suppression.</p>
<p>Ensuite, et seulement ensuite, le garbage collecteur arrive. Ceci n&#8217;est pas prédictible. Il peut arriver tout de suite après, ou mille opérations après. Et il supprime tous les objets marqués pour la suppression.</p>
<p>Alors seulement <code>__del__</code> est appelée.</p>
<p>Ce qui signifie que <code>__del__</code> peut être appelée beaucoup plus tard que vous le pensez, ou même pas du tout (si le script s&#8217;arrête avant).</p>
<h2>Donner de la gueule à ses objets</h2>
<p>Si vous créez un objet, la machine n&#8217;a aucune idée de ce que représente l&#8217;objet pour vous. Donc si vous lui demandez d&#8217;afficher cet objet, Python va afficher ce que l&#8217;objet représente pour lui :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Hic<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>, titre, auteur<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">titre</span> = titre
        <span style="color: #008000;">self</span>.<span style="color: black;">auteur</span> = auteur
&nbsp;
morceau = Hic<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;5eme Symfony&quot;</span>, <span style="color: #483d8b;">&quot;Beetlejuice&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> morceau
<span style="color: #808080; font-style: italic;">## &lt;Hic object at 0x1d877d0&gt;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: black;">&#91;</span>Hic<span style="color: black;">&#40;</span><span style="color: #483d8b;">'5eme Symfony'</span>, <span style="color: #483d8b;">'Beetlejuice'</span><span style="color: black;">&#41;</span>, Hic<span style="color: black;">&#40;</span><span style="color: #483d8b;">'La flute enchantee'</span>, <span style="color: #483d8b;">'Zarma'</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
<span style="color: #808080; font-style: italic;">## [&lt;Hic object at 0x1e54610&gt;, &lt;Hic object at 0x1e545d0&gt;]</span></pre></div></div>

<p>En gros il vous donne la classe de laquelle l&#8217;objet est issu, et son adresse en mémoire.</p>
<p>Mais si vous manipulez beaucoup ces objets dans un shell, vous êtes plus intéressé par le contenu de l&#8217;objet, pour rapidement identifier une instance.</p>
<p>Quand vous faites un <code>print</code>, Python essaye d&#8217;appeler les méthodes <code>__unicode__</code> et <code>__str__</code> (je ne sais plus dans quel ordre) pour récupérer la valeur à afficher. C&#8217;est le même comportement que d&#8217;appeler <code>unicode()</code> ou <code>str()</code> sur un objet :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">dico = <span style="color: black;">&#123;</span><span style="color: #483d8b;">'a'</span>: <span style="color: #ff4500;">1</span>, <span style="color: #483d8b;">'b'</span>: <span style="color: #ff4500;">2</span><span style="color: black;">&#125;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> dico
<span style="color: #808080; font-style: italic;">## {'a': 1, 'b': 2}</span>
&nbsp;
<span style="color: #008000;">str</span><span style="color: black;">&#40;</span>dico<span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## &quot;{'a': 1, 'b': 2}&quot;</span>
&nbsp;
<span style="color: #008000;">unicode</span><span style="color: black;">&#40;</span>dico<span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## u&quot;{'a': 1, 'b': 2}&quot;</span></pre></div></div>

<p>On peut donc coder les méthodes <code>__unicode__</code> et <code>__str__</code> pour obtenir ce résultat :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Hic<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>, titre, auteur<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">titre</span> = titre
        <span style="color: #008000;">self</span>.<span style="color: black;">auteur</span> = auteur
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__str__</span><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: #483d8b;">&quot;{} de {}&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">titre</span>, <span style="color: #008000;">self</span>.<span style="color: black;">auteur</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__unicode__</span><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> u<span style="color: #483d8b;">&quot;{} de {}&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">titre</span>, <span style="color: #008000;">self</span>.<span style="color: black;">auteur</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
morceau = Hic<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;5eme Symfony&quot;</span>, <span style="color: #483d8b;">&quot;Beetlejuice&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">str</span><span style="color: black;">&#40;</span>morceau<span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># ne marche que dans un terminal</span>
<span style="color: #808080; font-style: italic;">## '5eme Symfony de Beetlejuice'</span>
<span style="color: #008000;">unicode</span><span style="color: black;">&#40;</span>morceau<span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># ne marche que dans un terminal</span>
<span style="color: #808080; font-style: italic;">## u'5eme Symfony de Beetlejuice'</span>
<span style="color: #ff7700;font-weight:bold;">print</span> morceau
<span style="color: #808080; font-style: italic;">## 5eme Symfony de Beetlejuice</span></pre></div></div>

<p>Une autre méthode intéressante est <code>__repr__</code>. C&#8217;est ce que va utiliser Python quand vous entrez un objet dans un shell sans faire <code>print</code> ou quand vous faites <code>print</code> sur une structure de données (list, dico, etc) qui contient l&#8217;objet :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Hic<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
    ...
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__repr__</span><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: #483d8b;">&quot;Hic({}, {})&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">repr</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">titre</span><span style="color: black;">&#41;</span>, <span style="color: #dc143c;">repr</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">auteur</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #dc143c;">repr</span><span style="color: black;">&#40;</span>morceau<span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## Hic('5eme Symfony', 'Beetlejuice')</span>
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: black;">&#91;</span>Hic<span style="color: black;">&#40;</span><span style="color: #483d8b;">'5eme Symfony'</span>, <span style="color: #483d8b;">'Beetlejuice'</span><span style="color: black;">&#41;</span>, Hic<span style="color: black;">&#40;</span><span style="color: #483d8b;">'La flutte enchantee'</span>, <span style="color: #483d8b;">'Zarma'</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
<span style="color: #808080; font-style: italic;">## [Hic('5eme Symfony', 'Beetlejuice'), Hic('La flutte enchantee', 'Zarma')]</span></pre></div></div>

<p>Quand c&#8217;est possible (quand c&#8217;est pas trop long), <code>__repr__</code> doit retourner le code qu&#8217;il faut saisir pour recréer l&#8217;objet. C&#8217;est ce que fait Python pour les objets simples :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #dc143c;">repr</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>u<span style="color: #483d8b;">&quot;Père&quot;</span>, u<span style="color: #483d8b;">&quot;Noël&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## [u'P\xe8re', u'No\xebl']</span>
<span style="color: black;">&#91;</span>u<span style="color: #483d8b;">&quot;Père&quot;</span>, u<span style="color: #483d8b;">&quot;Noël&quot;</span><span style="color: black;">&#93;</span>
<span style="color: #808080; font-style: italic;">## [u'P\xe8re', u'No\xebl']</span>
l = <span style="color: black;">&#91;</span>u<span style="color: #483d8b;">'P<span style="color: #000099; font-weight: bold;">\x</span>e8re'</span>, u<span style="color: #483d8b;">'No<span style="color: #000099; font-weight: bold;">\x</span>ebl'</span><span style="color: black;">&#93;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> l:
     <span style="color: #ff7700;font-weight:bold;">print</span> x
&nbsp;
<span style="color: #808080; font-style: italic;">## Père</span>
<span style="color: #808080; font-style: italic;">## Noël</span></pre></div></div>

<p>Copier / coller la valeur de retour de <code>__repr__</code> dans un shell pour un int, une list, un tuple, un set ou un dico permet de recréer ce dico.</p>
<h2>Surcharge des opérateurs</h2>
<p>En Python, on ne peut pas surcharger les opérateurs comme en C++ par exemple. Mais comme les opérateurs ne font qu&#8217;appeler des méthodes magiques, on peut simplement overrider ces méthodes magiques.</p>
<p>Je vous ai montré <a href="http://sametmax.com/ordonner-en-python/">comment faire ça pour les comparateurs</a> (<code>=</code>, <code>!=</code>, <code>></code>, etc). Mais on peut le faire aussi pour les opérateurs tels que <code>/</code>, <code>+</code>, etc.</p>
<p>C&#8217;est très pratique pour créer de jolis APIs :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Met<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>, nom<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">nom</span> = nom
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__str__</span><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>.<span style="color: black;">nom</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__add__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, other<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Override l'opérateur +
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> Met<span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span> + <span style="color: #483d8b;">' et '</span> + <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>other<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__sub__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, other<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Override l'opérateur -
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> Met<span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span> + <span style="color: #483d8b;">' sans '</span> + <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>other<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__mul__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, other<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Override l'opérateur *
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> Met<span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span> + <span style="color: #483d8b;">' avec plein de '</span> + <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>other<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__div__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, other<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Override l'opérateur /
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> Met<span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span> + <span style="color: #483d8b;">' avec très peu de '</span> + <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>other<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__mod__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, other<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Override l'opérateur %
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> Met<span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span> + <span style="color: #483d8b;">' servi dans '</span> + <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>other<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__pow__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, other<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Override l'opérateur **
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> Met<span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span> + <span style="color: #483d8b;">' relevé avec '</span> + <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>other<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__lshift__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, other<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Override l'opérateur &lt;&lt;
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> Met<span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span> + <span style="color: #483d8b;">' après '</span> + <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>other<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__and__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, other<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Override l'opérateur &amp;
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span>  Met<span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span> + <span style="color: #483d8b;">' accompagné de '</span> + <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>other<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__or__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, other<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Override l'opérateur |
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> Met<span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span> + <span style="color: #483d8b;">' à la place de '</span> + <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>other<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
&nbsp;
plat = Met<span style="color: black;">&#40;</span><span style="color: #483d8b;">'Canard laqué'</span><span style="color: black;">&#41;</span> + Met<span style="color: black;">&#40;</span><span style="color: #483d8b;">'son fond de volaille'</span><span style="color: black;">&#41;</span>
plat -= Met<span style="color: black;">&#40;</span><span style="color: #483d8b;">'vinaigrette'</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">*</span> Met<span style="color: black;">&#40;</span><span style="color: #483d8b;">'frites'</span><span style="color: black;">&#41;</span> / Met<span style="color: black;">&#40;</span><span style="color: #483d8b;">'sel'</span><span style="color: black;">&#41;</span>
plat = plat <span style="color: #66cc66;">**</span> Met<span style="color: black;">&#40;</span><span style="color: #483d8b;">'du piment'</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&lt;&lt;</span> Met<span style="color: black;">&#40;</span><span style="color: #483d8b;">'une entrée de chorizo'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> plat <span style="color: #66cc66;">&amp;</span> Met<span style="color: black;">&#40;</span><span style="color: #483d8b;">'banana split'</span><span style="color: black;">&#41;</span> | Met<span style="color: black;">&#40;</span><span style="color: #483d8b;">'poire belle hélène'</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## Canard laqué et son fond de volaille sans vinaigrette avec plein de frites avec très peu de sel relevé avec du piment après une entrée de chorizo accompagné de banana split à la place de poire belle hélène</span></pre></div></div>

<p><a href="http://peewee.readthedocs.org/en/latest/peewee/querying.html">Peewee utilise cela</a> pour permettre de faire des requêtes très expressives.</p>
<p>Ceci n&#8217;est qu&#8217;un échantillon des méthodes magiques liées aux opérateurs. La liste complète est <a href="http://docs.python.org/2/reference/datamodel.html?highlight=__mul__#emulating-numeric-types">ici</a>.</p>
<h2>Conversion</h2>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Degre<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>, valeur, degre=<span style="color: #483d8b;">'C'</span><span style="color: black;">&#41;</span>:
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">valeur</span> = valeur
        <span style="color: #008000;">self</span>.<span style="color: black;">degre</span> = degre
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__str__</span><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: #483d8b;">&quot;{} °{}&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">valeur</span>, <span style="color: #008000;">self</span>.<span style="color: black;">degre</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__int__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Comportement quand converti en entier.
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">valeur</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__float__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Comportement quand converti en float.
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">float</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">valeur</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__add__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, other<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Pour le fun
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">degre</span> <span style="color: #66cc66;">!</span>= other.<span style="color: black;">degre</span>:
            <span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #008000;">ValueError</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Can't add {} and {}&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">degre</span>, other.<span style="color: black;">degre</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">return</span> Degre<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">valeur</span> + other.<span style="color: black;">valeur</span>, <span style="color: #008000;">self</span>.<span style="color: black;">degre</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> __index__<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Comportement quand utilisé dans un slicing
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span></pre></div></div>

<p>La manipulation des températures se fait facilement :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">t1 = Degre<span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span>, <span style="color: #483d8b;">&quot;C&quot;</span><span style="color: black;">&#41;</span>
t2 = Degre<span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> t1 + t2
<span style="color: #808080; font-style: italic;">## 13 °C</span>
<span style="color: #ff7700;font-weight:bold;">print</span> t1 + Degre<span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span>, <span style="color: #483d8b;">'F'</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## Traceback (most recent call last):</span>
<span style="color: #808080; font-style: italic;">##   File &quot;&lt;ipython-input-66-bc724ef7a556&gt;&quot;, line 1, in &lt;module&gt;</span>
<span style="color: #808080; font-style: italic;">##     t1 + Degre(10, 'F')</span>
<span style="color: #808080; font-style: italic;">##   File &quot;&lt;ipython-input-62-6fa11d434082&gt;&quot;, line 32, in __add__</span>
<span style="color: #808080; font-style: italic;">##     raise ValueError(&quot;Can't add {} and {}&quot;.format(self.degre, other.degre))</span>
<span style="color: #808080; font-style: italic;">## ValueError: Can't add C and F</span></pre></div></div>

<p>Et on peut convertir tout ça :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>t1<span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## 10</span>
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #008000;">float</span><span style="color: black;">&#40;</span>t2<span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## 3.0</span></pre></div></div>

<p>Ce qui est utile dans ce cas là :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #ff4500;">1</span> + t1
<span style="color: #808080; font-style: italic;">## Traceback (most recent call last):</span>
<span style="color: #808080; font-style: italic;">##   File &quot;&lt;ipython-input-48-4dc33235a03a&gt;&quot;, line 1, in &lt;module&gt;</span>
<span style="color: #808080; font-style: italic;">##     print 1 + t1</span>
<span style="color: #808080; font-style: italic;">## TypeError: unsupported operand type(s) for +: 'int' and 'Degre'</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #ff4500;">1</span> + <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>t1<span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## 11</span></pre></div></div>

<p>On peut même utiliser l&#8217;objet dans un contexte inattendu :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">douleur = <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> douleur<span style="color: black;">&#91;</span>t2<span style="color: black;">&#93;</span>
<span style="color: #808080; font-style: italic;">## 3</span></pre></div></div>

<p>Il y a bien entendu plein d&#8217;autres conversion possibles : octal, arrondi, complexe&#8230;</p>
<h2>Programmation dynamique</h2>
<p>Parce que oui, messieurs, on peut faire des trucs dynamiques avec Python. Pas du niveau de Lisp, certes, mais plus qu&#8217;en assembleur.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Tronc<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__getattr__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, name<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Est appelée quand on demande un attribut appelé &quot;name&quot; et qu'il
            n'existe pas.
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">None</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__setattr__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, name, value<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Est appelée quand on assigne une valeur &quot;value&quot; à un attribut 
            appelé &quot;name&quot;, qu'il existe ou non.
&nbsp;
            L'inverse se fait avec __delattr__ (qui réagit à del obj.attr)
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Merci&quot;</span>
        <span style="color: #008000;">super</span><span style="color: black;">&#40;</span>Tronc, <span style="color: #008000;">self</span><span style="color: black;">&#41;</span>.<span style="color: #0000cd;">__setattr__</span><span style="color: black;">&#40;</span>name, value<span style="color: black;">&#41;</span></pre></div></div>

<p>Ce qui nous permet de réagir sur la manipulation des attributs :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">pers = Tronc<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> pers.<span style="color: black;">main</span> <span style="color: #808080; font-style: italic;"># pas d'erreur !</span>
<span style="color: #808080; font-style: italic;">## None</span>
<span style="color: #ff7700;font-weight:bold;">print</span> pers.<span style="color: black;">pied</span>
<span style="color: #808080; font-style: italic;">## None</span>
pers.<span style="color: black;">testicules</span> = <span style="color: #483d8b;">&quot;00&quot;</span>
<span style="color: #808080; font-style: italic;">## Merci</span>
<span style="color: #ff7700;font-weight:bold;">print</span> pers.<span style="color: black;">testicules</span>
<span style="color: #808080; font-style: italic;">## 00</span></pre></div></div>

<p>Un usage très courant de <code>__getattr__</code> est de dire que si l&#8217;attribut n&#8217;existe pas, on retourne l&#8217;attribut de la stratégie sous-jacente :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Parseur<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;">__getattr__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, name<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">strategy</span>, name<span style="color: black;">&#41;</span></pre></div></div>

<p>Relisez les tutos précédents si vous ne vous souvenez plus du pattern strategy.</p>
<p>Attention cependant, intercepter la manipulation des attributs peut facilement se terminer en boucle infinie :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Tronc<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
    ...
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__setattr__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, name, value<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Merci&quot;</span>
        <span style="color: #008000;">setattr</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, name, value<span style="color: black;">&#41;</span>
&nbsp;
pers = Tronc<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
pers.<span style="color: black;">testicules</span> = <span style="color: #483d8b;">&quot;00&quot;</span>
<span style="color: #808080; font-style: italic;">##   File &quot;&lt;statement&gt;&quot;, line 19, in __setattr__</span>
  File <span style="color: #483d8b;">&quot;&lt;statement&gt;&quot;</span>, line <span style="color: #ff4500;">19</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #0000cd;">__setattr__</span>
  File <span style="color: #483d8b;">&quot;&lt;statement&gt;&quot;</span>, line <span style="color: #ff4500;">19</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #0000cd;">__setattr__</span>
  File <span style="color: #483d8b;">&quot;&lt;statement&gt;&quot;</span>, line <span style="color: #ff4500;">19</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #0000cd;">__setattr__</span>
  ...
  <span style="color: black;">File</span> <span style="color: #483d8b;">&quot;&lt;statement&gt;&quot;</span>, line <span style="color: #ff4500;">19</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #0000cd;">__setattr__</span>
  File <span style="color: #483d8b;">&quot;&lt;statement&gt;&quot;</span>, line <span style="color: #ff4500;">19</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #0000cd;">__setattr__</span>
  File <span style="color: #483d8b;">&quot;&lt;statement&gt;&quot;</span>, line <span style="color: #ff4500;">19</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #0000cd;">__setattr__</span>
  File <span style="color: #483d8b;">&quot;&lt;statement&gt;&quot;</span>, line <span style="color: #ff4500;">19</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #0000cd;">__setattr__</span>
  File <span style="color: #483d8b;">&quot;&lt;statement&gt;&quot;</span>, line <span style="color: #ff4500;">19</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #0000cd;">__setattr__</span>
  File <span style="color: #483d8b;">&quot;&lt;statement&gt;&quot;</span>, line <span style="color: #ff4500;">19</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #0000cd;">__setattr__</span>
  File <span style="color: #483d8b;">&quot;&lt;statement&gt;&quot;</span>, line <span style="color: #ff4500;">19</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #0000cd;">__setattr__</span>
  File <span style="color: #483d8b;">&quot;&lt;statement&gt;&quot;</span>, line <span style="color: #ff4500;">18</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #0000cd;">__setattr__</span>
  File <span style="color: #483d8b;">&quot;/opt/reinteract/lib/reinteract/stdout_capture.py&quot;</span>, line <span style="color: #ff4500;">27</span>, <span style="color: #ff7700;font-weight:bold;">in</span> write
    <span style="color: #008000;">self</span>.<span style="color: black;">current</span>.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#41;</span>
  File <span style="color: #483d8b;">&quot;/opt/reinteract/lib/reinteract/stdout_capture.py&quot;</span>, line <span style="color: #ff4500;">89</span>, <span style="color: #ff7700;font-weight:bold;">in</span> write
    <span style="color: #008000;">self</span>.__write_function<span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#41;</span>
  File <span style="color: #483d8b;">&quot;/opt/reinteract/lib/reinteract/statement.py&quot;</span>, line <span style="color: #ff4500;">193</span>, <span style="color: #ff7700;font-weight:bold;">in</span> __stdout_write
    s = <span style="color: #008000;">self</span>.__coerce_to_unicode<span style="color: black;">&#40;</span>s<span style="color: black;">&#41;</span>
  File <span style="color: #483d8b;">&quot;/opt/reinteract/lib/reinteract/statement.py&quot;</span>, line <span style="color: #ff4500;">157</span>, <span style="color: #ff7700;font-weight:bold;">in</span> __coerce_to_unicode
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>s, <span style="color: #008000;">basestring</span><span style="color: black;">&#41;</span>:
<span style="color: #008000;">RuntimeError</span>: maximum recursion depth exceeded <span style="color: #ff7700;font-weight:bold;">while</span> calling a Python <span style="color: #008000;">object</span></pre></div></div>

<p>En effet <code>pers.testicules = "00"</code> déclenche <code>__setattr__</code> qui déclenche <code>setattr</code> qui déclenche <code>__setattr__</code> qui déclenche <code>setattr</code>, etc&#8230;</p>
<p>C&#8217;est pour cette raison que dans la classe ci-dessus, j&#8217;ai fait:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__setattr__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, name, value<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Est appelée quand on assigne une valeur à un attribut, qu'il existe
            ou non.
&nbsp;
            L'inverse se fait avec __delattr__ (qui réagit à del obj.attr)
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Merci&quot;</span>
        <span style="color: #008000;">super</span><span style="color: black;">&#40;</span>Tronc, <span style="color: #008000;">self</span><span style="color: black;">&#41;</span>.<span style="color: #0000cd;">__setattr__</span><span style="color: black;">&#40;</span>name, value<span style="color: black;">&#41;</span></pre></div></div>

<p>On appelle le <code>__setattr__</code> du parent, qui va assigner l&#8217;attribut, mais n&#8217;est pas concerné par l&#8217;interception.</p>
<p>Ce problème est à garder en tête avec une des méthodes magiques les plus dangereuses qui existe :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #0000cd;">__getattribute__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, name<span style="color: black;">&#41;</span></pre></div></div>

<p>Cela fonctionne comme <code>__getattr__</code>, mais pour TOUS les attributs. Même si ils existent. Le potentiel de meli-melo avec cette méthode est de magnitude 7, donc à utiliser à vos risques et périls.</p>
<p>Oui je l&#8217;utilise, oui.</p>
<p>Oui je passe 3h en debug à chaque fois que je le fais.</p>
<p>Dans tous les cas, utiliser les properties (faites un flashback&#8230;) ou les <a href="http://sametmax.com/les-descripteurs-en-python/">descripteurs</a> peut être une bonne alternative.</p>
<p>[last_minute_insert]<br />
J&#8217;avais oublié <code>__dir__</code> qui est aussi overridable et qui intercepte <code>dir(objet)</code>. Just sayin&#8217;&#8230;<br />
[/last_minute_insert]</p>
<h2>Conteneurs</h2>
<p>Parfois, on a besoin d&#8217;avoir le comportement d&#8217;un conteneur comme un dico ou une liste, mais avec des comportements spécialisés. Il y a des méthodes magiques spécialement pour ç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> Main<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
&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>, <span style="color: #66cc66;">*</span>args<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">cartes</span> = args
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> ajouter<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, carte<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">assert</span> <span style="color: #008000;">hasattr</span><span style="color: black;">&#40;</span>carte, upper<span style="color: black;">&#41;</span>, <span style="color: #483d8b;">&quot;La carte doit etre une string, dude&quot;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">cartes</span>.<span style="color: black;">append</span><span style="color: black;">&#40;</span>carte.<span style="color: black;">upper</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__unicode__</span><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> u<span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">cartes</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__str__</span><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> u<span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">cartes</span><span style="color: black;">&#41;</span>.<span style="color: black;">encode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'utf8'</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__len__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Est appelé quand on fait len() sur l'objet.
&nbsp;
            Utile pour donner une longeur à un objet
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">cartes</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__getitem__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, key<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Est appelé quand on fait objet[index] ou objet[key].
&nbsp;
            Utile pour simuler une liste ou un dico.
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">cartes</span><span style="color: black;">&#91;</span>key<span style="color: black;">&#93;</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__setitem__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, key, value<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Est appelé quand on fait objet[index] = &quot;truc&quot;
        &quot;&quot;&quot;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">cartes</span><span style="color: black;">&#91;</span>key<span style="color: black;">&#93;</span> = value
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__delitem__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, key<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Est appelé quand on fait del objet[index].
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #008000;">TypeError</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Tu ne peux pas m'effacer, mouhahahahaah !&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__iter__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Est appelé quand on fait un iter(objet), en particulier, cela
            arrive à chaque boucle for.
&nbsp;
            La valeur retournée doit être un iterateur.
&nbsp;
            En général on retourne une valeur retournée par iter()
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">iter</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">cartes</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> __reversed__<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Est appelé quand on fait reversed(objt)
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">reversed</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">cartes</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__contains__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, item<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Est appelé quand &quot;in objet&quot;
        &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> item <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">self</span>.<span style="color: black;">cartes</span>
&nbsp;
&nbsp;
&nbsp;
&nbsp;
main = Main<span style="color: black;">&#40;</span>u<span style="color: #483d8b;">'1Coeur'</span>, u<span style="color: #483d8b;">'7Pique'</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> main
<span style="color: #808080; font-style: italic;">## 1Coeur7Pique</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> carte <span style="color: #ff7700;font-weight:bold;">in</span> main: <span style="color: #808080; font-style: italic;"># parce qu'on a défini __iter__ !</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> carte
<span style="color: #808080; font-style: italic;">## 1Coeur</span>
<span style="color: #808080; font-style: italic;">## 7Pique</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> main<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> <span style="color: #808080; font-style: italic;"># __getitem__ !</span>
<span style="color: #808080; font-style: italic;">## 1Coeur</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'fdjsklfd'</span> <span style="color: #ff7700;font-weight:bold;">in</span> main <span style="color: #808080; font-style: italic;"># __contains__ !</span>
<span style="color: #808080; font-style: italic;">## False</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>main<span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## 2</span></pre></div></div>

<p>Bon, ici on aurait presque pu utiliser une liste directement, ou même hériter d&#8217;une liste. CEstPourLExemple©</p>
<p>On peut faire aussi des trucs sur les slices avec <code>__getslice__</code> / <code>__setslice__</code>. C&#8217;est le même principe.</p>
<h2>Divers, autres, à classer, en vrac&#8230;</h2>
<p><code>__enter__</code> et <code>__exit__</code>, dont j&#8217;ai parlé dans l&#8217;article sur <a href="sametmax.com/les-context-managers-et-le-mot-cle-with-en-python/">les context managers</a>.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">__format__<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, formatstr<span style="color: black;">&#41;</span></pre></div></div>

<p>Appelé quand on fait <code>"{:formater}".format(ta_variable)</code> et pour lequel formatstr contiendra &#8220;formater&#8221;. Dans le cas où vous vouliez définir un truc qui a plusieurs formats.</p>
<p><code>__instancecheck__(self, instance)</code> et <code>__subclasscheck__(self, subclass)</code> pour les fans d&#8217;instrospection qui veulent intercepter <code>isinstance(objet)</code> et <code>issubclass(objet)</code>. Parce qu&#8217;on ne sait jamais, des fois qu&#8217;on veuille faire un truc super mega vilain à ses collègues qu&#8217;ils mettront des mois à debugger après son licenciement.</p>
<p>Plus intéressant :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #0000cd;">__call__</span></pre></div></div>

<p>Permet de rendre un objet &#8220;callable&#8221;, c&#8217;est à dire appelable comme une fonction.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Question<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;">__call__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, question<span style="color: black;">&#41;</span>:
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">'Parce que'</span>
&nbsp;
q = Question<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
q<span style="color: black;">&#40;</span><span style="color: #483d8b;">'Pourquoiiiiiiiii ?'</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## 'Parce que'</span></pre></div></div>

<p>Ça ne sert pas tous les jours, mais ça peut être pratique si votre objet va être placé dans une liste de fonctions.</p>
<p>A noter aussi l&#8217;existence de trucs exotiques comme <code>__copy__</code>, <code>__deepcopy__</code>, <code>__getstate__</code>, <code>__setstate__</code> ou encore <code>__reduce__</code> qui servent à <a href="http://docs.python.org/2.7/library/copy.html?highlight=__copy__">cloner des objets</a>, <a href="http://docs.python.org/2.7/library/pickle.html?highlight=__setstate__#pickling-and-unpickling-normal-class-instances">les sérialiser</a>, etc. Ce sont des considérations assez avancées, qui mériteraient un article à part entière. Mais c&#8217;est aussi marrant que de la compta donc l&#8217;attendez pas pour demain.</p>
<p>Bon, vous commencez à avoir une sacré besace d&#8217;outils pour faire de la POO. </p>
<p>La prochaine partie, je pense que je vais prendre le code de path.py et le décortiquer sous vos yeux histoire que vous voyez ce qu&#8217;on peut faire avec un cas concret d&#8217;utilisation de la POO.</p>
<hr />
<a href="https://github.com/sametmax/codes-des-articles/blob/master/2013/fev/methodes_magiques.py">Télécharger le code de l&#8217;article</a></p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5136&amp;md5=8535bb3fb6debe05482b7bf287e254bd" 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=5184
title: Comment Redis et Memcache font expirer leurs données
uri: Comment-Redis-et-Memcache-font-expirer-leurs-données
url: http://sametmax.com/comment-redis-et-memcache-font-expirer-leurs-donnees/
content:
<p>Redis et Memcache ont des opérations d&#8217;insertion de complexité O(1) (très rapide). Malgré ça ils proposent tout deux l&#8217;expiration de clé.</p>
<p>Et je me suis demandé : comment ils font ? Comment je pourrais fais ça si je devais le coder en Python ?</p>
<p>En effet, rechercher une clé expirée prend du temps. J&#8217;ai pensé à utiliser <a href="http://sametmax.com/heapq-le-module-python-incompris/">heapq</a>, mais l&#8217;insertion serait en 0(log(n)) (temps dépendant du nombre d&#8217;items), donc rapide, mais loin des perfs de Redis et Memcache.</p>
<p>Même si on garde à l&#8217;esprit qu&#8217;ils sont codés en C, et donc plus rapide, ça m&#8217;a turlupiné. Comment ils font ces cons ?</p>
<p>La réponse est surprenant : ils font la même chose que <a href="http://0bin.net">0bin</a> !</p>
<p><a href="http://www.memcachier.com/documentation/memcache-user-guide/">Memcache</a> :</p>
<blockquote><p>Memcache doesn’t evict keys when their expiration time expires, as doing so isn’t possible while still guaranteeing O(1) operation times. Instead expiration is more of a way to say how long until a key should be considered stale. When a GET is performed, Memcache checks if the key’s expiration time is still valid before returning it.</p></blockquote>
<p><a href="http://redis.io/commands/expire">Redis</a> :</p>
<blockquote><p>Redis keys are expired in two ways: a passive way, and an active way. A key is actively expired simply when some client tries to access it, and the key is found to be timed out. Of course this is not enough as there are expired keys that will never be accessed again. This keys should be expired anyway, so periodically Redis test a few keys at random among keys with an expire set. All the keys that are already expired are deleted from the keyspace.</p></blockquote>
<p>Memcache et Redis ne cherchent donc pas les clés, ils vérifient l&#8217;expiration à l&#8217;accès de la clé et suppriment le contenu si c&#8217;est dépassé.</p>
<p>Redis va plus loin en régulièrement prenant des clés <strong>au hasard</strong> et en checkant leur date d&#8217;expiration.</p>
<div id="attachment_5185" class="wp-caption aligncenter" style="width: 260px"><a href="media/d0dd4d6c.nQrJypO.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/nQrJypO.gif"><img class="size-full wp-image-5185" title="Comment il fait ? Ah bah il fait pas." src="media/d0dd4d6c.nQrJypO.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/nQrJypO.gif" alt="Gif de Tealc' buvant un café très chaud" width="250" height="136" /></a><p class="wp-caption-text">Comment il fait ? Ah bah il fait pas.</p></div>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5184&amp;md5=51a10c7e9e484249e6653cf3a4456135" 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=2640
title: Spamgourmet, mon amour
uri: Spamgourmet-mon-amour
url: http://sametmax.com/spamgourmet-mon-amour/
content:
<p><a href="http://www.spamgourmet.com">Spamgourmet</a>, que j&#8217;ai découvert grace à Sebsauvage, est un service gratuit et fiable d&#8217;alias d&#8217;emails. Vous donnez votre email à ce service, et vous pouvez ensuite distribuer des alias de cet email aux autres sites.</p>
<p>Exemple:</p>
<p>Je m&#8217;inscris sur Spamgourmet avec l&#8217;adresse <strong>contact@sametmax.com</strong> et le nom d&#8217;utilisateur <strong>sam</strong>.</p>
<p>Si un autre site me demande une adresse, au lieu de lui donner mon email, je lui un alias comme ça:</p>
<p><code>mot.un_numero.nom_utilisateur@spamgourmet.com</code></p>
<p>En alias je met souvent le nom du site, donc ça donne un truc comme ça:</p>
<p><code>sncf.5.sam@spamgourmet.com</code></p>
<p><strong>Vous n&#8217;avez rien besoin de faire pour créer cet alias.</strong> Il suffit de l&#8217;imaginer dans votre tête, et qu&#8217;il respecte la structure &#8220;mot.un_numero.nom_utilisateur@spamgourmet&#8221;.</p>
<p>Bref, vous donnez cet email imaginaire à tous les sites qui vous en demande un.</p>
<p>Quand spamgourmet va recevoir un email, il va envoyer une copie de cet email à votre adresse, la vraie, qu&#8217;il a retrouvé grâce au nom d&#8217;utilisateur (sncf.5.<strong>sam</strong>@spamgourmet.com).</p>
<p>Mais il va faire un truc en plus : il va regarder le numéro dans l&#8217;email (sncf.<strong>5</strong>.sam@spamgourmet.com). Si vous avez reçu plus de mails que le numéro, donc ici plus de 5 mails, sur cette adresse, spamgourmet ne vous enverra plus la copie.</p>
<p>C&#8217;est une version plus puissante des alias avec &#8220;+&#8221;.</p>
<p>Attention, le nombre max qu&#8217;on peut donner est 20. Mais si vous en voulez plus, alors c&#8217;est qu&#8217;il est temps de mettre votre véritable adresse email. Généralement je vais dans le formulaire de profile du site en question et change mon adresse pour la bonne à ce moment là, ou avec un alias en &#8220;+&#8221;.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=2640&amp;md5=59e3418b5b87b1f7de09167ae2f55917" 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=3486
title: Les goodies CSS qu’on peut utiliser maintenant que IE6 est mort
uri: Les-goodies-CSS-qu-on-peut-utiliser-maintenant-que-IE6-est-mort
url: http://sametmax.com/les-selecteurs-css-quon-peut-utiliser-maintenant-que-ie6-est-mort/
content:
<p>Avouez-le, il y a encore des trucs que vous n&#8217;osez pas utiliser, par habitude. Parce que vous avez appris pendant 10 ans que ça passait pas, et maintenant, vous êtes pas certains, alors vous continuez. Malgré le fait que la <a href="http://standblog.org/blog/post/2009/02/20/Meurs-IE6,-Meurs-!">citation célèbre</a> de Tristan Nitot soit devenu une réalité depuis des années (et que le 7 est presque mort né), on s&#8217;abstient parfois idiotement d&#8217;utiliser quelques goodies. Juste dans le doute.</p>
<p>Voici quelques opérations CSS que vous pouvez enfin utiliser sans danger. Promis. Ça fait des années maintenant qu&#8217;on peut sortir de sa carapace.</p>
<h2>&gt; &#8211; Selecteur des enfants immédiats</h2>
<p>Selectionne les enfants du premier niveau, mais pas récursivement.</p>
<p>Exemple:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&nbsp;
&lt;style&gt;
ul &gt; li {
    margin-left:1em;
}
&lt;/style&gt;
&nbsp;
&lt;ul&gt;
    &lt;li&gt;Foo:
        &lt;ul&gt;
            &lt;li&gt;Bar&lt;/li&gt;
            &lt;li&gt;Bar&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/li&gt;
    &lt;li&gt;
    Foo
    &lt;/li&gt;
&lt;/ul&gt;</pre></div></div>

<p>Le sélecteur appliquera la marge aux <code>li</code> avec &#8220;Foo&#8221;, mais pas ceux avec &#8220;Bar&#8221;.</p>
<h2>[attr] &#8211; Selecteur d&#8217;attribut</h2>
<p>Sélectionne un élément s&#8217;il possède un attribut avec ce nom et cette valeur.</p>
<p>Exemple:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&nbsp;
&lt;style&gt;
p[title=&quot;bouya&quot;] {
    margin-left:1em;
}
&lt;/style&gt;
&nbsp;
&lt;p title=&quot;bouya&quot;&gt;Foo&lt;/p&gt;
&lt;p&gt;Bar&lt;/p&gt;
&lt;p title=&quot;bouya&quot;&gt;Foo&lt;/p&gt;</pre></div></div>

<p>Le sélecteur appliquera la marge au <code>p</code> avec &#8220;Foo&#8221;, mais à celui avec &#8220;Bar&#8221;.</p>
<p>On peut aussi faire plus raffiné en cherchant si l&#8217;attribut contient une partie de quelque chose.</p>
<h2>:first-child &#8211; Sélecteur de premier enfant</h2>
<p>Sélectionne un élément s&#8217;il est le tout premier enfant d&#8217;un autre.</p>
<p>Exemple:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&nbsp;
&lt;style&gt;
ul li:first-child {
    margin-left:1em;
}
&lt;/style&gt;
&nbsp;
&lt;ul&gt;
    &lt;li&gt;Foo &lt;/li&gt;
    &lt;li&gt;Bar&lt;/li&gt;
&lt;/ul&gt;</pre></div></div>

<p>Le sélecteur appliquera la marge au <code>li</code> avec &#8220;Foo&#8221;, mais à celui avec &#8220;Bar&#8221;.</p>
<h2>min/max width/height &#8211; Définir une taille minimal ou maximale</h2>
<p>Donne une taille qu&#8217;un élément doit au moins avoir, ou peut avoir au maximum.</p>
<p>Exemple:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&nbsp;
&lt;style&gt;
ul {
    min-height:3em;
    max-height:10em;
}
&lt;/style&gt;
&nbsp;
&lt;ul&gt;
    &lt;li&gt;Foo &lt;/li&gt;
    &lt;li&gt;Bar&lt;/li&gt;
&lt;/ul&gt;</pre></div></div>

<p>On a ici un <code>ul</code> de taille élastique qui va s&#8217;adapter au nombre d&#8217;éléments qu&#8217;il contient, mais il aura au moins une taille de <code>3em</code>, et il ne dépassera jamais <code>10em</code>.</p>
<h2>position:fixed &#8211; Position fixée dans le viewport</h2>
<p>Donne une position sur la partie visible de la page. Quand l&#8217;utilisateur scroll, l&#8217;élément est toujours visible à cet endroit.</p>
<p>Exemple:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&nbsp;
&lt;style&gt;
ul {
    position:fixed;
    right: left;
    top: 10%;
}
&lt;/style&gt;
&nbsp;
&lt;ul&gt;
    &lt;li&gt;Foo &lt;/li&gt;
    &lt;li&gt;Bar&lt;/li&gt;
&lt;/ul&gt;</pre></div></div>

<p>Le menu restera toujours en haut à gauche de la page, même si je scroll. La même chose est vraie pour <code>background-attachment: fixed</code> que l&#8217;on peut maintenant utiliser et qui s&#8217;appliquer aux images de background.</p>
<h2>.A.B &#8211; Sélection à classe multiple</h2>
<p>Pour sélectionner un élément qui a les DEUX classes.</p>
<p>Exemple:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&nbsp;
&lt;style&gt;
p.danger.alerte {
    color:&quot;putainderouge&quot;;
}
&lt;/style&gt;
&nbsp;
&lt;p class=&quot;danger&quot;&gt;Bar&lt;/p&gt;
&lt;p class=&quot;alerte&quot;&gt;Bar&lt;/p&gt;
&lt;p class=&quot;danger alerte&quot;&gt;Foo&lt;/p&gt;</pre></div></div>

<p>Seul le <code>p</code> avec &#8220;Foo&#8221; sera en rouge.</p>
<h2>blockquote + p &#8211; Sélection des éléments adjacents</h2>
<p>Sélectionne un élément s&#8217;il est juste après un autre.</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&nbsp;
&lt;style&gt;
blockquote + p {
    font-style:italic;
}
&lt;/style&gt;
&nbsp;
&lt;blockquote&gt;
Rien ne sert de ramer quand on attaque la falaise.
&lt;/blockquote&gt;
&lt;p&gt;Anonyme&lt;/p&gt;
&nbsp;
&lt;p&gt;Et maintenant quelque chose de complètement différent.&lt;/p&gt;</pre></div></div>

<p>Le nom de l&#8217;auteur de la citation va être mis en italique. Mais pas le second <code>p</code>.</p>
<h2>Et en prime</h2>
<p>On cite souvent:</p>
<ul>
<li><code>:first-line</code> &#8211; First line selector of content copy.</li>
<li><code>:first-letter</code> &#8211; First letter selector of content copy.</li>
</ul>
<p>Mais en vérité ils étaient déjà supportés par IE6.</p>
<p>Par contre, tous ces trucs qui marchaient, mais auxquels il fallait faire super gaffe :</p>
<ul>
<li><code>float: right</code> et <code>clear:both</code> </li>
<li><code>z-index</code></li>
<li><code>:hover</code>. Pas juste sur les <code>a</code>. Partouuuuuuuuuuut. (marche uniquement si on précise le doctype, mais qui ne le fait pas ?)</li>
</ul>
<p>Ça marche comme pour tous les autres maintenant.</p>
<p>En plus on a les PNGs transparents (24 bit).</p>
<p>Et d&#8217;après <a href="http://stackoverflow.com/a/4450872/9951">ce post </a>sur SO, on s&#8217;affranchit aussi des bugs suivant :</p>
<ul>
<li><a href="http://www.positioniseverything.net/explorer/peekaboo.html">Peekaboo Bug</a></li>
<li><a href="http://www.positioniseverything.net/explorer/expandingboxbug.html">Internet Explorer and Expanding Box Problem</a></li>
<li><a href="http://www.positioniseverything.net/explorer/percentages.html">Quirky Percentages</a></li>
<li><a href="http://www.positioniseverything.net/explorer/lineheightbug.html">Line-height bug</a></li>
<li><a href="http://www.positioniseverything.net/explorer/border-chaos.html">Border Chaos</a></li>
<li><a href="http://www.positioniseverything.net/explorer/ie-listbug.html">Disappearing List-Background bug</a></li>
<li><a href="http://www.positioniseverything.net/explorer/guillotine.html">Guillotine Bug</a></li>
<li><a href="http://www.positioniseverything.net/explorer/unscrollable.html">Unscrollable Content bug</a></li>
<li><a href="http://www.positioniseverything.net/explorer/dup-characters.html">Duplicate Characters Bug</a></li>
<li><a href="http://www.positioniseverything.net/explorer/italicbug-ie.html">IE and Italics</a></li>
<li><a href="http://www.positioniseverything.net/explorer/doubled-margin.html">Doubled Float-Margin bug</a></li>
<li><a href="http://www.positioniseverything.net/explorer/floatIndent.html">Duplicate Indent bug</a></li>
<li><a href="http://www.positioniseverything.net/explorer/threepxtest.html">Three pixel text jog</a></li>
<li><a href="http://www.positioniseverything.net/explorer/creep.html">Creeping Text bug</a></li>
<li><a href="http://www.positioniseverything.net/explorer/firstletter.html">Missing First letter bug</a></li>
<li><a href="http://www.positioniseverything.net/explorer/inlinelist.html">Phantom box bug</a></li>
<li><a href="http://work.arounds.org/issue/33/ie-has-limit-31-stylesheets-web-page/">31 style sheet limit</a> -</li>
</ul>
<p>Mais gaffe quand même pour les micros IE7 qui reste (il doit pas en rester des masses). Il compte parfois les commentaires comme des éléments sélectionnables par les sélecteurs qu&#8217;on vient de voir :-(.</p>
<p>Sinon, souvenez-vous que la compatibilité IE9 pour IE7 et 8 est à la portée d&#8217;un <a href="http://code.google.com/p/ie7-js/">tout petit include Javascript</a>.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=3486&amp;md5=9f93940306d63e63b2f83a85b32dd17c" 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=5223
title: Bon bah voilà
uri: Bon-bah-voilà
url: http://sametmax.com/bon-bah-voila/
content:
<p>[16:29:33] Sam: tu nous écris l&#8217;article sur les médecins là ?<br />
[16:29:36] Sam: j&#8217;ai une gueule bois<br />
[16:29:43] Sam: pas la foi d&#8217;écire<br />
[19:57:59] Max: alors là c mort taz m&#8217;a fait installé LoL hier :) suis dessus depuis 24h ^^</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5223&amp;md5=dac80a14639cadd6993364934f894692" 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=570
title: Les docstrings en Python
uri: Les-docstrings-en-Python
url: http://sametmax.com/les-docstrings/
content:
<p>Du fait de la nature du tuto, exceptionellement je ne respecterai pas le <a href="http://sametmax.com/quelques-changements-sur-le-blog/">nouveau format de rédaction</a>. Mais y aura quand même de la zik :</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="560" height="315" src="http://www.youtube.com/embed/ls-LYas5j8U" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<p>Une des mes fonctionnalités favorites en Python est son mécanisme de documentation du code : les docstrings. En effet, je crois qu&#8217;il est très important de rendre simple les tâches over chiantes comme les tests unitaires ou la doc car moins il y a de frein à le faire, plus il y a de chances qu&#8217;on le fasse.</p>
<h2>Principe</h2>
<p>La docstring est une chaîne de caractère que l&#8217;on assigne pas, et qui est placée à un endroit spécifique du code pour décrire ce dernier.</p>
<p>La docstring la plus courante est placée sous une fonction. Voici une fonction SANS docstring :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> ajouter<span style="color: black;">&#40;</span>a, b<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> a + b</pre></div></div>

<p>Et voici une fonction AVEC docstring :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> ajouter<span style="color: black;">&#40;</span>a, b<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
        Ajoute deux nombres l'un à l'autre et retourne
        le résultat.
    &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> a + b</pre></div></div>

<p>La chaîne de caractère doit être placée juste en dessous de la signature de la fonction.</p>
<p>Écrire des docstrings offrent de nombreux avantages :</p>
<ul>
<li>La fonction <code>help()</code> affiche cette documentation dans un shell.</li>
<li>Les outils de programmation tels que les shells ou les IDE affichent cette documentation quand le développeur qui ne lit pas votre code, mais l&#8217;utilise, en a besoin.</li>
<li>On peut générer une bonne doc du code avec des commandes qui extraient ces docstrings.</li>
<li>C&#8217;est un mécanisme standardisé de documentation : tout le monde sait que si c&#8217;est là, et que ça a cette forme, c&#8217;est une documentation.</li>
<li>Le code Python peut utiliser la docstring pour la lire ou l&#8217;afficher.</li>
<li>On peut mettre des tests dans les docstrings, qui servent alors d&#8217;exemples d&#8217;utilisation.</li>
</ul>
<h2>Usage</h2>
<p>Si vous avez une fonction ainsi faite :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> ajouter<span style="color: black;">&#40;</span>a, b<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
        Ajoute deux nombres l'un à l'autre et retourne
        le résultat.
    &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> a + b</pre></div></div>

<p>Alors dans un shell, toute personne qui va utiliser votre fonction pourra 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: #008000;">help</span><span style="color: black;">&#40;</span>ajouter<span style="color: black;">&#41;</span>
Help on function ajouter <span style="color: #ff7700;font-weight:bold;">in</span> module <span style="color: #dc143c;">__main__</span>:
&nbsp;
ajouter<span style="color: black;">&#40;</span>a, b<span style="color: black;">&#41;</span>
    Ajoute deux nombres l<span style="color: #483d8b;">'un à l'</span>autre et retourne
    le résultat.</pre></div></div>

<p>Il y a ainsi une documentation de votre fonction DANS le shell, sans avoir à se connecter à Internet ou quoi que ce soit. Il n&#8217;a pas à ouvrir le moindre fichier.</p>
<p>On peut documenter également les modules en plaçant la docstring comme première expression Python (qui n&#8217;est pas un commentaire) tout en haut du fichier :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot;
    Ceci est un module génial qui va faire 
    plein de trucs super cool.
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">threading</span>
<span style="color: #ff7700;font-weight:bold;">import</span> multiprocessing
<span style="color: #ff7700;font-weight:bold;">from</span> functools <span style="color: #ff7700;font-weight:bold;">import</span> wraps
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">Queue</span> <span style="color: #ff7700;font-weight:bold;">import</span> Empty
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> BaseAsbtractAdapterStrategyFactoryMock<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>On peut aussi documenter une classe et ses méthodes :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> ADallas<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
        Cette classe vous donne le classe à Dallas
        quand vous en avez vraiment besoin.
    &quot;&quot;&quot;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> univers_impitoyable<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot;
            Retourne un objet univers, prêt
            à être impitoyable.
        &quot;&quot;&quot;</span></pre></div></div>

<p>La plupart des fonctions et modules de la lib standard sont ainsi documentées, vous pouvez donc 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: #008000;">help</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">from</span> functools <span style="color: #ff7700;font-weight:bold;">import</span> partial
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">help</span><span style="color: black;">&#40;</span>partial<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">help</span><span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">help</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'foo'</span>.<span style="color: black;">upper</span><span style="color: black;">&#41;</span></pre></div></div>

<h2>Bonnes pratiques</h2>
<p>D&#8217;abord, et malgré mes exemples à caractère purement pédagogique précédents, votre docstring devrait être en anglais. Même quand vous travaillez uniquement avec des français. L&#8217;anglais est la lingua franca (oui, oui, je sais&#8230;) de l&#8217;informatique, et de plus vous évitez tout problème d&#8217;encoding car vous n&#8217;avez aucun moyen de savoir si cette doc sera lue dans un shell rêglé avec les pieds (comme celui de Windows).</p>
<p>J&#8217;écrirai un article pour motiver les résistants à se mettre à l&#8217;anglais une bonne fois pour toute.</p>
<p>L&#8217;anglais est votre ami. Il est la novlang de notre métier. C&#8217;est pas vendeur ça ?</p>
<p>Bref.</p>
<p>Ensuite, il existe plusieurs manières de formater une docstring, et il y a même un <a href="http://www.python.org/dev/peps/pep-0257/">PEP 257</a> qui ne parle que de ça. En résumé :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Docstring d'une ligne&quot;&quot;&quot;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Résumé de la docstring de plusieurs lignes.
&nbsp;
    Contenu détaillé de la doctstring.
    Contenu détaillé de la doctstring.
    Contenu détaillé de la doctstring.
&nbsp;
    &quot;&quot;&quot;</span></pre></div></div>

<p>Je ne respecte jamais cette convention. Généralement je fais plutôt :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
        Docstring d'une ligne.
    &quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
        Résumé de la docstring de plusieurs lignes.
&nbsp;
        Contenu détaillé de la doctstring.
        Contenu détaillé de la doctstring.
        Contenu détaillé de la doctstring.
    &quot;&quot;&quot;</span></pre></div></div>

<p>Je trouve ça immensément plus lisible dans le code. Je ne peux pas vous recommander de faire comme moi, puisque c&#8217;est aller à l&#8217;encontre du PEP. Tout ce que je peux vous dire c&#8217;est que personne ne s&#8217;est jamais plaint de cette habitude. En matière de docstring, la plupart des gens est juste déjà trop heureuse qu&#8217;il y en ait.</p>
<p>En revanche, tout le monde est d&#8217;accord sur le fait qu&#8217;une ligne de la docstring ne doit pas faire plus de 80 caractères. Donc indentez en conséquence. Le plugin SublimeText <a href="https://github.com/ehuss/Sublime-Wrap-Plus">Wrap-Plus</a> permet de le faire automatiquement avec <kbd>Alt</kbd> + <kbd>Q</kbd> (et bien plus). Un must have.</p>
<h2>Usage avancé</h2>
<p>Python étant un langage qui aime l&#8217;instrospection, la docstring est accessible depuis le code sous la forme de l&#8217;attribut <code>__doc__</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;">def</span> foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
...     <span style="color: #483d8b;">&quot;&quot;&quot;
...         Can foo a bar with ease
...     &quot;&quot;&quot;</span>
...     <span style="color: #ff7700;font-weight:bold;">pass</span>
...
<span style="color: #66cc66;">&gt;&gt;&gt;</span> foo.__doc__
<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\n</span>        Can foo a bar with ease<span style="color: #000099; font-weight: bold;">\n</span>    '</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span></pre></div></div>

<p>Vous ne vous en servirez pas souvent, mais c&#8217;est utile pour créer le help d&#8217;un script (c&#8217;est ce que fait <a href="http://sametmax.com/sept-petites-libs-qui-changent-la-vie-dun-dev-python/">clize</a>) ou faire une popup dans un IDE.</p>
<p>Une autre particularité des docstrings, c&#8217;est qu&#8217;elles sont très utilisées dans les générateurs de documentation comme <a href="http://sphinx-doc.org/">sphinx</a>. Et ils comprennent généralement très bien <a href="http://thomas-cokelaer.info/tutorials/sphinx/docstring_python.html">le format RST</a>.</p>
<p>Le format RST est une convention de balisage pour formater du texte. Il garde le texte lisible, mais permet de générer du HTML, du PDF et un tas d&#8217;autres trucs plus propres. Aussi je vous invite à l&#8217;utiliser si vous avez une docstring dont vous sentez qu&#8217;elle a besoin d&#8217;être aussi complète que possible.</p>
<p>Voici toutes les balises à votre disposition :</p>
<pre>:param arg1: description
:param arg2: description
:type arg1: type
:type arg1: type
:return: description de la valeur de retour
:rtype: type de la valeur de retour

:Example:

Un exemple écrit après un saut de ligne.

.. seealso:: Référence à une autre partie du code
.. warnings:: Avertissement
.. note:: Note
.. todo:: A faire</pre>
<p>On peut aussi utilise <code>``element``</code> pour signaler un morceau de code au milieu du texte. Sur les docstrings très longues (il n&#8217;est pas rare qu&#8217;une docstring soit plus longue que le code qu&#8217;elle documente), comme celles des modules, on peut sous-ligner les titres et sous-titres avec des <code>=</code> et des <code>-</code>.</p>
<p>Par exemple :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot;
    The ``obvious`` module
    ======================
&nbsp;
    Use it to import very obvious functions.
&nbsp;
    :Example:
&nbsp;
    &gt;&gt;&gt; from obvious import add
    &gt;&gt;&gt; add(1, 1)
    2
&nbsp;
    This is a subtitle
    -------------------
&nbsp;
    You can say so many things here ! You can say so many things here !
    You can say so many things here ! You can say so many things here !
    You can say so many things here ! You can say so many things here !
    You can say so many things here ! You can say so many things here !
&nbsp;
    This is another subtitle
    ------------------------
&nbsp;
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
    quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
    consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
    cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
    proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
&nbsp;
&nbsp;
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> add<span style="color: black;">&#40;</span>a, b<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
        Adds two numbers and returns the result.
&nbsp;
        This add two real numbers and return a real result. You will want to
        use this function in any place you would usually use the ``+`` operator
        but requires a functional equivalent.
&nbsp;
        :param a: The first number to add
        :param b: The second number to add
        :type a: int
        :type b: int
        :return: The result of the addition
        :rtype: int
&nbsp;
        :Example:
&nbsp;
        &gt;&gt;&gt; add(1, 1)
        2
        &gt;&gt;&gt; add(2.1, 3.4)  # all int compatible types work
        5.5
&nbsp;
        .. seealso:: sub(), div(), mul()
        .. warnings:: This is a completly useless function. Use it only in a 
                      tutorial unless you want to look like a fool.
        .. note:: You may want to use a lambda function instead of this.
        .. todo:: Delete this function. Then masturbate with olive oil.
    &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> a + b</pre></div></div>

<p>Aucun champ n&#8217;est obligatoire, aucuns ne sont interdépendant. Cela vous donne une grande flexibilité pour savoir jusqu&#8217;à quel point vous voulez documenter votre fonction.</p>
<p>La section la plus importante à mon sens est la <code>:Example:</code>. Avec ça une personne peut généralement avoir une bonne idée de ce qui se passe, et en plus ça sert de tests (comme on le verra plus loin).</p>
<p>La section la plus inutile est de loin <code>.. todo::</code>. En fait je vous recommande de ne pas l&#8217;utiliser. Si vous avez des todos, utilisez plutôt la convention de commentaire :</p>
<p><code># TODO: un truc à faire</code></p>
<p>Car :</p>
<ul>
<li>Je pense que vos TODO n&#8217;ont rien à foutre dans la doc.</li>
<li>Il faut mieux avoir un TODO le plus proche du truc qu&#8217;il doit modifier. Le mettre en haut de la fonction n&#8217;a pas toujours de sens.</li>
<li>De très nombreux outils et services détectent ce format automatiquement et en font quelque chose d&#8217;utile.</li>
</ul>
<p>Le typage des arguments et de la valeur de retour n&#8217;est pas toujours utile, surtout avec Python faisant massivement usage du duck typing. La description est plus importante. Mettez le typage quand le type n&#8217;est pas intuitif ou signalez une caratéristique comme : itérable, indexable, file-like object, etc.</p>
<p><em>EDIT: ah, y aussi un field <code>raises</code> pour déclarer que le code peut lever une exception en particulier. J&#8217;avais zappé. On m&#8217;a aussi demandé si il y avait des équivalent à <code>@since</code> et <code>@depreciated</code> mais non, en général on fout ça dans <code>.. note::</code> ou <code>.. warning:: </code></em></p>
<h2>Doc tests<br />
</h2>
<p>Une fonctionalité controversée des docstrings sont les doctests, des tests unitaires directement intégrés dans la docstring.</p>
<p>Mon conseil : utilisez les docstests pour des petites fonctions simples ou pour quelques exemples sur les fonctions complexes, et complétez les avec des tests ordinnaires. Ce sont des bons compléments, mais pas forcément idéales pour contenir TOUS les tests. Après, si c&#8217;est le seul truc qui vous motive pour écrire des tests, mettez tout dedans, il vaut mieux ça que rien du tout.</p>
<p>Une doc test est donc la rédaction d&#8217;une partie de la docstring avec la syntaxe d&#8217;un shell :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> add<span style="color: black;">&#40;</span>a, b<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
        Do I neeed to explain this ?
&nbsp;
        :Example:
&nbsp;
        &gt;&gt;&gt; add(1, 1)
        2
        &gt;&gt;&gt; add(2.1, 3.4)  # all int compatible types work
        5.5
&nbsp;
    &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> a + b
&nbsp;
<span style="color: #808080; font-style: italic;"># A la fin de votre script, mettez ce snippet qui va activer les doctest</span>
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">doctest</span>
    <span style="color: #dc143c;">doctest</span>.<span style="color: black;">testmod</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Si vous importez ce module, il ne se passera rien. Mais si vous faites <code>python script.py</code>, Python va exécuter <code>add(1, 1)</code> et vérifier que cela affiche bien <code>2</code>, puis exécuter <code>add(2.1, 3.4)</code> et vérifier que cela affiche bien <code>5.5</code>.</p>
<p>Si il n&#8217;y a aucune erreur, le script se termine silencieusement (il donne des détails si on utilise l&#8217;option <code>-v</code>). Sinon, il beugle. Par exemple si je rajoute :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">        <span style="color: #66cc66;">&gt;&gt;&gt;</span> add<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
        <span style="color: #ff4500;">3</span></pre></div></div>

<p>On obtient en sortie :</p>
<pre>$ python script.py
*******************************************
File "script.py", line 7, in __main__.add
Failed example:
    add(1, 1)
Expected:
    3
Got:
    2
*******************************************
1 items had failures:
   1 of   2 in __main__.add
***Test Failed*** 1 failures.</pre>
<p><strong>Attention !</strong></p>
<p>Python compare non pas la valeur, mais CE QUI S&#8217;AFFICHE. Ça peut être très déroutant. Si j&#8217;ai les tests :</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;">str</span><span style="color: black;">&#40;</span>add<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff4500;">2</span>
        <span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>add<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff4500;">2</span></pre></div></div>

<p>Ça va planter :</p>
<pre>$ python script.py
*******************************************
File "script.py", line 10, in __main__.add
Failed example:
    str(add(1, 1))
Expected:
    2
Got:
    '2'
*******************************************
1 items had failures:
   1 of   2 in __main__.add
***Test Failed*** 1 failures.</pre>
<p>Il aurait fallu que j&#8217;écrive :</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;">str</span><span style="color: black;">&#40;</span>add<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff4500;">2</span>
        <span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>add<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #483d8b;">'2'</span></pre></div></div>

<p>Notez les guillemets. C&#8217;est ainsi que ça s&#8217;afficherait dans le shell. Donc c&#8217;est ce que teste Python.</p>
<p>C&#8217;est la raison pour laquelle les docstests ne sont pas parfaites pour les gros tests. Si vous testez des caratères d&#8217;échappements ou du texte unicode, il vous faudra préfixer vos doctests de <code>ur</code> sinon ça va échouer :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">ur<span style="color: #483d8b;">&quot;&quot;&quot;
    Ceci est une doctring écrite en unicode, sans interprétation des caractères
    d'échappement.
&quot;&quot;&quot;</span></pre></div></div>

<p>Même problème pour les textes longs. Il faut préciser qu&#8217;on veut tester une sortie tronquée avec <code>+ELLIPSIS</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;">print</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1000</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># doctest: +ELLIPSIS</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">1</span>, ..., <span style="color: #ff4500;">18</span>, <span style="color: #ff4500;">999</span><span style="color: black;">&#93;</span></pre></div></div>

<p>Car vous allez pas écrire les 1000 entiers pour le fun dans le test. Pareil pour les stacktraces.</p>
<p>Les espaces sont signficatifs, du coup il faut parfois marquer les tests avec <code>+NORMALIZE_WHITESPACE</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;">print</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">20</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># doctest: +NORMALIZE_WHITESPACE</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: #ff4500;">4</span>,  <span style="color: #ff4500;">5</span>,  <span style="color: #ff4500;">6</span>,  <span style="color: #ff4500;">7</span>,  <span style="color: #ff4500;">8</span>,  <span style="color: #ff4500;">9</span>,
<span style="color: #ff4500;">10</span>,  <span style="color: #ff4500;">11</span>, <span style="color: #ff4500;">12</span>, <span style="color: #ff4500;">13</span>, <span style="color: #ff4500;">14</span>, <span style="color: #ff4500;">15</span>, <span style="color: #ff4500;">16</span>, <span style="color: #ff4500;">17</span>, <span style="color: #ff4500;">18</span>, <span style="color: #ff4500;">19</span><span style="color: black;">&#93;</span></pre></div></div>

<p>Sinon c&#8217;est galère car il faut reformater la sortie à la main correctement.</p>
<p>Enfin, sur les structures de données comme les dicos, l&#8217;ordre des éléments n&#8217;est pas garanti, donc l&#8217;ordre d&#8217;affichage non plus. Quand aux données aléatoires&#8230;</p>
<p>Bref, les docstests, c&#8217;est cool, mais il ne faut pas en abuser.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=570&amp;md5=50490beac989c8e1654ba090db51aa97" 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=5236
title: Gagner de la place sur Windows 7
uri: Gagner-de-la-place-sur-Windows-7
url: http://sametmax.com/gagner-de-la-place-sur-windows-7/
content:
<p>Vous avez un dual boot que vous utilisez rarement, mais disons totalement <a href="http://sametmax.com/bon-bah-voila/">hypothétiquement</a> que vos amis se mettent à jouer à League of Legend et que soudainement vous allez la réutiliser.</p>
<p>Vous bootez, et la stupeur vous gagne, il reste 2,1Mo de place libre sur la partition. Après avoir appuyé 3 fois sur &#8220;vider la corbeille&#8221; pour être bien sûr, le desespoir vous gagne.</p>
<p>Don&#8217;t panic.</p>
<h2>Détecter et virer les gros fichiers</h2>
<p>Vous téléchargez <a href="http://windirstat.info/">Win Dir Stats</a>, vous lancez un scan complet, et il va vous montrer les plus gros fichiers / dossiers de votre ordi. Il ne vous reste plus qu&#8217;à surpprimer manuellement tous ces parasites avec shift + delete pour les envoyer directement dans l&#8217;oblivion, sans passer par la case corbeille, et sans toucher 20 000 francs.</p>
<h2>Desinstaller massivement</h2>
<p>L&#8217;utilitaire de désinstallation de Windows est à chier. <a href="http://www.glarysoft.com/absolute-uninstaller/">Absolute uninstaller</a> est rapide et vous permet de supprimer allégrement tous ces boulets qui vous encombre.</p>
<h2>Vider winsxs</h2>
<p>C&#8217;est un dossier que Windows 7 ADOOOOOOOOORE charger de plein de merdes qui ne sont en fait que des fichiers temporaires. Ca peut monter jusqu&#8217;à 20 Go. Si.</p>
<p>Donc on cherche <code>cmd.exe</code> dans le menu, on clic droit &gt; &#8220;Executer en tant qu&#8217;Administrateur&#8221; et on lance la commande :</p>
<p><code>DISM /online /Cleanup-Image /SpSuperseded</code></p>
<p>C&#8217;est un peu long, mais ça libère quelques Go.</p>
<h2>Se débarrasser du fichier hyberfil.sys</h2>
<p>Quand on est en dual boot avec Linux comme système principal, on en a rien à branlé de la mise en veille de Windows. Qui prend quand même 4Go avec sont super fichier <em>hyberfil.sys</em>.</p>
<p>Donc pareil, vous lancez une console en tant qu&#8217;administrateur, et vous lui fermez sa gueule:<br />
<code><br />
powercfg.exe -h off</code></p>
<p>Un petit reboot, et l&#8217;hybernation est désactivée.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5236&amp;md5=a46f01ada914a13b0d872adcab65bc69" 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=5179
title: Qu’est-ce qu’un UUID et à quoi ça sert ?
uri: Qu-est-ce-qu-un-UUID-et-à-quoi-ça-sert
url: http://sametmax.com/quest-ce-quun-uuid-et-a-quoi-ca-sert/
content:
<p>Je vous avais <a href="http://sametmax.com/utiliser-des-uuid-comme-primary-key-avec-lorm-de-django/">déjà parlé</a> des UUID, mais je crois qu&#8217;ils méritent un article à eux tout seul.</p>
<p>Les <a href="https://en.wikipedia.org/wiki/Uuid">UUID</a> (Universally Unique IDentifiers) sont des séries de lettres et chiffres générées par la machine de telle sorte qu&#8217;ils soient garantis d&#8217;être uniques, quel que soit le nombre d&#8217;appel que vous faites, et ce, n&#8217;importe où dans le monde.</p>
<p>Ça ressemble à un truc comme ça :</p>
<p><code>550e8400-e29b-41d4-a716-446655440000</code></p>
<p>Si vous lancez la création de millions d&#8217;UUID ici, et autant au Japon, en Nouvelle Zélande et au Vénézuéla, vous avez la garantie de ne jamais avoir le même nombre qui sort 2 fois. C&#8217;est une garantie statistique: il y a 4×10³⁷ combinaisons possibles pour les versions des algos récents, et il faudrait créer un milliard de UUID par seconde pendant 100 ans pour que le prochain ait 50% de chance d’être un doublon. </p>
<p>Les UUID les plus célèbres sont les <a href="https://en.wikipedia.org/wiki/Guid">GUID</a> (Globally Unique IDentifiers) de Microsoft utilisés pour l&#8217;API COM, mais il existe de nombreuses versions. Par version, je veux dire qu&#8217;il existe plusieurs algos qui les produisent, basés soit sur l&#8217;adresse MAC (cette technique est dépreciée), soit sur des hash (md5, sha1, etc), soit sur une génération peudo aléatoire.</p>
<p>La version 4 du standard ISO/IEC 11578:1996 est justement basée sur du pseudo aléatoire, et est très largement répandue.</p>
<h2>Comment ça s&#8217;utilise en Python</h2>
<p>Il y a un module pour ça ©</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> uuid <span style="color: #ff7700;font-weight:bold;">import</span> uuid4
&nbsp;
uid = uuid4<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># créer un objet uuid</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>uid<span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## &lt;class 'uuid.UUID'&gt;</span>
&nbsp;
uid 
<span style="color: #808080; font-style: italic;">## UUID('786d1b69-a603-4eb8-9178-fed2a195a1ed')</span>
&nbsp;
<span style="color: #008000;">str</span><span style="color: black;">&#40;</span>uid<span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># récupérer la chaîne de caratères</span>
<span style="color: #808080; font-style: italic;">## '786d1b69-a603-4eb8-9178-fed2a195a1ed'</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> uid.<span style="color: #dc143c;">bytes</span> <span style="color: #808080; font-style: italic;"># la même chose en bytes</span>
<span style="color: #808080; font-style: italic;">## apparait ici un merdier de bytes</span>
<span style="color: #808080; font-style: italic;">## mais censuré car ça fait planter wordpress</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> uid.<span style="color: black;">get_version</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## 4</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> uid.<span style="color: #008000;">int</span> <span style="color: #808080; font-style: italic;"># pratique pour stocker comme un nombre</span>
<span style="color: #808080; font-style: italic;">## 160073875847165073709894672235460141549</span></pre></div></div>

<p>C&#8217;est très basique et facile à utiliser. Le module <a href="http://docs.python.org/2/library/uuid.html?highlight=uuid#uuid">uuid</a> contient de quoi générer des uuid version 1, 3, 4 et 5. Pour vérifier que deux UUIDs sont égaux, on peut les comparer, où comparer les chaînes.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">print</span> uuid4<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> == uuid4<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## False</span>
&nbsp;
uid = uuid4<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> uid == uid
<span style="color: #808080; font-style: italic;">## True</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> uid
<span style="color: #808080; font-style: italic;">## 837806a7-6c37-4630-9f6c-9aa7ad0129ed</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>uid<span style="color: black;">&#41;</span> == <span style="color: #483d8b;">&quot;837806a7-6c37-4630-9f6c-9aa7ad0129ed&quot;</span>
<span style="color: #808080; font-style: italic;">## True</span></pre></div></div>

<p>On peut aussi générer tout ça manuellement :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> uuid <span style="color: #ff7700;font-weight:bold;">import</span> UUID
&nbsp;
UUID<span style="color: black;">&#40;</span><span style="color: #008000;">int</span>=<span style="color: #ff4500;">160073875847165073709894672235460141549</span>, version=<span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## UUID('786d1b69-a603-4eb8-9178-fed2a195a1ed')</span></pre></div></div>

<h2>Usage ?</h2>
<p>C&#8217;est pratique pour générer des noms uniques.</p>
<p>Les systèmes de fichiers les utilisent pour identifier les disques durs. Les créateurs d&#8217;appareils électroniques pour identifier un appareil en particulier, ou une licence.</p>
<p>Les bases de données peuvent les utiliser à la place des entiers autoincrémentés pour les clés primaires. Très utile car l&#8217;ID est garanti d&#8217;être unique même si on le génère sur pleins de serveurs différents. On peut ainsi pratiquer le sharding, c&#8217;est à dire avoir une table (par exemple une table Utilisateurs), mais répartie sur plein de serveurs. Les JOINS sont plus lents par contre.</p>
<p>Nous on l&#8217;utilise beaucoup pour les images et les vidéos: c&#8217;est à la fois le nom de fichier, et une partie du nom de chaque dossier qui contient le fichier, afin de ne pas avoir trop de fichiers dans un dossier (ce qui peut faire mourir certaines commandes ou outils).</p>
<hr />
<p><a href="https://github.com/sametmax/codes-des-articles/blob/master/2013/mars/uuids.py">Télécharger le code de l&#8217;article.</a></p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5179&amp;md5=36ab942a2129ca36be47d4c740276668" 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=5260
title: Log post mortem avec Python
uri: Log-post-mortem-avec-Python
url: http://sametmax.com/log-post-mortem-avec-python/
content:
<p>Il y a des mois de ça, j&#8217;avais écris <a href="http://sametmax.com/lancer-une-fonction-automatiquement-a-larret-de-python/">un article sur atexit</a>, un module qui permet de lancer une fonction à la fermeture de la VM Python.</p>
<p>Ces fonctions sont appelées même si la VM s&#8217;arrête brutalement, mais on a aucune information sur la raison de l&#8217;arrêt de la machine virtuelle Python. Et elles sont exécutées même si tout s&#8217;est bien passé.</p>
<p>Si vous voulez réagir au plantage de votre programme, et seulement au plantage, tout en ayant en plus des informations sur la nature du foinage :</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;">sys</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> on_crash<span style="color: black;">&#40;</span><span style="color: #008000;">type</span>, value, tb<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #008000;">type</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> value
    <span style="color: #ff7700;font-weight:bold;">print</span> tb
&nbsp;
<span style="color: #dc143c;">sys</span>.<span style="color: black;">excepthook</span> = on_crash
&nbsp;
declencher_erreur = <span style="color: #ff4500;">1</span> + <span style="color: #483d8b;">&quot;1&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">## &lt;type 'exceptions.TypeError'&gt;</span>
<span style="color: #808080; font-style: italic;">## unsupported operand type(s) for +: 'int' and 'str'</span>
<span style="color: #808080; font-style: italic;">## &lt;traceback object at 0x00543AF8&gt;</span></pre></div></div>

<p>Ca peut être très intéressant pour débugger un processus détaché comme par exemple votre serveur WSGI qui fait tourner Django qui décide de se petit-suicider : demandez à <code>sys.excepthook</code> de faire un dump de l&#8217;exception dans un fichier log , et vous pourrez voir ce qui a propoqué la crise.</p>
<p>Si vous êtes du genre poli, vous voudrez quand même garder l&#8217;ancien comportement de <code>sys.excepthook</code>, qui est toujours disponible depuis <code>sys.__excepthook__</code> :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> on_crash<span style="color: black;">&#40;</span><span style="color: #008000;">type</span>, value, tb<span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># faire ce que vous voulez ici puis...</span>
    <span style="color: #dc143c;">sys</span>.__excepthook__<span style="color: black;">&#40;</span><span style="color: #008000;">type</span>, value, tb<span style="color: black;">&#41;</span></pre></div></div>

<p>Et dire que vous commenciez à croire que vous saviez presque tout sur Python. Mouarf.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5260&amp;md5=49b3bf3df1505a609545c25b33674881" 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=5267
title: Écrire des logs en Python
uri: Écrire-des-logs-en-Python
url: http://sametmax.com/ecrire-des-logs-en-python/
content:
<p>Good morning&#8230;</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="420" height="315" src="http://www.youtube.com/embed/IB7LsjkZvvc" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<p>Au lieu de mettre des <code>print()</code> partout qu&#8217;il va falloir retirer après et qui en plus ne servent à rien dans un processus daemonisé, utiliser les facilités de logging de Python peut se révéler un bon investissement. Investissement car le module <code>logging</code> est du même genre que <code>urllib2</code>, <code>datetime</code> ou <code>os.path</code> : on peut tout faire avec mais vaut mieux avoir la doc sous la main.</p>
<h2>Pour les gens pressés</h2>
<p>Avant de se lancer dans les explications, voici le snippet qui permet d&#8217;afficher les informations à l&#8217;écran et dans un fichier de log :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">logging</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">logging</span>.<span style="color: black;">handlers</span> <span style="color: #ff7700;font-weight:bold;">import</span> RotatingFileHandler
&nbsp;
<span style="color: #808080; font-style: italic;"># création de l'objet logger qui va nous servir à écrire dans les logs</span>
logger = <span style="color: #dc143c;">logging</span>.<span style="color: black;">getLogger</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># on met le niveau du logger à DEBUG, comme ça il écrit tout</span>
logger.<span style="color: black;">setLevel</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">logging</span>.<span style="color: black;">DEBUG</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># création d'un formateur qui va ajouter le temps, le niveau</span>
<span style="color: #808080; font-style: italic;"># de chaque message quand on écrira un message dans le log</span>
<span style="color: #dc143c;">formatter</span> = <span style="color: #dc143c;">logging</span>.<span style="color: black;">Formatter</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'%(asctime)s :: %(levelname)s :: %(message)s'</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># création d'un handler qui va rediriger une écriture du log vers</span>
<span style="color: #808080; font-style: italic;"># un fichier en mode 'append', avec 1 backup et une taille max de 1Mo</span>
file_handler = RotatingFileHandler<span style="color: black;">&#40;</span><span style="color: #483d8b;">'activity.log'</span>, <span style="color: #483d8b;">'a'</span>, <span style="color: #ff4500;">1000000</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># on lui met le niveau sur DEBUG, on lui dit qu'il doit utiliser le formateur</span>
<span style="color: #808080; font-style: italic;"># créé précédement et on ajoute ce handler au logger</span>
file_handler.<span style="color: black;">setLevel</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">logging</span>.<span style="color: black;">DEBUG</span><span style="color: black;">&#41;</span>
file_handler.<span style="color: black;">setFormatter</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">formatter</span><span style="color: black;">&#41;</span>
logger.<span style="color: black;">addHandler</span><span style="color: black;">&#40;</span>file_handler<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># création d'un second handler qui va rediriger chaque écriture de log</span>
<span style="color: #808080; font-style: italic;"># sur la console</span>
steam_handler = <span style="color: #dc143c;">logging</span>.<span style="color: black;">StreamHandler</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
steam_handler.<span style="color: black;">setLevel</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">logging</span>.<span style="color: black;">DEBUG</span><span style="color: black;">&#41;</span>
logger.<span style="color: black;">addHandler</span><span style="color: black;">&#40;</span>steam_handler<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Après 3 heures, on peut enfin logguer</span>
<span style="color: #808080; font-style: italic;"># Il est temps de spammer votre code avec des logs partout :</span>
logger.<span style="color: black;">info</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Hello'</span><span style="color: black;">&#41;</span>
logger.<span style="color: black;">warning</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Testing %s'</span>, <span style="color: #483d8b;">'foo'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Cette config va afficher :</p>
<pre>Hello
Tesing foo</pre>
<p>sur la console</p>
<p>Et :</p>
<pre>2013-03-08 11:37:31,311 :: INFO :: Hello
2013-03-08 11:37:31,411 :: WARNING :: Testing foo</pre>
<p>Dans le fichier de <em>activity.log</em>.</p>
<p>Quand vous passez en prod, mettez simplement une condition sur le stream handler, et le <code>setLevel</code> sur <code>logging.WARN</code> et vous êtes tranquile, quel que soit le nombre de <code>logger.info</code> que vous avez mis partout.</p>
<p>Mais bon, avouez le, si vous aviez dû le faire vous même, vous auriez abandonné avant de trouver. D&#8217;une manière générale, quand vous voyez des noms en camelCase comme <code>setLevel</code> dans une lib Python, c&#8217;est que la lib va être relou à utiliser.</p>
<p>Donc, faites comme moi, mettez cette config dans un fichier à part, et pour chaque nouveau projet, copier le bêtement. Comme ça vous aurez en une seconde la possibilité de logger dans un fichier et sur la console avec une désactivation facile.</p>
<h2>Un peu de théorie</h2>
<p>En Python, les logs se font à travers un logger. Le logger prend toute écriture que vous lui demandez, et regarde si le niveau de log est suffisamment haut pour continuer. Si non, il ignore l&#8217;entrée, si oui, il va passer le message à chaque handler.</p>
<p>Chaque handler fait le même test pour lui même : le niveau est il assez élevé pour moi ? Si non, il ne fait rien. Si oui, il écrit le log. La manière dont il écrit le log dépend du type du logger : le StreamHandler va écrire par défaut sur la console, le FileHandler dans un fichier, le SmtpHandler va envoyer un email, etc. Un logger peut avoir autant de handlers qu&#8217;il veut, et donc autant de type d&#8217;écritures qu&#8217;il veut.</p>
<p>Tout handler possède un formatter, qui est un objet qui décide dans quel format il va écrire la nouvelle entrée du log. Le formateur par défaut écrit juste le message, mais on peut lui demander (comme on l&#8217;a fait plus haut), d&#8217;écrire un timestamp, le niveau du message ou des choses plus complexes comme des éléments de la pile d&#8217;appel.</p>
<p>Vous avez suivi ? Allez, comme je suis sympa, je vous mets un dessin :</p>
<div id="attachment_5275" class="wp-caption aligncenter" style="width: 465px"><a href="media/7b7e9a4b.logging.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/03/logging.png"><img class=" wp-image-5275  " title="Si vous saviez combien de temps prennent ces schémas à la con à faire..." src="media/7b7e9a4b.logging.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/03/logging.png" alt="Schéma de l'organisation de la configuration d'un logger" width="455" height="644" /></a><p class="wp-caption-text">Si vous saviez combien de temps prennent ces schémas à la con à faire...</p></div>
<p>Bref, pour configurer un logger en Python :</p>
<ul>
<li>On créé un objet logger</li>
<li>On lui ajoute des handlers</li>
<li>On ajoute des formateurs aux handlers</li>
<li>On set les niveaux du loggers et des handlers</li>
</ul>
<p>Et enfin, on peut logger avec <code>logger.(info|warn|debug|error|critical)</code>.</p>
<p>Mais là vient s&#8217;intercaler un des plus grands mystères de l&#8217;histoire du logging : les niveaux. Personne ne se rappelle comme ça marche.</p>
<p>Si vous mettez un flingue sur la tête de quelqu&#8217;un et que vous lui donnez une dernière chance d&#8217;expliquer les niveaux de logging sinon vous le butez lui et toute sa famille, il se mettra à chouiner bêtement. Inutile de monter la pression en menaçant de profaner leurs tombes et violer leurs cadavres. Il ne sait tout simplement pas.</p>
<h2>Donc, un bonne fois pour toute, voilà comment les niveaux marchent</h2>
<table>
<tbody>
<tr>
<th>Niveau
</th>
<th>Valeur
</th>
<th>Usage
</th>
</tr>
<tr>
<td>CRITICAL</td>
<td>50
</td>
<td>Le programme complet est en train de partir en couille.
</td>
</tr>
<tr>
<td>ERROR</td>
<td>40
</td>
<td>Une opération a foirée.
</td>
</tr>
<tr>
<td>WARNING</td>
<td>30
</td>
<td>Pour avertir que quelque chose mérite l&#8217;attention : enclenchement d&#8217;un mode particulier, detection d&#8217;une situation rare, un lib optionelle peut être installée.
</td>
</tr>
<tr>
<td>INFO</td>
<td>20
</td>
<td>Pour informer de la marche du programme. Par exemple : &#8220;Starting CSV parsing&#8221;
</td>
</tr>
<tr>
<td>DEBUG</td>
<td>10
</td>
<td>Pour dumper des information quand vous débuggez. Par exemple savoir ce qu&#8217;il y a dans ce putain de dictionnaire.
</td>
</tr>
</tbody>
</table>
<p>Vous spécifiez les niveaux une fois quand vous créez vos loggers et handlers avec <code>setLevel</code>. Vous passez à cette méthode une des valeurs suivantes : <code>logging.DEBUG</code>, <code>logging.INFO</code>, <code>logging.WARNING</code>, etc. C&#8217;est la valeur minimal qu&#8217;ils acceptent.</p>
<p>Ensuite, à chaque écriture de message dans le logger, vous passez le niveau avec le message:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> logger.<span style="color: black;">log</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">logging</span>.<span style="color: black;">DEBUG</span>, <span style="color: #483d8b;">'Message !'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Comme c&#8217;est relou à taper, Python fournit des raccourcis :</p>
<p><code>logger.debug('message')</code> va faire <code>logger.log(logging.DEBUG, 'message')</code></p>
<p><code>logger.error('message')</code> va faire <code>logger.log(logging.ERROR, 'message')</code></p>
<p>Etc</p>
<p>A chaque fois que vous allez envoyer un message, le logger (et chaque handler) va comparer le niveau du message avec le sien. Si le niveau du message est inférieur au sien, il l&#8217;ignore, sinon il l&#8217;écrit.</p>
<p>Exemple :</p>
<pre>CRITICAL
ERROR
WARNING <- niveau du logger (ou du handler)
INFO    <- niveau du message
DEBUG
</pre>
<p>Le message est ignoré.</p>
<pre>
CRITICAL
ERROR   <- niveau du message
WARNING <- niveau du logger (ou du handler)
INFO
DEBUG</pre>
<p>Le message est écrit.</p>
<pre>CRITICAL
ERROR   <- niveau du message et du logger
WARNING
INFO
DEBUG
</pre>
<p>Le message est écrit.</p>
<p>Ce mécanisme permet de controler la sortie de votre programme. Si vous passez le programme en prod, vous avez sans doute plus envie de tous les messages d'information et de debug. Vous mettez alors le level sur, par exemple, ERROR, et vous aurez un log avec uniquement les erreurs.</p>
<p>Cette techique permet un gros niveau de granularité puisque non seulement le logger à un level, mais aussi chaque handler.</p>
<p>Exemple : vous avez un logger avec deux handlers, un qui va vers la console, et l'autre dans un fichier.</p>
<pre>CRITICAL
ERROR
WARNING  <- niveau du handler fichier
INFO    <- niveau du logger et du handler console
DEBUG
</pre>
<p>Si un message arrive avec un niveau DEBUG, il est ignoré. Si il arrive avec un niveau INFO, il est affiché sur la console. Si il arrive avec un niveau WARNING ou plus, il est affiché sur la console ET mis dans le fichier.</p>
<h2>Des combos de ouf</h2>
<p>Rappelez-vous qu'on peut avoir autant de handlers qu'on veut, et même plusieurs handlers de même nature tels que deux handlers fichiers. Le premier peut par exemple logger les infos, et l'autre juste les erreurs.</p>
<p>Vous pouvez même créez vos propres niveaux (<code>logging.CAMERDEGRAVE</code>) et vos propres handlers. Un handler qui appelle une URL quand il y a une erreur, un handler qui met tout le debug en coloration syntaxique, un handler qui envoit un SMS en cas de critical, etc.</p>
<p>Les handlers disponibles dans la lib standard sont :</p>
<ul>
<li><strong>FileHandler</strong>: écrit tout dans un fichier.</li>
<li><strong>RotatingFileHandler</strong>: écrit tout dans un fichier. Si le fichier depasse une certaine taile, renomme le fichier avec un compter, et recommence avec un nouveau fichier. Le nombre de backup est configurable.</li>
<li><strong>TimedRotatingFileHandler</strong>: écrit tout dans un fichier. Après un certain temps, renomme le fichier avec un compter, et recommence avec un nouveau fichier. Le nombre de backup est configurable.</li>
<li><strong>WatchedFileHandler</strong>: écrit dans un fichier, mais surveille si il n'a pas été modifié entre temps. Ne marche pas sous Windows</li>
<li><strong>HTTPHandler</strong>: envoit le contenu par POST ou GET à l'URL donnée.</li>
<li><strong>SMTPHandler</strong>: envoit le contenu par email.</li>
<li><strong>MemoryHandler</strong>: garde tout en mémoire jusqu'à un certain temps, puis balance tout à un autre handler. Utile avec SMTPHandler.</li>
<li><strong>BufferingHandler</strong>: accumule tout en mémoire, et vide régulièrement le buffer. Utile pour l'instrospection.</li>
<li><strong>NTEventLogHandler</strong>: envoit les entrées sur le event log de Windows NT.</li>
<li><strong>SysLogHandler</strong>: envoit les entrées sur un serveur syslog.</li>
<li><strong>SocketHandler</strong>: envoit les entrées (picklées) via une socket.</li>
<li><strong>DatagramHandler</strong>: envoit les entrées sur une socket datagram.</li>
</ul>
<h2>Traiter le fichier de log</h2>
<p>90% du temps, vous voudrez juste un bon vieux fichier de log. Mais rien ne sert d'avoir un fichier de log si on ne peut pas le lire.</p>
<p>D'abord, choisissez le bon endroit pour le mettre. Si c'est juste du debug, le dossier courant fera l'affaire. Si vous pensez qu'il va rester longtemps mais qu'il faudra le vider de temps à autre (et qu'il ne contient pas des informations qui ne doivent être lues que par root), alors mettez le dans un fichier temporaire. Le module <a href="http://docs.python.org/2/library/tempfile.html?highlight=tempfile#tempfile">tempfile</a> est votre ami.</p>
<p>Sinon, pour les logs plus sérieux, il faudra le mettre dans le dossier officiel pour les logs du systèmes. Par exemple pour Ubuntu server : <em>/var/log</em>.</p>
<p>Attention aux permissions d'écriture, vous risquez de vous retrouver avec une erreur à la con sur les bras. Vérifiez bien vos droits d'accès.</p>
<p>Ensuite, il faut bien choisir son format de log. Sauf cas particulier, j'utilise ce formatteur :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #dc143c;">formatter</span> = <span style="color: #dc143c;">logging</span>.<span style="color: black;">Formatter</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'%(asctime)s :: %(levelname)s :: %(message)s'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Il produit des sorties du genre "TIMESTAMP :: LEVEL :: Message", par exemple :</p>
<pre>
2012-03-08 12:01:31,311 :: INFO :: My life for Aiur
2012-03-08 12:20:31,311 :: ERROR :: We require more Vespin Gaz
2012-03-08 12:37:31,311 :: WARNING :: We are under attack
2012-03-08 12:38:31,311 :: CRITICAL :: Nuclear launch detected
</pre>
<p>Ce format est facile à analyser car le séparateur a peu de risque de se retrouver dans le message.</p>
<p>On peut très rapidement filtrer uniquement les erreurs, par exemple sous bash on peut voir si il y a eu récement des erreurs ainsi :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">tail</span> <span style="color: #660033;">-n</span> <span style="color: #000000;">100</span> fichier.log <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> ERROR</pre></div></div>

<p>Sous Python on peut faire des traitements super chiadés en deux secondes :</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;">datetime</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">datetime</span>
&nbsp;
lines = <span style="color: black;">&#40;</span>ligne.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">' :: '</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> ligne <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'fichier.log'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
errors = <span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>date, mes<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> date, lvl, mes <span style="color: #ff7700;font-weight:bold;">in</span> lines <span style="color: #ff7700;font-weight:bold;">if</span> lvl <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'ERROR'</span>, <span style="color: #483d8b;">'CRITICAL'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
before, after = <span style="color: #dc143c;">datetime</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2012</span>, <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">12</span><span style="color: black;">&#41;</span>, <span style="color: #dc143c;">datetime</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2012</span>, <span style="color: #ff4500;">3</span>, <span style="color: #ff4500;">24</span><span style="color: black;">&#41;</span>
parse = <span style="color: #ff7700;font-weight:bold;">lambda</span> d: <span style="color: #dc143c;">datetime</span>.<span style="color: black;">strptime</span><span style="color: black;">&#40;</span>d, <span style="color: #483d8b;">'%Y-%m-%d %H:%M:%S,%f'</span><span style="color: black;">&#41;</span>
dated_line = <span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>date, mes<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> date, mess <span style="color: #ff7700;font-weight:bold;">in</span> errors <span style="color: #ff7700;font-weight:bold;">if</span> before <span style="color: #66cc66;">&lt;</span>= parse<span style="color: black;">&#40;</span>date<span style="color: black;">&#41;</span> <span style="color: #66cc66;">&lt;</span>= after<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> date, message <span style="color: #ff7700;font-weight:bold;">in</span> dated_line:
    <span style="color: #ff7700;font-weight:bold;">print</span> date, message
&nbsp;
<span style="color: #808080; font-style: italic;"># Affiche uniquement les message d'erreur ou criques qui sont arrivés entre</span>
<span style="color: #808080; font-style: italic;">#  le 12 janviers 2012 et le 24 mars 2012</span></pre></div></div>

<p>Et je ne vous parle même pas de ce qu'on peut faire avec des libs comme <a href="http://pandas.pydata.org/">pandas</a>.</p>
<h2>Aller plus loin</h2>
<p>Le log peut vous emener très loin. En vérité, non seulement on peut avoir plusieurs handlers, mais on peut aussi avoir plusieurs loggers.</p>
<p>Quand vous faites:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">logger = <span style="color: #dc143c;">logging</span>.<span style="color: black;">getLogger</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Vous récupérez ce qu'on appelle le logger "racine" (ou "root"). Mais vous pouvez aussi donner un nom au logger :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">logger = <span style="color: #dc143c;">logging</span>.<span style="color: black;">getLogger</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'encoding'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Ceci vous permet de préconfigurer le logger quelque part dans le programme, et de récupérer celui-ci en particulier à un autre endroit, sans se trimbaler la référence. <code>logging.getLogger('encoding')</code> n'a besoin d'être configuré qu'une fois, si vous refaites ça ailleurs, vous récupérez le même logger.</p>
<p>On peut même utiliser des sous-noms:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">enc_aud_logger = <span style="color: #dc143c;">logging</span>.<span style="color: black;">getLogger</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'encoding.audio'</span><span style="color: black;">&#41;</span>
enc_vid_logger = <span style="color: #dc143c;">logging</span>.<span style="color: black;">getLogger</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'encoding.video'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Alors chaque logger aura sa propre config, MAIS, tout message envoyé sur un logger nommé "encoding.quelquechose" sera aussi automatiquement envoyé au logger "encoding" si il existe.</p>
<p>Vous pouvez donc créer une hierarchie de log, par exemple pour avoir un fichier par process, et un gros log central sur un serveur à part via socket. Ca ne m'a jamais servi, mais je me suis dit que je ferai circuler l'info.</p>
<p>Je n'ai pas parlé des filters, qui sont des objets qui permettent de faire la même chose que les niveaux, mais avec des règles d'écriture dans les logs plus avancées que juste "c'est le bon niveau". Et je n'ai pas abordé non plus les formateurs particuliers. Là on rentre dans le domaine de la drosophilie.</p>
<p>En revanche si vous avez le temps, je vous conseille de passer quelque temps sur les options de configuration (plein de recettes <a href="http://docs.python.org/2/howto/logging-cookbook.html">ici</a>). En effet, en général on veut avoir un log configurable (c'est un peu le but de la manœuvre, sinon on ferait des print). Or, le logger peut se configurer de plein d'autres façons qu'avec du code Python.</p>
<p>On peut notamment déclarer la configuration avec un <a href="http://docs.python.org/2/howto/logging-cookbook.html#an-example-dictionary-based-configuration">gros dictionaire</a> (c'est ce que fait <a href="https://docs.djangoproject.com/en/dev/topics/logging/">Django</a>) ou avec un <a href="http://docs.python.org/2/library/logging.config.html#configuration-file-format">fichier ini</a>.</p>
<p>Enfin, normalement ce package est thread-safe. Vous devriez pouvoir logger en toute impunité dans plusieurs threads. Je recommande quand même de faire la configuration du logger avant d'entrer dans un thread, on ne sait jamais.</p>
<p>Pour ceux qui veulent se plonger dans les méandres de tout ce qu'on peut faire avec logging, chechez <a href="http://docs.python.org/2/library/logging.html?highlight=logging#logging">la doc</a> et <a href="http://www.red-dove.com/python_logging.html">cet article</a> de l'auteur du module.</p>
<hr />
<p><a href="https://github.com/sametmax/codes-des-articles/blob/master/2013/mars/tuto_logging.py">Télécharger le code de l'article</a></p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5267&amp;md5=4eb18cc58eb37029c661260604e986ce" 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=5295
title: Et le Bitcoin est toujours là
uri: Et-le-Bitcoin-est-toujours-là
url: http://sametmax.com/et-le-bitcoin-est-toujours-la/
content:
<p>Vu l&#8217;instabilité du projet, rien n&#8217;était moins sûr, mais la monnaie virtuelle continue son petit bonhomme de chemin.</p>
<p>En fait <a href="http://sametmax.com/quest-ce-que-bitcoin/">la dernière fois que j&#8217;en ai parlé</a>, le BTC valait $9. Ensuite il s&#8217;était crashé à $3. En ce moment, il y a une sorte de bulle, comme en début d&#8217;année dernière, et il est à $45. Ce qui fait que si je revend quelques pourcent de mes BTC, je rembourse tout ceux que j&#8217;ai acheté.</p>
<p>Évidement cet article n&#8217;est pas une invitation à la spéculation sur le Bitcoin, mais plutôt l&#8217;expression de ma joie que cette bizarrerie soit allée aussi loin. Qui l&#8217;eut cru ? Déjà moi, quand Wikipedia est sortie, j&#8217;ai dis que ça marcherait jamais&#8230;</p>
<p>Bref, ça fait plus d&#8217;un an que j&#8217;utilise Bitcoin maintenant, et voici les quelques points à noter :</p>
<ul>
<li>Pour les curieux, voici un <a href="http://www.bitcoinrate.com/en/">site avec des taux de change</a> à peu prêt à jour. Rappelez-vous juste que ça peut changer du tout au tout du jour au lendemain. Bitcoin n&#8217;est PAS stable. Bitcoin n&#8217;est PAS sûr.</li>
<li>Achat et revente sur <a href="http://bitmarket.eu/">Bitmarket.eu</a>. C&#8217;est facile. C&#8217;est pratique. Pas de problème de vol pour le moment. (Par contre le site est down aujourd&#8217;hui :().</li>
<li>En combinant l&#8217;hébergeur <a href="http://www.cinfu.com/">cinfu</a>, le registrar <a href="https://www.namecheap.com/">namecheap</a>, et quelques <a href="http://torrentfreak.com/vpn-services-that-take-your-anonymity-seriously-2013-edition-130302/">VPN sérieux</a>, on se retrouve avec une chaîne complètement anonyme pour gérer un service Web, payé en bitcoins.</li>
<li><a href="https://localbitcoins.com/">LocalBitcoin</a> est un annuaire qui permet d&#8217;acheter et de vendre des BTC de main à la main. Il utilise un système de réseau de confiance appelé <a href="bitcoin-otc.com">bitcoin-otc</a> basé sur IRC et GPG. Pratique, mais pas très user friendly.</li>
<li>Cette semaine je l&#8217;ai utilisé pour qu&#8217;un ami aux US me rembourse un coli que je lui ai envoyé. Rapide. Pratique. Il a fait une affaire vu le taux de change.</li>
<li>Le <a href="http://code.google.com/p/bitcoin-wallet/">wallet android</a> marche très bien. Quand on voit la pression pour imposer NFC qui est une sombre bouse, je me dis qu&#8217;il faut vraiment travailler sur les alternatives.</li>
<li><a href="https://github.com/kangasbros/django-bitcoin">django-bitcoin</a> permet l&#8217;intégration de Bitcoin à son site (tellement qu&#8217;on peut créer son site de trading avec).</li>
<li>accepter Bitcoin sur son site de vente en ligne peut maintenant se faire à travers un simple plus sur un des <a href="https://en.bitcoin.it/wiki/Category%3aShopping_Cart_Interfaces">nombreux</a> <a href="http://acceptbit.com/">services</a> disponibles. Plus besoin de coder.</li>
<li>Pour les amoureux du code, il y a quand même un implémentation pédagogique (et super lente) d&#8217;un <a href="https://github.com/jgarzik/pyminer">mineur en Python</a> et une API pour écrire son <a href="https://en.bitcoin.it/wiki/Bitcoin-python">Wallet en Python</a>.</li>
<li>Il y a un tas, mais alors un tas, de services morts nés. On sent que tout ça est très jeune.</li>
</ul>
<p>Certes, on est encore loin de faire ses courses avec. Ce n&#8217;est toujours mamy-proof. On ne peut <a href="http://www.digitaltrends.com/web/virtual-bitcoins-can-now-be-traded-for-dominos-pizza/">acheter ses pizza en bitcoins</a> qu&#8217;aux USA et l&#8217;<a href="http://www.btc4amazon.com/">achat sur Amazon et Ebay</a> est toujours un truc à base de 3rd party. Mais l&#8217;expérience continue. C&#8217;est beau. C&#8217;est fun.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5295&amp;md5=5c82dd346c65a196dbe059dc4b326e7b" 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=5301
title: De débutant à débutant
uri: De-débutant-à-débutant
url: http://sametmax.com/de-debutant-a-debutant/
content:
<p>Quand j&#8217;ai commencé le guide sur <a href=" 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 1.">la POO pour débutant</a>, j&#8217;ai eu des demandes de faire les choses plus simplement, de retirer des prérequis ou encore des remarques que celui-ci n&#8217;était pas débutant malgré le titre.</p>
<p>Si vous preniez un cours &#8220;Triple saut périlleux pour débutant&#8221; en gymnastique, je pense que vous auriez compris que :</p>
<ul>
<li>Il s&#8217;agit de débutant en triple saut périlleux, pas en gymnastique.</li>
<li>On ne se lance pas dans l&#8217;apprentissage du triple avant de savoir le double. Encore moins avant de savoir faire la roue.</li>
<li>Si l&#8217;enseignant vous parle d&#8217;une posture d&#8217;étirement à l&#8217;échauffement dont vous ne connaissez pas le nom, vous commenceriez par vous dire que peut-être vous n&#8217;avez pas encore le niveau pour apprendre ce saut périlleux.</li>
</ul>
<p>Et on en vient à un problème fondamental d&#8217;Internet : comme tout le monde à accès à tout, les gens sont tenus d&#8217;avoir du bon sens.</p>
<p>En l’occurrence, on ne se lance pas dans un guide sur la POO avant de savoir faire du scripting de base.</p>
<p>Mais ce guide n&#8217;est qu&#8217;un exemple. Régulièrement, dans mon métier de formateur, et dans ma vie en générale, je croise des gens qui sont frustrés que telle ou telle chose soit &#8216;aussi compliquée&#8217; en programmation.</p>
<h2><strong>1 &#8211; Ce n&#8217;est pas compliqué</strong></h2>
<p>L&#8217;immense majorité des choses n&#8217;est pas compliquée en programmation. Si vous ne comprenez pas, c&#8217;est probablement soit mal expliqué, soit ça demande des connaissances que vous n&#8217;avez pas. Ce qui vous manque, ce n&#8217;est pas des neurones, c&#8217;est du temps et de la pratique. Même des concepts abstraits tels que les metaclasses sont explicables facilement.</p>
<p>Une chose que j&#8217;ai noté, c&#8217;est que beaucoup de personnes en chient parce qu&#8217;ils ne savent pas dans quel ordre il faut apprendre les choses. Ou alors ils savent mais sont impatients et sautent des étapes.</p>
<h2><strong>2 &#8211; Si vous êtes un être humain normal, ça prend 10 ans</strong></h2>
<p>Vous avez entre les mains une machine qui fait des milliards d&#8217;opérations à la seconde, composée de milliers de pièces matérielles et de millions de pièces logicielles qui interagissent entre elles de manière complexe. Par dessus ça vous avez des outils d&#8217;abstractions, en premier lieu un langage de programmation, pour lui faire faire quelque chose.</p>
<p>Forcément, ça prend du temps à maîtriser.</p>
<p>L&#8217;informatique est une science très très jeune. La médecine, les maths, l&#8217;architecture ou la chimie sont des trucs qu&#8217;on pratique depuis des millénaires. On a des ordinateurs depuis moins d&#8217;un siècle. Tout ça n&#8217;a pas suffisamment évolué pour qu&#8217;il suffise de pousser un bouton pour créer un logiciel. On y arrivera peut être, mais pour le moment, il faut comprendre ce qu&#8217;on fait.</p>
<p>Et comprendre quelque chose de complexe n&#8217;est PAS FORCÉMENT compliqué. Mais ça prend du temps. Comptez une décennie pour être un programmeur averti.</p>
<p>Rappelez-vous qu&#8217;un expert, c&#8217;est uniquement quelqu&#8217;un qui a fait toutes les erreurs possibles dans un champ donné.</p>
<h2><strong>3 &#8211; Ça ne veut pas dire qu&#8217;en deux semaines vous ne pouvez pas faire quelque chose</strong></h2>
<p>Vous n&#8217;avez pas besoin d&#8217;être un professionnel en informatique pour coder. C&#8217;est la beauté de la chose : les amateurs sont les bienvenus dans notre univers, justement parce que c&#8217;est un domaine encore juvénile.</p>
<p>Vous pouvez faire des bidouillages amusants et même des choses utiles en très peu de temps.</p>
<p>Mais NON, vous ne pouvez pas tout maîtriser. Tout comprendre. Ce n&#8217;est pas possible.</p>
<p>Il ne faut pas vous en sentir frustré. Le cerveau humain a ses limites. La pédagogie a ses limites. Les journées n&#8217;ont que 24H, et on en passe une bonne partie au lit, à table, sur les chiottes et parfois même au boulot.</p>
<p>Et puis, j&#8217;ai une confession : je suis un débutant moi aussi.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5301&amp;md5=fb73176fd770c445a01c04d5297e9115" 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=5368
title: Se déplacer devient de plus en plus périlleux
uri: Se-déplacer-devient-de-plus-en-plus-périlleux
url: http://sametmax.com/se-deplacer-devient-de-plus-en-plus-perilleux/
content:
<p>Une pensée bête qui m&#8217;a traversée la tête.</p>
<ul>
<li>à pied on ne craignait que les brigands.</li>
<li>à cheval on risquait juste de tomber.</li>
<li>en bateau on risquait de se noyer mais la chute ne signifiait pas forcement la mort.</li>
<li>en voiture on a le plus fort taux de mortalité qui existe de tous les moyens de transports.</li>
<li>en avion on a aucun contrôle sur notre destin en cas d&#8217;accident.</li>
<li>dans l&#8217;espace, bientôt, un accident signifiera toujours la mort.</li>
</ul>
<p>C&#8217;est amusant, c&#8217;est comme si avancer devenait un défi de plus en plus difficile pour l&#8217;humanité, un pallier progressif à la hauteur de son évolution.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5368&amp;md5=7c1dfd2153d2af290e7509fc374236d8" 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=5387
title: Pardon aux familles, tout ça
uri: Pardon-aux-familles-tout-ça
url: http://sametmax.com/pardon-aux-familles-tout-ca/
content:
<p>Voulant faire de la place pour la blockchain de Bitcoin qui prend 6Go (la salope), j&#8217;ai fais du tri dans les emails.</p>
<p>Par tri j&#8217;entends que j&#8217;ai accidentellement effacé tous les mails de la boîte aux lettre de Sam Et Max. L&#8217;IMAP est taquin.</p>
<p>Donc, à tous ceux qui nous ont écrit dernièrement, renvoyez-les nous, car on ne peut pas vous répondre.</p>
<p>Désolé. C&#8217;est not&#8217; fot&#8217;. Nan. C&#8217;est MA faute.</p>
<p>Je pense particulièrement aux mails de questions et le très gentil mail disant qu&#8217;on était trop cool mais que le tableau des niveaux de log était pas dans le bon ordre.</p>
<p>Ce que je n&#8217;ai pas compris d&#8217;ailleurs car :</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;">logging</span>.<span style="color: black;">DEBUG</span>
<span style="color: #ff4500;">10</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">logging</span>.<span style="color: black;">INFO</span>
<span style="color: #ff4500;">20</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">logging</span>.<span style="color: black;">WARNING</span>
<span style="color: #ff4500;">30</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">logging</span>.<span style="color: black;">ERROR</span>
<span style="color: #ff4500;">40</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">logging</span>.<span style="color: black;">CRITICAL</span>
<span style="color: #ff4500;">50</span></pre></div></div>

<p>Bref, tout ça pour dire que ce n&#8217;est pas qu&#8217;on veut pas vous répondre, c&#8217;est qu&#8217;on peut pas. Renvoyez tout !</p>
<div id="attachment_5389" class="wp-caption aligncenter" style="width: 330px"><a href="media/1f51b190.x1gzuBb.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/03/x1gzuBb.gif"><img class="size-full wp-image-5389" title="Et il fonce vers un disque dur avec plus de place et un monde moins de souci. Il s'approche. Il sauuuuuuuuuuuuuuuuute !" src="media/1f51b190.x1gzuBb.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/03/x1gzuBb.gif" alt="Gif animé d'un enfant qui saute dans une piscine et la rate" width="320" height="240" /></a><p class="wp-caption-text">Et il fonce vers un disque dur avec plus de place et un monde moins de souci. Il s&#39;approche. Il sauuuuuuuuuuuuuuuuute !</p></div>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5387&amp;md5=79974e11820d7aa44a35560816b02c25" 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=5313
uri: Envoi-d-un-email-par-logging-en-cas-de-plantage-d-un-script-python
title:
Envoi d’un email par logging en cas de plantage d’un script python (ou: comment faire bouffer u”\xe9″ à SMTPHandler)

url:
http://sametmax.com/envoi-dun-email-par-logging-en-cas-de-plantage-dun-script-python-ou-comment-faire-bouffer-uxe9-a-smtphandler/

content:
<p><em>(Ceci est un post invité d&#8217;un débutant pour les débutants&#8230; sous licence <a href="http://creativecommons.org/licenses/by/3.0/">creative common 3.0 unported</a>.)</em></p>
<p>Il y a peu, je me suis mis à utiliser <code>logging</code> pour debugger mes scripts de débutant.</p>
<p>Si comme moi vous avez l&#8217;habitude de mettre des <code>print</code> partout pour trouver l&#8217;origine d&#8217;un problème, et qu&#8217;ensuite vous avez passé de longues longues longues minutes/heures à traquer ces foutus <code>print</code> pour dépolluer la sortie console, jetez un oeil à <a href="http://sametmax.com/ecrire-des-logs-en-python/">écrire des logs en python</a>.</p>
<p>Après quelques (minutes/heures/jours) de prise en main (vite, quoi&#8230;), on se demande comment on a fait pour s&#8217;en passer si longtemps. C&#8217;est simple, je n&#8217;utilise plus les touches &#8220;p&#8221;, &#8220;r&#8221;, &#8220;i&#8221;, &#8220;n&#8221; et &#8220;t&#8221; de mon clavier. Elles sont toutes propres.</p>
<p>En plus, <code>logging</code> m&#8217;a ouvert de nouvelles perspectives, parmi lesquelles la possibilité d&#8217;envoyer les logs par mail. Pas besoin de tout recevoir par mail, mais si ce foutu script de m%@rde pouvait m&#8217;envoyer un email quand il plante avec la source détaillé du problème, ce serait super.</p>
<h2>Log post mortem par email</h2>
<p>Admettons que vous vouliez vérifier que les pensées qui vous traversent l&#8217;esprit sont safe for work. Vous écrivez un script génial qui fait le boulot.</p>
<p>Comme vous commencez à savoir y faire en python, vous avez même écrit votre propre exception à vous tout seul&#8230;</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> NotSafeForWorkError<span style="color: black;">&#40;</span><span style="color: #008000;">Exception</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
    Exception soulevée si une pensée est NSFW
    &quot;&quot;&quot;</span>
    <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>, msg<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">msg</span> = u<span style="color: #483d8b;">&quot;Danger! %s est NSFW.&quot;</span> <span style="color: #66cc66;">%</span> msg
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__str__</span><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>.<span style="color: black;">msg</span>.<span style="color: black;">encode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;utf-8&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># liste des pensées proscrites</span>
<span style="color: #808080; font-style: italic;"># (échantillon, elle est beaucoup plus longue que ça en réalité)</span>
NSFW = <span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;cul&quot;</span>, <span style="color: #483d8b;">&quot;seins&quot;</span>, <span style="color: #483d8b;">&quot;sametmax&quot;</span><span style="color: black;">&#93;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># boucle de censure qui soulève une exception si une pensée déconne</span>
<span style="color: #ff7700;font-weight:bold;">for</span> pensee <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;pause&quot;</span>, <span style="color: #483d8b;">&quot;pipi&quot;</span>, <span style="color: #483d8b;">&quot;sametmax&quot;</span><span style="color: black;">&#93;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> pensee <span style="color: #ff7700;font-weight:bold;">in</span> NSFW:
        <span style="color: #ff7700;font-weight:bold;">raise</span> NotSafeForWorkError<span style="color: black;">&#40;</span>pensee<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> u<span style="color: #483d8b;">&quot;%s est SFW&quot;</span> <span style="color: #66cc66;">%</span> pensee
&nbsp;
<span style="color: #808080; font-style: italic;">#sortie:</span>
<span style="color: #808080; font-style: italic;">## pause est SFW</span>
<span style="color: #808080; font-style: italic;">## pipi est SFW</span>
<span style="color: #808080; font-style: italic;">## Traceback (most recent call last):</span>
<span style="color: #808080; font-style: italic;">##   File &quot;censure_setm3.py&quot;, line 30, in</span>
<span style="color: #808080; font-style: italic;">##     raise NotSafeForWorkError(pensee)</span>
<span style="color: #808080; font-style: italic;">## __main__.NotSafeForWorkError: Danger! sametmax est NSFW.</span></pre></div></div>

<p>Ça marche du tonnerre! C&#8217;est là que vous vous dites que ce serait bien si le script envoyait le traceback par email à votre psy pour le prévenir que vous avez déconné.</p>
<p>A la maison, vous avez lu l&#8217;article de Sam sur les <a href="http://sametmax.com/log-post-mortem-avec-python/">logs post mortem</a>. Ça a l&#8217;air facile à faire.</p>
<p>Vous créez d&#8217;abord un logger qui enverra les logs de niveau critique par mail:</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;">logging</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">logging</span>.<span style="color: black;">handlers</span> <span style="color: #ff7700;font-weight:bold;">import</span> SMTPHandler
&nbsp;
nom_loggeur = <span style="color: #483d8b;">&quot;test_nsfw&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On crée un logger et on met le niveau à critique:</span>
<span style="color: #808080; font-style: italic;">#  il ne tiendra compte que des logs de ce niveau</span>
logger = <span style="color: #dc143c;">logging</span>.<span style="color: black;">getLogger</span><span style="color: black;">&#40;</span>nom_loggeur<span style="color: black;">&#41;</span>
logger.<span style="color: black;">setLevel</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">logging</span>.<span style="color: black;">CRITICAL</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On crée le handler en lui passant les paramètres</span>
<span style="color: #808080; font-style: italic;">#  nécessaires à l'envoi d'un email</span>
mail_handler = SMTPHandler<span style="color: black;">&#40;</span>
    <span style="color: #808080; font-style: italic;"># Host et port</span>
    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'SMTP.GMAIL.COM'</span>, <span style="color: #ff4500;">587</span><span style="color: black;">&#41;</span>,
    <span style="color: #808080; font-style: italic;"># From</span>
    <span style="color: #483d8b;">&quot;MOI@GMAIL.COM&quot;</span>,
    <span style="color: #808080; font-style: italic;"># To (liste)</span>
    <span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;QUELQU.UN@QUELQUE.PART&quot;</span><span style="color: black;">&#93;</span>,
    <span style="color: #808080; font-style: italic;"># Sujet du message</span>
    <span style="color: #483d8b;">&quot;Erreur critique dans %s&quot;</span> <span style="color: #66cc66;">%</span> nom_loggeur,
    <span style="color: #808080; font-style: italic;"># pour l'authentification</span>
    credentials = <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;MONEMAIL@GMAIL.COM&quot;</span>, <span style="color: #483d8b;">&quot;MONSUPERPASSWORD&quot;</span><span style="color: black;">&#41;</span>,
    secure = <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 met le handler à &quot;critique&quot;.</span>
<span style="color: #808080; font-style: italic;"># Il enverra donc par mail les messages de ce niveau</span>
mail_handler.<span style="color: black;">setLevel</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">logging</span>.<span style="color: black;">CRITICAL</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On définit un formatter: date, nom du logger, niveau, message</span>
<span style="color: #dc143c;">formatter</span> = <span style="color: #dc143c;">logging</span>.<span style="color: black;">Formatter</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'%(asctime)s - %(name)s - %(levelname)s - %(message)s'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On associe le formatter au handler:</span>
<span style="color: #808080; font-style: italic;">#  c'est lui qui formatera les logs de ce handler</span>
mail_handler.<span style="color: black;">setFormatter</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">formatter</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># ... et on associe le handler au logger:</span>
<span style="color: #808080; font-style: italic;">#  il utilisera ce handler, qui émettra les logs critiques</span>
logger.<span style="color: black;">addHandler</span><span style="color: black;">&#40;</span>mail_handler<span style="color: black;">&#41;</span></pre></div></div>

<p>Ensuite vous redéfinissez sys.excepthook de manière à ce que l&#8217;exception soit logguée. La fonction convertit le traceback en string, la loggue au niveau critique et laisse l&#8217;exception continuer son chemin.</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;">sys</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># la fonction qui remplacera sys.excepthook</span>
<span style="color: #ff7700;font-weight:bold;">def</span> en_cas_de_plantage<span style="color: black;">&#40;</span>type_except, value, tb<span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;"># Traceback permettra de formater l'exception.</span>
    <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">traceback</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Mise en forme de l'exception. Retourne la trace</span>
    <span style="color: #808080; font-style: italic;">#  sous forme de str avec numéros de lignes et tout</span>
    trace = <span style="color: #483d8b;">&quot;&quot;</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">traceback</span>.<span style="color: black;">format_exception</span><span style="color: black;">&#40;</span>type_except, value, tb<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># On loggue l'exception au niveau &quot;critique&quot;,</span>
    <span style="color: #808080; font-style: italic;">#  elle sera donc envoyée par email</span>
    logger.<span style="color: black;">critical</span><span style="color: black;">&#40;</span>u<span style="color: #483d8b;">&quot;Erreur inattendue:<span style="color: #000099; font-weight: bold;">\n</span>%s&quot;</span>, trace<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># ... et on laisse le script se planter...</span>
    <span style="color: #dc143c;">sys</span>.__excepthook__<span style="color: black;">&#40;</span>type_except, value, tb<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># on remplace sys.excepthook, et le tour est joué</span>
    <span style="color: #dc143c;">sys</span>.<span style="color: black;">excepthook</span> = en_cas_de_plantage</pre></div></div>

<p>Et voilà. Vous lancez le script, il se casse la gueule dès qu&#8217;il rencontre &#8220;sametmax&#8221;, votre psy reçoit un email avec le traceback, c&#8217;est cool.</p>
<p>Sauf que&#8230;</p>
<h2>SMTPHandler ne gère pas unicode</h2>
<p>Si au moment de la création de mail_handler, vous passez comme sujet à SMTPHandler:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">u<span style="color: #483d8b;">&quot;%s s'est planté&quot;</span> <span style="color: #66cc66;">%</span> nom_loggeur</pre></div></div>

<p>ou que dans votre fonction &#8220;en_cas_de_plantage&#8221; vous mettez:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">logger.<span style="color: black;">critical</span><span style="color: black;">&#40;</span>u<span style="color: #483d8b;">&quot;Bébé a encore glissé dans son caca:<span style="color: #000099; font-weight: bold;">\n</span>%s&quot;</span>, trace<span style="color: black;">&#41;</span></pre></div></div>

<p>&#8230; autrement dit si vous avez une chaîne unicode qui ne peut pas être encodée en ascii, ça va pas marcher:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;envoie_mail_on_crash.py&quot;</span>, line <span style="color: #ff4500;">84</span>, <span style="color: #ff7700;font-weight:bold;">in</span> emit
    smtp.<span style="color: black;">sendmail</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">fromaddr</span>, <span style="color: #008000;">self</span>.<span style="color: black;">toaddrs</span>, msg<span style="color: black;">&#41;</span>
  File <span style="color: #483d8b;">&quot;/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/smtplib.py&quot;</span>, line <span style="color: #ff4500;">734</span>, <span style="color: #ff7700;font-weight:bold;">in</span> sendmail
    <span style="color: black;">&#40;</span><span style="color: #dc143c;">code</span>, resp<span style="color: black;">&#41;</span> = <span style="color: #008000;">self</span>.<span style="color: black;">data</span><span style="color: black;">&#40;</span>msg<span style="color: black;">&#41;</span>
  File <span style="color: #483d8b;">&quot;/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/smtplib.py&quot;</span>, line <span style="color: #ff4500;">501</span>, <span style="color: #ff7700;font-weight:bold;">in</span> data
    <span style="color: #008000;">self</span>.<span style="color: black;">send</span><span style="color: black;">&#40;</span>q<span style="color: black;">&#41;</span>
  File <span style="color: #483d8b;">&quot;/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/smtplib.py&quot;</span>, line <span style="color: #ff4500;">321</span>, <span style="color: #ff7700;font-weight:bold;">in</span> send
    <span style="color: #008000;">self</span>.<span style="color: black;">sock</span>.<span style="color: black;">sendall</span><span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#41;</span>
  File <span style="color: #483d8b;">&quot;/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ssl.py&quot;</span>, line <span style="color: #ff4500;">229</span>, <span style="color: #ff7700;font-weight:bold;">in</span> sendall
    v = <span style="color: #008000;">self</span>.<span style="color: black;">send</span><span style="color: black;">&#40;</span>data<span style="color: black;">&#91;</span>count:<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
  File <span style="color: #483d8b;">&quot;/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ssl.py&quot;</span>, line <span style="color: #ff4500;">198</span>, <span style="color: #ff7700;font-weight:bold;">in</span> send
    v = <span style="color: #008000;">self</span>._sslobj.<span style="color: black;">write</span><span style="color: black;">&#40;</span>data<span style="color: black;">&#41;</span>
<span style="color: #008000;">UnicodeEncodeError</span>: <span style="color: #483d8b;">'ascii'</span> codec can<span style="color: #483d8b;">'t encode character u'</span>\xe9<span style="color: #483d8b;">' in position 62: ordinal not in range(128)
Logged from file envoie_mail_on_crash.py, line 163</span></pre></div></div>

<p>D&#8217;où l&#8217;on déduit qu&#8217;il y a une tentative foirée d&#8217;encodage d&#8217;une chaîne unicode en ascii par la méthode &#8220;write&#8221; de ce mystérieux _sslobj, et que c&#8217;est une méthode &#8220;emit&#8221; quelque part dans handlers.py qui lui a passé la chaîne.</p>
<p>Fuck! Investiguons. Et essayons de régler ça par le haut de la pile.</p>
<h2>Toi, là au fond! Oui, toi!</h2>
<p>C&#8217;est la methode <code>emit</code> de SMTPHandler qui est responsable. Elle fait quoi cette méthode? Elle formate le &#8220;record&#8221;, crée un message et l&#8217;envoie à l&#8217;adresse mail spécifiée. Voilà le code:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> emit<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, record<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
    Emit a record.
&nbsp;
    Format the record and send it to the specified addressees.
    &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">smtplib</span>
        <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">email</span>.<span style="color: black;">utils</span> <span style="color: #ff7700;font-weight:bold;">import</span> formatdate
        port = <span style="color: #008000;">self</span>.<span style="color: black;">mailport</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> port:
            port = <span style="color: #dc143c;">smtplib</span>.<span style="color: black;">SMTP_PORT</span>
        smtp = <span style="color: #dc143c;">smtplib</span>.<span style="color: black;">SMTP</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">mailhost</span>, port<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># C'est ici l'objet &quot;record&quot; est formatté</span>
        msg = <span style="color: #008000;">self</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>record<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Le message est construit ici. Il sera ensuite envoyé par smtp.sendmail</span>
        <span style="color: #808080; font-style: italic;"># C'est là que le bât blesse</span>
        msg = <span style="color: #483d8b;">&quot;From: %s<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>To: %s<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>Subject: %s<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>Date: %s<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>%s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>
                        <span style="color: #008000;">self</span>.<span style="color: black;">fromaddr</span>,
                        <span style="color: #483d8b;">&quot;,&quot;</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">toaddrs</span><span style="color: black;">&#41;</span>,
                        <span style="color: #808080; font-style: italic;"># Notons ce getSubject(record). La méthode renvoie</span>
                        <span style="color: #808080; font-style: italic;">#  le sujet du message, passé à la création</span>
                        <span style="color: #808080; font-style: italic;">#  de mail_handler</span>
                        <span style="color: #008000;">self</span>.<span style="color: black;">getSubject</span><span style="color: black;">&#40;</span>record<span style="color: black;">&#41;</span>,
                        formatdate<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>,
                        <span style="color: #808080; font-style: italic;"># le record formaté</span>
                        msg<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">username</span>:
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">secure</span> <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">None</span>:
                smtp.<span style="color: black;">ehlo</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
                smtp.<span style="color: black;">starttls</span><span style="color: black;">&#40;</span><span style="color: #66cc66;">*</span><span style="color: #008000;">self</span>.<span style="color: black;">secure</span><span style="color: black;">&#41;</span>
                smtp.<span style="color: black;">ehlo</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            smtp.<span style="color: black;">login</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">username</span>, <span style="color: #008000;">self</span>.<span style="color: black;">password</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Le mail et envoyé</span>
        smtp.<span style="color: black;">sendmail</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">fromaddr</span>, <span style="color: #008000;">self</span>.<span style="color: black;">toaddrs</span>, msg<span style="color: black;">&#41;</span>
&nbsp;
        smtp.<span style="color: black;">quit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: black;">&#40;</span><span style="color: #008000;">KeyboardInterrupt</span>, <span style="color: #008000;">SystemExit</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">raise</span>
    <span style="color: #ff7700;font-weight:bold;">except</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">handleError</span><span style="color: black;">&#40;</span>record<span style="color: black;">&#41;</span></pre></div></div>

<p>Qu&#8217;est-ce qu&#8217;il se passe?</p>
<p>Après quelques tests genre:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">    msg = <span style="color: #008000;">self</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>record<span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># C'est pratique parfois un petit print</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>msg<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">##</span></pre></div></div>

<p>&#8230; on voit que la méthode <code>format</code> (qui structure votre log selon la forme passée à logging.Formatter) retourne un objet de type unicode si le message que vous avez loggué (<code>logger.critical(u"% foiré!", trace)</code>) contient de l&#8217;unicode.</p>
<p>Idem pour <code>getSubject(record)</code> qui, en l&#8217;état, ne fait que retourner le sujet du email tel que vous l&#8217;avez passé à l&#8217;instanciation de SMTPHandler.</p>
<p>Donc, quand msg est formaté, si le log ou le message sont en unicode, msg sera en unicode.</p>
<h2>WTF!?</h2>
<p>J&#8217;ai été surpris quand j&#8217;ai fini par piger comment ça fonctionne. Même pour un débutant comme moi ça a l&#8217;air bête.</p>
<p>J&#8217;y connais rien en email, mais il ne m&#8217;a pas fallu longtemps pour comprendre que, dans sa forme basique, un email c&#8217;est du ascii, point. Et que si on veut envoyer autre chose que du ascii, qui soit décodable de l&#8217;autre côté, il faut qu&#8217;il y ait les headers appropriés, que le contenu soit encodé, que sais-je encore&#8230;</p>
<p>Peut-être un truc programmé par des gars qui ne manipulent jamais autre chose que de l&#8217;anglais? Ils auraient essayé d&#8217;envoyer un mail en russes ou en suédois, ça se serait planté au premier test. Oui, oui, Sam, la lingua franca, tout ça&#8230;</p>
<p>Ou alors c&#8217;est pour des questions de compatibilité avec des versions antérieures de python qui ne contiendraient pas les ressources nécessaires pour formater correctement un mail? Aucune idée&#8230;</p>
<p>Comment régler ça?</p>
<h2>Il mangea u&#8221;\xe9&#8243; et il en redemanda</h2>
<p>Le module <a href="http://docs.python.org/2/library/email.html"> email </a> de la lib standard permet de créer des emails. On trouve dans <code>email.mime</code> une classe MIMEText qui nous conviendra parfaitement. On va donc subclasser SMTPHandler et réécrire la méthode <code>emit</code> pour qu&#8217;elle construise un message &#8220;RFC-compliant&#8221;, comme ils disent dans la doc.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> SMTPHandler_unicode<span style="color: black;">&#40;</span>SMTPHandler<span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> emit<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, record<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">try</span>:
            <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">smtplib</span>
            <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">email</span>.<span style="color: black;">utils</span> <span style="color: #ff7700;font-weight:bold;">import</span> formatdate
&nbsp;
            <span style="color: #808080; font-style: italic;"># On importe MIMEText</span>
            <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">email</span>.<span style="color: black;">mime</span>.<span style="color: black;">text</span> <span style="color: #ff7700;font-weight:bold;">import</span> MIMEText
&nbsp;
            port = <span style="color: #008000;">self</span>.<span style="color: black;">mailport</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> port:
                port = <span style="color: #dc143c;">smtplib</span>.<span style="color: black;">SMTP_PORT</span> <span style="color: #808080; font-style: italic;"># 25</span>
            smtp = <span style="color: #dc143c;">smtplib</span>.<span style="color: black;">SMTP</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">mailhost</span>, port<span style="color: black;">&#41;</span>
&nbsp;
            msg = <span style="color: #008000;">self</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>record<span style="color: black;">&#41;</span>
&nbsp;
            <span style="color: #808080; font-style: italic;"># Au moment de la création de l'objet par MIMEText,</span>
            <span style="color: #808080; font-style: italic;">#  si msg est de type unicode, il sera encodé</span>
            <span style="color: #808080; font-style: italic;">#  selon _charset, sinon il sera laissé tel quel</span>
            message = MIMEText<span style="color: black;">&#40;</span>msg, _charset = <span style="color: #483d8b;">&quot;utf-8&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
            <span style="color: #808080; font-style: italic;"># On ajoute les headers nécessaires. S'il sont de type unicode,</span>
            <span style="color: #808080; font-style: italic;">#  ils seront encodés selon _charset</span>
            message.<span style="color: black;">add_header</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Subject&quot;</span>, <span style="color: #008000;">self</span>.<span style="color: black;">getSubject</span><span style="color: black;">&#40;</span>record<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            message.<span style="color: black;">add_header</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;From&quot;</span>, <span style="color: #008000;">self</span>.<span style="color: black;">fromaddr</span><span style="color: black;">&#41;</span>
            message.<span style="color: black;">add_header</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;To&quot;</span>, <span style="color: #483d8b;">&quot;,&quot;</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">toaddrs</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            message.<span style="color: black;">add_header</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Date&quot;</span>, formatdate<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;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">username</span>:
                <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">secure</span> <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">None</span>:
                    smtp.<span style="color: black;">ehlo</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
                    smtp.<span style="color: black;">starttls</span><span style="color: black;">&#40;</span><span style="color: #66cc66;">*</span><span style="color: #008000;">self</span>.<span style="color: black;">secure</span><span style="color: black;">&#41;</span>
                    smtp.<span style="color: black;">ehlo</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
                smtp.<span style="color: black;">login</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">username</span>, <span style="color: #008000;">self</span>.<span style="color: black;">password</span><span style="color: black;">&#41;</span>
&nbsp;
            <span style="color: #808080; font-style: italic;"># Envoi du message proprement encodé</span>
            smtp.<span style="color: black;">sendmail</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">fromaddr</span>, <span style="color: #008000;">self</span>.<span style="color: black;">toaddrs</span>, message.<span style="color: black;">as_string</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
            smtp.<span style="color: black;">quit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: black;">&#40;</span><span style="color: #008000;">KeyboardInterrupt</span>, <span style="color: #008000;">SystemExit</span><span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">raise</span>
        <span style="color: #ff7700;font-weight:bold;">except</span>:
            <span style="color: #008000;">self</span>.<span style="color: black;">handleError</span><span style="color: black;">&#40;</span>record<span style="color: black;">&#41;</span></pre></div></div>

<p>Ce qui est intéressant avec MIMEText c&#8217;est que si vous déclarez un encodage (<code>_charset = "utf-8"</code>), et que vous passez une chaîne unicode a l&#8217;instanciation, il l&#8217;encodera selon <code>_charset</code>.</p>
<p>Idem si vous ajoutez un header en appelant <code>add_header</code>, ce qui permet dans notre cas de traiter correctement le sujet du mail.</p>
<p>L&#8217;appel à la méthode <code>to_string</code> retournera le message proprement encodé (en base64) pour le transfert, et les headers appropriés seront inclus.</p>
<p>Voilà, il ne reste plus qu&#8217;à utiliser cette classe pour créer mail_handler, et le tour est joué.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">mail_handler = SMTPHandler_unicode<span style="color: black;">&#40;</span>
    <span style="color: #808080; font-style: italic;"># host et port</span>
    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'SMTP.GMAIL.COM'</span>, <span style="color: #ff4500;">587</span><span style="color: black;">&#41;</span>,
    <span style="color: #808080; font-style: italic;"># From</span>
    <span style="color: #483d8b;">&quot;MOI@GMAIL.COM&quot;</span>,
    <span style="color: #808080; font-style: italic;"># To (liste)s</span>
    <span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;QUELQU.UN@QUELQUE.PART&quot;</span><span style="color: black;">&#93;</span>,
    <span style="color: #808080; font-style: italic;"># sujet du message</span>
    u<span style="color: #483d8b;">&quot;Bonjour Mr Freud. %s a encore repéré des pensées génantes&quot;</span> <span style="color: #66cc66;">%</span> nom_loggeur,
    <span style="color: #808080; font-style: italic;"># pour l'authentification</span>
    credentials = <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;MONEMAIL@GMAIL.COM&quot;</span>, <span style="color: #483d8b;">&quot;MONSUPERPASSWORD&quot;</span><span style="color: black;">&#41;</span>,
    secure = <span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: black;">&#41;</span></pre></div></div>

<p>Bilan de l&#8217;histoire: c&#8217;est en débutant qu&#8217;on devient débutant&#8230;</p>
<hr />
<a href="https://github.com/sametmax/codes-des-articles/blob/master/2013/mars/envoi_mail_on_crash.py">Télécharger le code de l&#8217;article.</a></p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5313&amp;md5=2a70d8c9d9e3c74fb78760edd63af5f9" 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=5380
title: Si ça existe, il y a une version porno
uri: Si-ça-existe-il-y-a-une-version-porno
url: http://sametmax.com/si-ca-existe-il-y-a-une-version-porno/
content:
<p>Pour ceux qui ne connaissent pas encore la règle 34 (qui est un chiffre rond comme 42, 64, 69, 128, 256 et 512 en informatique)  d&#8217;internet :</p>
<p>&#8220;Si ça existe, il y a une version porno.&#8221;</p>
<p>Aujourd&#8217;hui on va donc faire le tour, non pas des trucs les plus bizarres, mais des adaptations de cul de choses de la vie réelle.</p>
<p>Je pense que tout le monde connaît plus ou moins les adaptations merdiques de films mainstream du genre <a href="The Matrix Re Entered">Matrix, rentered</a>. Et bien entendu les animés réadaptés à la sauce blanche du style <a href="http://sextvx.com/fr/video/140170/dragon-ball-z-android-18-and-cell">les boules du dragon</a>.</p>
<p>Mais, et c&#8217;est une preuve que le réalisateur X maîtrise la mise en abîme, il y a aussi des versions sexuelles de fausses conventions de Cosplay. Si vous aviez toujours rêver de vous faire Sakura IRL (de Naruto, pas de Card Captor, mais je suis sûr que ça peut se trouver), voici :</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="510" height="400" src="http://sextvx.com/embed/238720" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<p>Quand il s&#8217;agit de média vidéo, il y a des quantités énormes de sources d&#8217;inspiration. Que diriez-vous d&#8217;une bonne tarte aux pommes avec Maïté qui se doigte pendant la cuisson ?</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="510" height="400" src="http://xhamster.com/xembed.php?video=1521005" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<p>Et en cette époque où on ne peut plus faire un sport de plein air sans croiser un mec avec une Go Pro vissée sur la tête, il n&#8217;y a pas de raison d&#8217;aller sport extrême et pratiques hards :</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="510" height="400" src="http://sextvx.com/embed/275166" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<p>Alors vous allez essayer. Essayez de trouver un truc qui ne soit pas transformable. Un truc sérieux peut être ? Les échecs ? Pauvres noobs que vous êtes !</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="632" height="470" type="text/html" src="http://embed.porntube.com/1175971" frameborder="0" id="f1175971" scrolling="no" class="iframe-class"></iframe>
<p>Un truc improbable peut être. Aller, le curling ? Mouahahaha, vous n&#8217;y êtes pas !</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe src="http://www.youjizz.com/videos/embed/118780" frameborder="0" width="704" height="550" scrolling="no" allowtransparency="true" class="iframe-class"></iframe>
<p>Ne cherchez pas dans le dégueulasse, les animaux, le sang, la merde, tout ça c&#8217;est couvert depuis la nuit des temps. Les niches bien entendu : nains, vieux, femmes enceintes, checked. Reste-t-il un espoir ? Un truc jamais touché par la main salace de nos dealers de fantasmes ?</p>
<p>Oui.</p>
<p>Après moult recherches, je n&#8217;ai pas trouvé de film de cul sur le thème de la collection de timbres. Gageons que ce sera très bientôt corrigé.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5380&amp;md5=bffa810754df7ff433183db396458b61" 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=5408
title: Set -e for the win
uri: Set-e-for-the-win
url: http://sametmax.com/set-e-for-the-win/
content:
<p>10 ans plus tard, je découvre cette option pour les scripts bash.</p>
<p>Voyez vous, quand on écrit un script bash, il exécute les commandes ligne à ligne. Si il y en a une qui retourne une erreur, il continue vaillamment. </p>
<p>Sur un script ou chaque ligne dépend de la précédente (comme un script de déploiement), c&#8217;est moyen.</p>
<p>Pour y pallier, il suffit de mettre tout en haut du script :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #008000;">set</span> -e</pre></div></div>

<p>Et voilà. Si une commande retourne une erreur, le script s&#8217;arrête à ce niveau. 10 ans de Linux et je découvre ça maintenant. Moi content.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5408&amp;md5=653b9ce5709daa902628ccdbf3d474b9" 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=5419
title: s&m.5.lezy…out@spamgourmet.net => erreur
uri: s-m-5-lezy-out-spamgourmet-net-erreur
url: http://sametmax.com/sm-5-lezy-outspamgourmet-net-erreur/
content:
<p>Bilou, je veux bien te répondre, mais ton adresse me donne une &#8220;Delivery Status Notification&#8221;</p>
<blockquote><p>Salut les gars,</p>
<p>J&#8217;ai cru comprendre que vous avez des sites de vidéos, vous vous<br />
démerdez comment pour envoyer la vidéo en streaming tous en l&#8217;encodant.<br />
Par exemple j&#8217;ai des mkv qui doivent être passer en mk4.<br />
Une petite idée ?</p>
<p>Merci d&#8217;avance,</p></blockquote>
<p>Yop,</p>
<p>On encode pas à la volée. On a des workers (powered by kombu) avec des files d&#8217;attente qui encodent les videos avec ffmpeg, et qui déclarent quand elles sont prêtes. Derrière on streamp tout ça avec nginx.  Ca demande beaucoup de tests (il n&#8217;y a pas de commande magique car ça dépend de ta cible client), et surtout, des disques durs énormes pour stocker tout ça.</p>
<p>Pour ton cas particulier, n&#8217;oublie pas qu&#8217;il y a 3 choses à prendre en compte:</p>
<ul>
<li>le codec video (h264, mpeg-2, etc)</li>
<li>le codec audio (mp3, aac, etc)</li>
<li>le conteneur (mkv, avi, mov, etc)</li>
</ul>
<p>Donc il ne s&#8217;agit pas juste de streamer (c&#8217;est le plus facile, il suffit de compiler nginx avec l&#8217;extension qui va bien et payer un bon serveur), mais bien de trouver la combinaison des 3 qui corresponde à sa cible. Tester si on vise : le HTML5 ? Un lecteur flash ? Un truc lisible sur téléphone mobile (et quels modèles&#8230; ?). Quelle définition ? Quelle bande passante ? Quel traffic ?</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5419&amp;md5=11a6bffe9b9330e1216a2a087d9e985f" 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=5410
title: Compiler nginx avec un tas d’options super cool
uri: Compiler-nginx-avec-un-tas-d-options-super-cool
url: http://sametmax.com/compiler-nginx-avec-un-tas-doptions-super-cool/
content:
<p>Ce qui est cool avec <a href="http://wiki.nginx.org/Main">nginx</a>, c&#8217;est qu&#8217;il peut très facilement se compiler avec pleinnnn de modules additionnels.</p>
<p>Par exemple, pour le compiler avec le support du scripting en Lua et des URLs sécurisées jetables :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">set</span> <span style="color: #660033;">-ex</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #000000; font-weight: bold;">/</span>tmp
&nbsp;
<span style="color: #666666; font-style: italic;"># on installe quelques dépendances, exemple sous Ubuntu</span>
<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> libgpgme11 libgpgme11-dev git-core
&nbsp;
<span style="color: #666666; font-style: italic;"># on récupère le codes modules additionnels</span>
<span style="color: #666666; font-style: italic;"># très souvent dispo sur github, c'est la fête !</span>
<span style="color: #c20cb9; font-weight: bold;">git</span> clone https:<span style="color: #000000; font-weight: bold;">//</span>github.com<span style="color: #000000; font-weight: bold;">/</span>chaoslawful<span style="color: #000000; font-weight: bold;">/</span>lua-nginx-module
<span style="color: #c20cb9; font-weight: bold;">git</span> clone https:<span style="color: #000000; font-weight: bold;">//</span>github.com<span style="color: #000000; font-weight: bold;">/</span>WebServer-Tools<span style="color: #000000; font-weight: bold;">/</span>nginx-accesskey-module.git
&nbsp;
<span style="color: #666666; font-style: italic;"># on dl les sources de nginx lui même</span>
<span style="color: #c20cb9; font-weight: bold;">wget</span> http:<span style="color: #000000; font-weight: bold;">//</span>nginx.org<span style="color: #000000; font-weight: bold;">/</span>download<span style="color: #000000; font-weight: bold;">/</span>nginx-1.2.6.tar.gz
&nbsp;
<span style="color: #c20cb9; font-weight: bold;">tar</span> <span style="color: #660033;">-xvf</span> nginx-1.2.6.tar.gz
&nbsp;
<span style="color: #7a0874; font-weight: bold;">cd</span> nginx-1.2.6<span style="color: #000000; font-weight: bold;">/</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># on compile nginx avec les modules, on inclut aussi le support de gzip</span>
<span style="color: #666666; font-style: italic;"># vu que c'est une config web, et on lui dit de mettre l'exe</span>
<span style="color: #666666; font-style: italic;"># dans /usr/local/nginx</span>
.<span style="color: #000000; font-weight: bold;">/</span>configure <span style="color: #660033;">--prefix</span>=<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>nginx --with-http_gzip_static_module <span style="color: #660033;">--add-module</span>=<span style="color: #000000; font-weight: bold;">/</span>tmp<span style="color: #000000; font-weight: bold;">/</span>lua-nginx-module <span style="color: #660033;">--add-module</span>=<span style="color: #000000; font-weight: bold;">/</span>tmp<span style="color: #000000; font-weight: bold;">/</span>nginx-accesskey-module 
&nbsp;
<span style="color: #666666; font-style: italic;"># et on lance la compilation</span>
<span style="color: #c20cb9; font-weight: bold;">make</span>
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">make</span> <span style="color: #c20cb9; font-weight: bold;">install</span></pre></div></div>

<p>Et voilà, un nginx tout neuf. Bon derrière, il faut modifier le fichier /etc/init.d/nginx pour qu&#8217;il démarre votre nginx custo, et pas celui des packages.</p>
<p>Juste pour dire que c&#8217;est facile à faire. Y a pas 40 000 dépendances, on a des features très étonnantes disponibles dans les modules, et on peut faire des configs différentes pour chaque type de serveur.</p>
<p>Joie.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5410&amp;md5=95dc85b035a10b6623ea7b196fbfd871" 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=5429
title: A l’intérieur du dossier .bitcoin
uri: A-l-intérieur-du-dossier-bitcoin
url: http://sametmax.com/a-linterieur-du-dossier-bitcoin/
content:
<p>Le logiciel <a href="http://bitcoin.org/">Bitcoin-QT</a>, le client le plus utilisé pour échanger des BTC actuellement, sauvegarde toute sa configuration dans un dossier ~/.bitcoin.</p>
<p>Voilà ce qu&#8217;on trouve dedans:</p>
<p>Le chaine de block. Tout l&#8217;historique des transactions Bitcoin depuis le lancement du projet. Ça tient dans deux dossiers :</p>
<ul>
<li>chainstate</li>
<li>blocks</li>
</ul>
<p>Plusieurs Go. Si vous supprimez ces dossiers, vous en avez pour des heures à tout télécharger avant de pouvoir faire une transaction. Mais une fois je l&#8217;ai fais, et j&#8217;ai gagné 3Go de place car le format de stockage avait changé entre deux version du soft (c&#8217;est encore un projet beta, ne l&#8217;oubliez pas).</p>
<p>Il existe des <a href="http://electrum.org/">clients lites</a> rapides et légers qui ne stockent pas la chaîne en entier pour les gens qui s&#8217;en branle d&#8217;être un nœud de transfert dans le projet et qui veulent juste que ça marche maintenant tout de suite. Je préfère participer au réseau.</p>
<p>Ensuite il y a le carnet d&#8217;adresse. Si vous le supprimez, vous ne risquez rien, mais toutes vos transactions seront listées comme une suite d&#8217;adresses Bitcoin au lieu des noms que vous leur aviez donner. En plus ça prend pas de place, donc gardez les.</p>
<ul>
<li>addr.dat</li>
<li>peers.dat</li>
</ul>
<p>Si vous êtes paranos, ces fichiers contiennent des informations qui permettent d&#8217;aider à l&#8217;identification des participants à Bitcoin. </p>
<p>Puis viens le fichier le plus important. Le porte monnaie :</p>
<ul>
<li>wallet.dat</li>
</ul>
<p>C&#8217;est votre identité. Si vous le perdez, adieu les bitcoins. Si on vous le vol, on vous vol vos bitcoins. Il ne pèse pas lourd, donc faites en un backup chiffré (une fois suffit, le fichier ne change jamais). Le contenu de ce wallet marche pour tous les clients. </p>
<p>Le client Bitcoin-QT permet de chiffrer automatiquement le wallet, mais ce n&#8217;est pas activé par défaut. Attention, une fois j&#8217;ai oublié mon mot de passe, et j&#8217;ai faillit tout perdre. Heureusement j&#8217;avais un backup.</p>
<p>Chez moi tout le dossier .bitcoin est sur une partition TrueCrypt. Une couche de sécurité de plus. C&#8217;est du pognon après tout.</p>
<p>Finalement vient les fichiers de log. Supprimez ça sans peine, tout le monde s&#8217;en branle.</p>
<ul>
<li>db.log</li>
<li>debug.log</li>
</ul>
<p>Et entre parenthèses, il y a ces fichiers qui servent au fonctionnement interne du client. Je n&#8217;ai aucune idée de ce qu&#8217;ils font ou à quoi ils servent :</p>
<ul>
<li>database</li>
<li>DB_CONFIG</li>
</ul>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5429&amp;md5=2841d363a92c1466f658ba8be7bc19d8" 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=5424
title: Limiter la gueule de bois après une cuite
uri: Limiter-la-gueule-de-bois-après-une-cuite
url: http://sametmax.com/limiter-la-gueule-de-bois-apres-une-cuite/
content:
<p>Vendredi Max, dans un élan d&#8217;ébriété motivatoire, s&#8217;est lancé dans la rédaction d&#8217;un sujet qui lui tenait à cœur sur le moment &#8220;Limiter la gueule de bois après une cuite&#8221;.</p>
<p>Il a donc tapé l&#8217;article suivant, que je vous fais partager dans son intégralité :</p>
<blockquote><p>aspirine avt de dormir<br />
1 litre d&#8217;eau</p></blockquote>
<p>Ensuite il a dévasé comme une merde toute la journée en me promettant qu&#8217;il allait le publier.</p>
<p>Je redécouvre ce concentré de génie en navigant les drafts, je pense qu&#8217;on doit pouvoir en faire un haiku.</p>
<p>Sam.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5424&amp;md5=19bf814e3e24f74dcea92c9ce0386e05" 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=5405
title: Demander confirmation à la fermeture d’un onglet en javascript
uri: Demander-confirmation-à-la-fermeture-d-un-onglet-en-javascript
url: http://sametmax.com/demander-confirmation-a-la-fermeture-dun-onglet-en-javascript/
content:
<p>Votre utilisateur est en train d&#8217;écrire un commentaire, upload un ficher ou fait un truc quelconque qui n&#8217;est pas terminé. Puis il clique sur &#8220;fermer l&#8217;onglet&#8221;.</p>
<p>Dans certains cas, vous voulez lui demander confirmation pour éviter qu&#8217;il perde tout son travail.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> confirmOnLeave <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>msg<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    window.<span style="color: #660066;">onbeforeunload</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        e <span style="color: #339933;">=</span> e <span style="color: #339933;">||</span> window.<span style="color: #660066;">event</span><span style="color: #339933;">;</span>
        msg <span style="color: #339933;">=</span> msg <span style="color: #339933;">||</span> <span style="color: #3366CC;">''</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #006600; font-style: italic;">// For IE and Firefox</span>
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>e.<span style="color: #660066;">returnValue</span> <span style="color: #339933;">=</span> msg<span style="color: #339933;">;</span><span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #006600; font-style: italic;">// For Chrome and Safari</span>
        <span style="color: #000066; font-weight: bold;">return</span> msg<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// message de confirmation générique du navigateur</span>
confirmOnLeave<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// message de confirmation personnalisé</span>
confirmOnLeave<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Vous allez perdre votre travail, êtes vous sûr(e) de vouloir quitter la page ?'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Quand vous appelez la fonction <code>confirmOnLeave()</code>, le <a href="http://sametmax.com/quest-ce-quun-callback/">callback</a> de l&#8217;événement &#8216;onbeforeunload&#8217; va être remplacé par une nouvelle fonction. Vous pouvez appeler cette fonction n&#8217;importe quand, l&#8217;événement ne se déclenche que quand l&#8217;utilisateur quitte la page de toute façon.</p>
<p>Cette fonction ne fait que retourner un message et assigner le message à l&#8217;attribut <code>returnValue</code>.</p>
<p>La navigateur va réagir ainsi:</p>
<ul>
<li>À la fermeture de la page, il va déclencher l&#8217;événement &#8216;onbeforeunload&#8217;.</li>
<li>Au déclenchement de l&#8217;événement, il va appeler le callback.</li>
<li>Le navigateur va ensuite regarder la valeur de <code>returnValue</code>. Si elle n&#8217;est pas <code>undefined</code>, il va demander confirmation à l&#8217;utilisateur avec une pop up.</li>
<li>Le contenu de la pop up dépend de <code>returnValue</code>. Si c&#8217;est une chaîne vide, c&#8217;est un message générique, sinon, c&#8217;est le contenu de la chaîne qui est affiché.</li>
</ul>
<p>Dans la plupart des cas, cette fonction suffit. Mais si vous utilisez d&#8217;autres codes JS qui ont besoin aussi de réagir à &#8216;onbeforeunload&#8217; (comme par exemple pour faire un autosave), dans ce cas il vaut mieux utiliser utiliser une gestion avancée d&#8217;attachement de callback a des événements (pour qu&#8217;ils ne s&#8217;écrasent pas les uns les autres). Vous pouvez coder ça à la main, ou juste utiliser celui de jQuery qui fait ça très bien:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">$<span style="color: #009900;">&#40;</span>window<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'beforeunload'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    ...
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5405&amp;md5=8e0c507c1326327abc680d6c57dc9d18" 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=5436
title: Detecter la version d’IE en Javascript
uri: Detecter-la-version-d-IE-en-Javascript
url: http://sametmax.com/detecter-la-version-die-en-javascript/
content:
<p>Sniffer le browser, c&#8217;est maaaaal. Mais comme toute technique diabolique, il existe quelques corner cases dans lesquels on peut la justifier. Par exemple, vous utilisez un plugin jQuery qui plante mystérieusement sous IE (toute ressemblance avec un événement réel n&#8217;est que purement accidentelle), et vous ne comprenez pas pourquoi. Vous ne pouvez donc pas détecter la fonctionnalité qu&#8217;il manque avec <a href="http://modernizr.com/">modernizr</a> ou autre, seulement que ça plante sous IE. En attendant que votre ticket de bug soit pris en compte, il faut bien que votre site en prod marche. Donc, détection du browser, et mise en place de mesures de contournement.</p>
<p>Il y a d&#8217;autres cas utiles :</p>
<ul>
<li>Faire des statistiques sur les versions d&#8217;IE sur votre site sans taper dans votre code backend.</li>
<li>Charger dynamiquement des feuilles de styles et scripts pour IE (en opposition aux commentaires conditionnels qui les chargent avec la page).</li>
<li>Afficher dynamiquement plus de pub aux utilisateurs d&#8217;IE car vous savez qu&#8217;ils sont moins tech saavy que les autres et cliquent plus facilement dessus.</li>
</ul>
<p>Bref, la méthode la plus propre (pour un truc sale :-)) est d&#8217;utiliser des commentaires conditionnels pour mettre une classe au tag <code><html></code>.</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;!doctype html&gt;
&lt;!--[if lt IE 7 ]&gt; &lt;html class=&quot;ie6&quot;&gt; &lt;![endif]--&gt;
&lt;!--[if IE 7 ]&gt;    &lt;html class=&quot;ie7&quot;&gt; &lt;![endif]--&gt;
&lt;!--[if IE 8 ]&gt;    &lt;html class=&quot;ie8&quot;&gt; &lt;![endif]--&gt;
&lt;!--[if IE 9 ]&gt;    &lt;html class=&quot;ie9&quot;&gt; &lt;![endif]--&gt;
&lt;!--[if (gt IE 9)|!(IE)]&gt;&lt;!--&gt; &lt;html class=&quot;&quot;&gt; &lt;!--&lt;![endif]--&gt;
&lt;head&gt;</pre></div></div>

<p>Ainsi votre page va commencer avec :</p>
<pre><html></pre>
<p> si ce n&#8217;est pas IE ou si c&#8217;est IE10 (qui est presqu&#8217;un navigateur décent).</p>
<pre><html class="ie6"></pre>
<p> si c&#8217;est IE6 ou moins.</p>
<pre><html class="ie7 ou ie8 ou ie9"></pre>
<p> respectivement pour ie7, ie8 et ie 8</p>
<p>Et derrière, pour cibler une version d&#8217;IE dans le code JS, jQuery fait des merveilles avec la fonction <code>is()</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> browserDeMerde <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'html'</span><span style="color: #009900;">&#41;</span>.<span style="color: #000066; font-weight: bold;">is</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'.ie6, .ie7, .ie8, .ie9'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Rappelez-vous qu&#8217;avec de grands pouvoirs viennent de grandes responsabilités, alors n&#8217;abusez pas de cette techique, c&#8217;est aussi chiant que les mecs qui font des sites Webkit only.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5436&amp;md5=b4d7ab18197bf3a66e7ca17977d58a95" 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=5403
title: Les hooks de virtualenv (exemple: postactivate pour les settings de Django)
uri: Les-hooks-de-virtualenv-(exemple-postactivate-pour-les-settings-de-Dj
url: http://sametmax.com/les-hooks-de-virtualenv-exemple-postactivate-pour-les-settings-de-django/
content:
<p>Virtualenv possède ce qu&#8217;on appelle des hooks, c&#8217;est à dire des scripts qui sont appelés automatiquement quand un événement se produit.</p>
<p>Tous les scripts se trouvent dans le dossier &#8216;bin&#8217; de l&#8217;environnement virtuel.</p>
<p>On y trouve:</p>
<ul>
<li>activate: appelé quand vous activez l&#8217;env</li>
<li>postactivate: appelé après l&#8217;activation de l&#8217;env</li>
<li>postdeactivate: appelé après la désactivation de l&#8217;env</li>
<li>preactivate: appelé avant d&#8217;activer l&#8217;env</li>
<li>predeactivate: appelé avant la désactivation de l&#8217;env</li>
</ul>
<p>Ce sont des scripts bash vides, il suffit de les remplir avec ce qu&#8217;on veut qu&#8217;il arrive : lancer un service, logger dans un dossier, setter une variable&#8230;</p>
<p>Par exemple, j&#8217;ai un fichier de settings django qui n&#8217;est pas détecté automatiquement par ./manage.py, du coup je met ce code dans &#8220;~/.virtualenv/monenv/postactivate&#8221; :</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: #ff0000;">'Set DJANGO_SETTINGS_MODULE=&quot;settings.unsettingsparticulier&quot;'</span>
<span style="color: #7a0874; font-weight: bold;">export</span> <span style="color: #007800;">DJANGO_SETTINGS_MODULE</span>=<span style="color: #ff0000;">&quot;settings.unsettingsparticulier&quot;</span></pre></div></div>

<p>Ça me set ma variable d&#8217;environnement et du coup ./manage.py trouve mon fichier de settings.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5403&amp;md5=4cd14cb5495762b3169a36841705c996" 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=5468
title: Il ne faut pas prendre des gens pour des cons mais ne jamais oublier qu’ils en sont
uri: Il-ne-faut-pas-prendre-des-gens-pour-des-cons-mais-ne-jamais-oublier-q
url:
http://sametmax.com/il-ne-faut-pas-prendre-des-gens-pour-des-cons-mais-ne-jamais-oublier-quils-en-sont/

content:
<p>Ça a été dur.</p>
<p>Ça a été dur de regarder cet homme appuyer avec son gros doigt gras, <strong>5 LONGUES fois de suite</strong>, sur l&#8217;écran du Mac Book Air pour lancer la vidéo Youtube car il croyait que c&#8217;était un iPad.</p>
<p>Ça été dur de lire les centaines de feedbacks sur un de nos sites streaming qui disent explicitement que les gens ne comprennent pas que notre site n&#8217;est pas megavideo, purevid et rutube mais qu&#8217;il ne fait que faire des embeds.</p>
<p>Ça a été dur de mettre en œuvre ces dizaines de tests ergonomiques ou chaque candidat regardait l&#8217;écran avec PEUR. Oui, de la peur. La vraie. Comme si un tigre allait sauter sur eux après qu&#8217;ils aient cliqué sur le moindre putain de lien.</p>
<p>Ça a été dur d&#8217;entendre ce retour sur un design qui nous disait &#8220;j&#8217;ai pas osé cliqué, j&#8217;avais pas confiance, je savais pas si c&#8217;était une pub. Si il y a pas marqué &#8216;cliquez-ici&#8217;, moi je clique pas&#8221;.</p>
<p>Ça a été dur de faire ces formations en voyant ces gens ignorer le même avertissement, ne lire aucun texte, fermer au bout de 2 secondes un site qui mettait 2,5 secondes à se charger car ils croyaient qu&#8217;il ne marchait pas. Ne pas comprendre. Et surtout, ne pas chercher à comprendre.</p>
<h2>Bienvenue Sam. Bienvenue, dans le monde réel.</h2>
<blockquote><p>&#8230;Tout ce que nous savons que c&#8217;est qu&#8217;un moment donné à l&#8217;orée du XXIe siècle, l&#8217;Humanité a voulu s&#8217;unir dans la célébration. Nous nous sommes émerveillés de notre magnificence dès la venue au monde de l&#8217;Internet, un réseau unique qui s&#8217;est répandu dans toute une génération de machines. Nous ignorons qui a frappé le premier, nous ou eux, mais nous avons que c&#8217;est l&#8217;humanité qui assombrit le Web.</p>
<p>Les développeurs pensaient qu&#8217;en fait les utilisateurs ne seraient pas capables de faire des erreurs privés de leurs libertés individuelles. Vouloir régner en maître était un rêve, mais c&#8217;est nous qui dépendions des utilisateurs pour survivre.</p>
<p>Nous voilà les victimes de ce que nous appelions l&#8217;ironie du sort&#8230;</p></blockquote>
<p>Car oui les amis, que vous le vouliez ou non, ce sont les utilisateurs finaux qui font rentrer les sous &#8230; au final. Et ce ne sont pas des flèches.</p>
<p>Alors oui je sais, vous voulez choisir quand ouvrir un nouvel onglet. Oui je sais, vous ne voulez pas de cette confirmation de fermeture d&#8217;onglet. Oui je sais, ces interfaces limitées qui ne permettent pas de faire la moitié de ce que vous voulez vous emmerdent au plus haut point.</p>
<p>Mais la vérité, c&#8217;est que vous êtes une minorité.</p>
<p>La majorité des internautes ne savent pas ce qu&#8217;est un navigateur.</p>
<p>La majorité des internautes ne lisent pas le texte. Aucun texte. J&#8217;ai dit AUCUN.</p>
<p>Je sais, c&#8217;est dur à croire. Mais je ne dis pas ça pour la gloire, pour le plaisir ou pour me rendre intéressant.</p>
<p>Je ne dis pas ça pour me moquer, insulter ou manquer de respects aux personnes qui me font vivre.</p>
<p>On est tous le con de quelqu&#8217;un.</p>
<p>Mais sur un site large publique (e-commerce, réseau social, porno&#8230;), vos cons, ce sont vos utilisateurs.</p>
<p>Vous n&#8217;y pouvez rien. L&#8217;ignorer ne les rendra pas moins cons. Prétendre qu&#8217;ils ne le sont pas ne leur rendra pas leur dignité.</p>
<h2>Je m&#8217;insurge, ce n&#8217;est pas vrai, la preuve&#8230;</h2>
<p>Si vous pensez répliquer, ne lisez pas la suite de l&#8217;article. Je ne peux pas vous convaincre. Seul le constat le pourrait. Les nombreux contacts que j&#8217;ai dû avoir, avant moi-même de me rendre à l&#8217;évidence que cette interface d&#8217;idiocracy n&#8217;était pas si loin de l&#8217;iphone:</p>
<div id="attachment_5469" class="wp-caption aligncenter" style="width: 410px"><a href="media/cd1c09e4.Idiocracy_hospital.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/03/Idiocracy_hospital.jpg"><img class="size-full wp-image-5469" title="Uh, this goes in your mouth. This one goes in your ear. And this one goes in your butt. Shit. Hang on a second. This one-- No. Uh... This one goes in your mouth." src="media/cd1c09e4.Idiocracy_hospital.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/03/Idiocracy_hospital.jpg" alt="Photo du clavier de l'hopital dans le film odiocracy" width="400" height="206" /></a><p class="wp-caption-text">Uh, this goes in your mouth. This one goes in your ear. And this one goes in your butt. Shit. Hang on a second. This one-- No. Uh... This one goes in your mouth.</p></div>
<p>Non, je ne suis pas condescendant. Non, je ne suis pas prétentieux. Non, je ne me crois pas meilleur qu&#8217;eux.</p>
<p>Mais j&#8217;ai vu des choses. Des choses affreuses, qui m&#8217;ont marqué à jamais.</p>
<p>La rencontre avec Max a tout changé. Avant j&#8217;étais ergonome, c&#8217;est vrai. Et j&#8217;avais fait des tests d&#8217;ergonomie. Mais toujours pour des boîtes d&#8217;informatique. Les sites visaient des geeks, mais je ne le savais pas. En fait, même quand on ne vise pas les geeks, mais un simple outil Web, on tape déjà dans un niveau &#8220;au-dessus&#8221;. Parce qu&#8217;un utilisateur mainstream ne prendra jamais le temps d&#8217;utiliser un tel outil. Il n&#8217;en aura de toute façon jamais entendu parler.</p>
<p>Puis j&#8217;ai rencontré Max, ses sites de cul et ses centaines de milliers d&#8217;utilisateurs. Et ses amis aussi.</p>
<p>C&#8217;est là qu&#8217;est la masse. C&#8217;est là qu&#8217;est monsieur &#8220;tout-le-monde&#8221;. C&#8217;est aussi là que le pognon est.</p>
<p>Bien sûr, l&#8217;argent n&#8217;est pas la seule motivation à faire un outil. Si vous faites un <a href="http://0bin.net/">0bin</a>, visez le geek. Tout ira bien. Si vous faites un service pour vous, ou pour une cause, faites comme vous le sentez.</p>
<p>Mais si vous visez les 99%. Le reste du monde. L&#8217;iPhone est trop compliqué.</p>
<p>C&#8217;est une simple question de démographie. Il y a 10 ans, il y avait beaucoup moins de monde sur Internet. Et ceux qui y allaient étaient plus à l&#8217;aise avec l&#8217;informatique. Logique : les premiers arrivés étaient les plus intéressés. Aujourd&#8217;hui, la planète entière est sur le Web.</p>
<h2>L&#8217;iPhone est trop compliqué</h2>
<p>Il y a 5 ans, on prenait les interfaces Apple comme modèle de simplicité. Et c&#8217;est toujours vrai. Sauf que maintenant ça ne suffit plus : il existe une bonne part des utilisateurs d&#8217;iPhone qui ne savent pas :</p>
<ul>
<li>Faire autre chose que Tel + SMS + Facebook.</li>
<li>Installer une app.</li>
<li>Copier / coller.</li>
<li>Savoir où ils sont (sur un app natives, externes au téléphones, sur un site internet&#8230;). En fait ils ne savent pas ce qu&#8217;est une app.</li>
</ul>
<p>Pour toutes ces actions, ces gens demandent à quelqu&#8217;un d&#8217;autre de les aider. C&#8217;est comme ça que fonctionne l&#8217;humanité : je ne sais pas réparer ma voiture, je demande à un garagiste. Sauf que la voiture à mis près d&#8217;un siècle à s&#8217;installer dans les foyers, traversant lentement les couches sociales.</p>
<p>Internet s&#8217;est imposé partout, et à tout le monde, en 30 ans.</p>
<p>Le Workflow de ces personnes est :</p>
<ol>
<li>Je cherche un truc qui ne fasse pas peur.</li>
<li>Je clique. Il se passe quelque chose qui ne fait pas peur dans les 2 secondes ? Je continue. Sinon je ferme l&#8217;app et j&#8217;oublie.</li>
<li>Je regarde si ça semble faire ce que je veux. Si oui, je continue. Si non, je recommence cette procédure une à deux fois. Si ça ne marche pas je ferme l&#8217;app et j&#8217;oublie.</li>
</ol>
<p>Oui, la notion de peur est importante. Les utilisateurs ont peur sur une machine. Ils sont stressés. Faites l&#8217;expérience : prenez un utilisateur qui n&#8217;a pas Skype, demandez-lui de l&#8217;installer, créer un compte, se connecter et passer un coup de fil. Prenez son pouls pendant la procédure (et un chrono pour juger du temps). C&#8217;est hallucinant.</p>
<p>Tout ça pour dire que maintenant, simple ne suffit plus. Il faut du gros, du voyant, et des garde-fous. Cela peut se traduire par le principe suivant : &#8220;il doit être facile de trouver comment faire quelque chose, et difficile de faire une erreur&#8221;.</p>
<p>Quitter la page pendant un upload est une erreur. Il faut mettre <a href="http://sametmax.com/demander-confirmation-a-la-fermeture-dun-onglet-en-javascript/">une confirmation</a>.</p>
<p>Quitter le site alors qu&#8217;on lisait un article car on a cliqué sur un lien sortant est une erreur. Il faut mettre un <code>target="_blank"</code> sur les liens sortants et les liens sur une page de formulaire.</p>
<p>Je sais, ça fait chier. Mais votre revenu en dépend, à moins de travailler en interne pour EDF.</p>
<p>Les boutons doivent être gros. Simplistes. Les labels doivent privilégier un SEUL mot. Un seul putain de mot. Afin que l&#8217;utilisateur n&#8217;ait pas à le lire, mais que sa vision périphérique puisse l&#8217;enregistrer. Si vous mettez 3 mots, c&#8217;est la merde. Bientôt il faudra mettre des onomatopées. Et non, <a href="http://sametmax.com/beau-et-facile-a-utiliser-deux-choses-bien-differentes/">les icônes ne suffisent pas</a>.</p>
<p>Il y a aussi certains problèmes que vous ne pouvez pas résoudre. Par exemple, le principe du contenu embed ne sera jamais compris par une partie des utilisateurs. Jamais. Ils vous blâmeront toujours pour des problèmes du site qui héberge le contenu. Ils vous insulteront même. Violemment. Vous n&#8217;y pouvez rien, faites vous à l&#8217;idée. Sans compter que <a href="http://xkcd.com/1053/">la génération d&#8217;ignorants se renouvelle</a>.</p>
<p>Ça ne veut pas dire qu&#8217;il ne faut pas mettre de message d&#8217;erreur, de FAQ ou d&#8217;aide. Ça ne veut CERTAINEMENT PAS dire qu&#8217;il ne faut pas un formulaire de feedback auquel il faut répondre avec courtoisie en aidant le plus possible l&#8217;interlocuteur.</p>
<p>Ça veut juste dire que ces mesures ne concernent qu&#8217;une petite partie des utilisateurs.</p>
<h2>La solution finale</h2>
<blockquote><p>Qu&#8217;est-ce qu&#8217;un utilisateur dans la mer ? La pollution. Qu&#8217;est-ce que tous les utilisateurs dans la mer ? La solution.</p></blockquote>
<p>Je sais, vous allez être tentés de vous en foutre. Au diable tous ces connards qui <a href="http://sametmax.com/detecter-la-version-die-en-javascript/">utilisent IE8</a>. Que crèvent ces abrutis qui tapent &#8220;videos sexe&#8221; dans le moteur de recherche de votre tube de cul. Vomissons sur ces demeurés qui cliquent sur le premier résultat de Google, en haut, en jaune, labélisé &#8220;Annonces&#8221; car ils pensent que c&#8217;est un résultat de recherche.</p>
<p>Sauf que non.</p>
<p>D&#8217;une part, les ignorer est le vrai manque de respect. Pester contre des gens qui vous font faire plus de travail et dont le comportement vous énerve est humain. Mais ils méritent comme tous les autres d&#8217;avoir accès à votre site. Rappel : ce sont eux qui vous font vivre.</p>
<p>Ensuite, rendre l&#8217;expérience utilisateur agréable pour eux, c&#8217;est généralement (généralement&#8230;) aussi améliorer l&#8217;expérience utilisateur de ceux qui ont un meilleur niveau. Ils vous servent donc de mètre étalon. Ajouter des options sur une interface épurée est beaucoup plus facile qu&#8217;en retirer.</p>
<p>Enfin, il est extrêmement gratifiant de voir quelqu&#8217;un qui n&#8217;est pas à l&#8217;aise avec l&#8217;informatique être satisfait de votre produit. Croyez-moi, c&#8217;est une vraie victoire.</p>
<p>Avocats, pharmaciens, étudiants en médecine, consultant en bilan thermodynamique&#8230; Ce sont des profils de personnes nulles à chier en informatique que j&#8217;ai rencontré. Si vous pensiez qu&#8217;on était sur un mode lutte des classes ou dans une logique de calcul de QI, vous pouvez vous rhabiller. La population concernée par le syndrome du brainfreeze devant un ordinateur est parfaitement transversale. Comme un nerd devant une machine à coudre.</p>
<p>Et votre intuition, en tant que geek, est à chier pour juger de la qualité de votre interface.</p>
<p>Il n&#8217;y a donc qu&#8217;un seul moyen : testez. Testez, testez, testez.</p>
<p>Et retirez. Retirez, retirez, retirez.</p>
<blockquote><p>It&#8217;s not the daily increase but daily decrease. Hack away at the unessential.</p></blockquote>
<p style="text-align: right;"><em>Lee (Bruce, de son pti nom)</em></p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5468&amp;md5=96f8a6b302b5f0fd1c3eac78febda421" 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=5497
title: On s’casse
uri: On-s-casse
url: http://sametmax.com/on-scasse/
content:
<p>Sam et Max seront en déplacement&#8230; hum&#8230; professionnel.</p>
<p>Donc si il n&#8217;y a pas d&#8217;article ou qu&#8217;on répond pas aux commentaires dans les prochains jours, c&#8217;est normal. Cassez pas le Web pendant ce temps hein. Je vais quand même voir si on a pas un gentil correcteur qui veut pas surveiller le bac à sable.</p>
<p>&nbsp;</p>
<div id="attachment_5498" class="wp-caption aligncenter" style="width: 557px"><a href="media/ad900810.oxBulI1.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/03/oxBulI1.jpg"><img class=" wp-image-5498 " title="Vous inquiétez pas, on respecte la limite de 88 miles par heure sur la route." src="media/ad900810.oxBulI1.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/03/oxBulI1.jpg" alt="Photo de rails en feu" width="547" height="411" /></a><p class="wp-caption-text">Vous inquiétez pas, on respecte la limite de 88 miles par heure sur la route.</p></div>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5497&amp;md5=ed6083e70ef977d41bf9b745ad79b981" 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=5488
title: Ego et corruption
uri: Ego-et-corruption
url: http://sametmax.com/ego-et-corruption/
content:
<p>J&#8217;ai craqué.</p>
<p>La première fois en acceptant de censurer une blague de cul.</p>
<p>Mais merde, c&#8217;est Jacob Kaplan-Moss.</p>
<p>La seconde fois en me la pêtant en publiant cet article.</p>
<p>Mais merde, c&#8217;est Jacob Kaplan-Moss, quoi.</p>
<p>Désolé pour cet instant de traitrise / faiblesse / vantardise. Je promets pas de plus le refaire. Mais je ferai de mon mieux.</p>
<blockquote><p>    Le ven. 22 mars 2013 21:08:41 CET, Jacob Kaplan-Moss a écrit :<br />
Thanks, I appreciate it. I owe you one.</p>
<p>Jacob</p>
<p>&gt; On Fri, Mar 22, 2013 at 1:05 PM, Sam et Max &lt;lesametlema&#8230;mail.com&gt; wrote:<br />
&gt; I updated the git repo and pypi. Children are safe now.<br />
&gt;<br />
&gt;<br />
&gt;&gt; On Fri, Mar 22, 2013 at 1:00 PM, Sam et Max &lt;lesametlem&#8230;ail.com&gt; wrote:<br />
&gt;&gt; Hi man,<br />
&gt;&gt;<br />
&gt;&gt; I would usually say fuck to &#8216;politically correct&#8217;, as I think it kills slowly fun and mind openness in our community. I don&#8217;t care if my work has low visibility on the &#8220;formal&#8221;</p>
<p>&gt;&gt; professional world.<br />
&gt;&gt;<br />
&gt;&gt; But first, I&#8217;m a big fan of yours. Second, I make a living thanks to your work on Django.<br />
&gt;&gt;<br />
&gt;&gt; So yeah, no problem, I&#8217;ll edit that.<br />
&gt;&gt;<br />
&gt;&gt; Please just continue to do your awesome work.<br />
&gt;&gt;<br />
&gt;&gt; Cheers<br />
&gt;&gt;<br />
&gt;&gt; Sam<br />
&gt;&gt;<br />
&gt;&gt;&gt; Le ven. 22 mars 2013 20:12:41 CET, Sam &amp; Max a écrit :<br />
&gt;&gt;&gt; From: Jacob Kaplan-Moss &lt;jaco&#8230;ian.org&gt;<br />
&gt;&gt;&gt; Subject: django-quickly<br />
&gt;&gt;&gt;<br />
&gt;&gt;&gt; Message Body:<br />
&gt;&gt;&gt; Hi there -<br />
&gt;&gt;&gt;<br />
&gt;&gt;&gt; I&#8217;m writing about https://github.com/sametmax/django-quicky; I beieve this is your repository?<br />
&gt;&gt;&gt;<br />
&gt;&gt;&gt; The README makes a sexually suggestive joke (about &#8220;foreplay&#8221;) that I think is distracting and unfortunate in a technical context. Would you mind doing me a favor and dropping &gt;&gt;the sexual reference? I think it&#8217;d make your tool more accessible.<br />
&gt;&gt;&gt;<br />
&gt;&gt;&gt; Thanks,<br />
&gt;&gt;&gt;<br />
&gt;&gt;&gt; Jacob Kaplan-Moss<br />
&gt;&gt;&gt;<br />
&gt;&gt;&gt; &#8211;<br />
&gt;&gt;&gt;</p></blockquote>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5488&amp;md5=5210c25dd6dc83d3c264eea246e1696c" 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=5265
title: Warning technique à un autre développeur en Python
uri: Warning-technique-à-un-autre-développeur-en-Python
url: http://sametmax.com/warning-technique-a-un-autre-developpeur-en-python/
content:
<p>Une dépendance optionnelle est manquante. Une fonction est dépréciée. Une syntaxe n&#8217;est pas recommandée.</p>
<p>Il y a mieux qu&#8217;un <code>print()</code> pour signaler ça à votre utilisateur.</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;">warnings</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># on definit quels types de warning on va afficher (a faire une seule fois)</span>
<span style="color: #dc143c;">warnings</span>.<span style="color: black;">simplefilter</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;always&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># et on affiche tous nos warning</span>
<span style="color: #dc143c;">warnings</span>.<span style="color: black;">warn</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;La fonction je_vais_a_une_boom() est depreciee&quot;</span>, <span style="color: #008000;">DeprecationWarning</span><span style="color: black;">&#41;</span>
<span style="color: #dc143c;">warnings</span>.<span style="color: black;">warn</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Le module optionnel 'braces' n'est pas disponible&quot;</span>, ImportWarning<span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># ne mettez pas de caracteres non ASCII, sinon ca chie</span>
&nbsp;
<span style="color: #808080; font-style: italic;">## /home/Sam/Bureau/test.py:8: DeprecationWarning: La fonction je_vais_a_une_boom() est depreciee</span>
<span style="color: #808080; font-style: italic;">##   warnings.warn(&quot;La fonction je_vais_a_une_boom() est depreciee&quot;, DeprecationWarning)</span>
<span style="color: #808080; font-style: italic;">## /home/Sam/Bureau/test.py:9: ImportWarning: Le module optionnel 'braces' n'est pas disponible</span>
<span style="color: #808080; font-style: italic;">##   warnings.warn(&quot;Le module optionnel 'braces' n'est pas disponible&quot;, ImportWarning)</span></pre></div></div>

<p>L&#8217;avantage d&#8217;utiliser le module <code>warning</code> est :</p>
<ul>
<li>Il affiche sur stderr automatiquement.</li>
<li>Il affiche un format clair automatiquement (fichier, ligne, type de warning).</li>
<li>On peut très vite lire le code source et voir ce qui déclenche un warning.</li>
</ul>
<p>Mais surtout, on peut filtrer les warning:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #dc143c;">warnings</span>.<span style="color: black;">simplefilter</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;type de filtrage&quot;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Le module permet de choisir ce qu&#8217;on affiche comme warning. Ils sont désactivables par la ligne de commande. Et surtout, quelqu&#8217;un qui importe votre module qui balance des warnings possède de nombreux moyens de les réduire au silence ou de les rediriger ailleurs. Par exemple :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #dc143c;">warnings</span>.<span style="color: black;">catch_warnings</span><span style="color: black;">&#40;</span>record=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> w:
     <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">test</span></pre></div></div>

<p>Vous trouverez ici un <a href="http://docs.python.org/2/library/warnings.html">liste des warnings disponibles ainsi que les filtres possibles</a>.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5265&amp;md5=bef106a0851575bdc3c0c9a11159cbe7" 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=4449
title: Les fichiers sublime-workspace et sublime-project
uri: Les-fichiers-sublime-workspace-et-sublime-project
url: http://sametmax.com/les-fichiers-sublime-workspace-et-sublime-project/
content:
<p>Quand vous créez un projet avec <a href="http://sametmax.com/tag/sublime-text/">Sublime  Text 2</a>, il met deux fichiers à la racine de celui-ci: <a href="http://www.sublimetext.com/docs/2/projects.html">sublime-workspace et sublime-project</a>.</p>
<p>Le premier contient des données de cache à destination de l&#8217;éditeur. Vous pouvez le supprimer, ça n&#8217;a aucune importance. Il est juste là pour que ST aille plus vite pour des tâches comme le &#8220;Go To anything&#8221; ou la completion du code. Il ne doit pas être rajouté dans votre gestionnaire de source, et peut donc être listé dans les blacklists comme <em>.gitignore</em>.</p>
<p>Le second contient des configurations spécifiques à ce projet : modes de build, settings de ST qui changent juste pour ce projet (par exemple l&#8217;interpréteur Python pointe sur le virtualenv), etc. Celui-ci est généralement intéressant à partager avec son équipe (évitez juste de mettre des chemins absolus dedans), donc vous pouvez le foutre dans le repo Git, Mercurial ou (Dieu vous pardonne), SVN.</p>
<p>Souvent, je mets au moins ça dedans :</p>

<div class="wp_syntax"><div class="code"><pre class="json" style="font-family:monospace;">{
    &quot;settings&quot;:
    {
	&quot;rulers&quot;:
	[
		80
	],
	&quot;translate_tabs_to_spaces&quot;: true,
	&quot;trim_trailing_white_space_on_save&quot;: true,
        &quot;tab_size&quot;: 4
    }
}</pre></div></div>

<p>Ce sont de bons settings par défaut pour le PEP8. À éviter, les params du genre <code>shift_tab_unindent</code>, <code>spell_check</code>, <code>word_separators</code> ou <code>word_wrap</code> qui sont de l&#8217;ordre de la préférence ergonomique et seront bien mieux dans le fichier de settings de l&#8217;utilisateur.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=4449&amp;md5=7336ccf2243c3ccb71216ffe84dba16b" 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=4002
title: Un code plus propre avec “use strict” en javascript
uri: Un-code-plus-propre-avec-use-strict-en-javascript
url: http://sametmax.com/un-code-plus-propre-avec-use-strict-en-javascript/
content:
<p>Le JavaScript est très permissif. Mais vous avez reçu <a href="http://shop.oreilly.com/product/9780596517748.do">un message de Dieu</a> lui-même, et maintenant vous n&#8217;utilisez juste qu&#8217;un sous-ensemble du langage dans votre code. Mais cela demande de la vigilance.</p>
<p>Une astuce peut vous aider à rester dans le droit chemin : <code>"use strict"</code>.</p>
<p>Bien entendu, vous écrivez votre code dans <a href="http://sametmax.com/la-fonction-anonyme-appelee-immediatement-en-javascript-function/">une fonction appelée immédiatement</a>. Ajoutez la chaîne de caractères <code>"use strict";</code> juste en dessous de cette fonction pour que les interpréteurs des navigateurs modernes deviennent plus exigeants avec celui-ci :</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
<span style="color: #3366CC;">&quot;use strict&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">// votre code</span>
&nbsp;
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span></pre></div></div>

<p>Pour les navigateurs qui ne connaissent pas cette instruction, c&#8217;est juste une string, et c&#8217;est ignoré. Pour ceux qui connaissent l&#8217;instruction, tout le bloc concerné (ici tout votre code, mais PAS le code en dehors de la fonction, donc pas de risque de planter le code des autres tels qu&#8217;un plugin jQuery) sera vérifié.</p>
<p>Parmi les vérifications :</p>
<ul>
<li>Définir deux fois le même attribut dans un objet avec la notation littérale.</li>
<li>Utilisation de <code>eval()</code>.</li>
<li>Utilisation de <code>with</code>.</li>
<li>Utilisation de <code>arguments</code> and <code>caller</code>.</li>
</ul>
<p>Si ces situations sont rencontrées, une exception est levée. Un bon article avec des exemples en anglais <a href="http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/">ici</a>.</p>
<p>Tous mes codes JS ont maintenant<code> "use strict"</code> par défaut, en plus du plugin <a href="https://github.com/SublimeLinter/SublimeLinter">SublimeLinter</a> qui me sert de garde-fou supplémentaire.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=4002&amp;md5=ebfb64d54bb2e59d524ab07054a61083" 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=2171
title: Récupérer une branche supprimée sous Git
uri: Récupérer-une-branche-supprimée-sous-Git
url: http://sametmax.com/recuperer-une-branche-supprimee-sous-git/
content:
<p>Vous avez supprimé une branche (avec <code>git branch -D nom_de_branche</code>), pas de panique. Tant que le garbage collector n&#8217;est pas passé, la branche est toujours dans l&#8217;historique.</p>
<p>Retrouvez le hash du dernier commit de la branche en vous baladant dans <code>git reflog</code> (quelques <code>git checkout</code> peuvent être nécessaires pour en voir le contenu). Si vous ne le trouvez pas dans le reflog, tentez <code>git fsck —lost-found</code>.</p>
<p>Une fois que vous avez le numéro magique, faites <code>git branch nom_de_branche votre_hash</code>, et vous voilà sorti d&#8217;affaire. </p>
<p>Non ne me remerciez pas, je ne fais que mon devoir madame.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=2171&amp;md5=cac938b600f28abe118b3aba6a755014" 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=5540
title: Listerine rime avec Cyprine
uri: Listerine-rime-avec-Cyprine
url: http://sametmax.com/listerine-rime-avec-cyprine/
content:
<p>L’expérience de mainte fleurs léchées,<br />
Laisse penser le coquin tendre,<br />
Qu&#8217;il a fait le tour du sujet,<br />
Que rien ne pourra le surprendre.</p>
<p>Mais c&#8217;est au détour d&#8217;un voyage,<br />
Accompagné de pairs moins verts,<br />
Qu&#8217;il bénéficia du partage,<br />
De cette sagesse décrite en vers.</p>
<p>Il n&#8217;est nul doute que les muqueuses,<br />
Perméables, intimement enlacées,<br />
Laissent passer des choses douteuses,<br />
Pour chaque minou bien chouchouté.</p>
<p>Un mal de gorges, une irritation,<br />
Un aphte ou bien d&#8217;autres maux,<br />
Peuvent résulter de la passion,<br />
D&#8217;une langue et d&#8217;un mignon clito.</p>
<p>Aussi avant et après l&#8217;action,<br />
Si vous ne pouvez prendre une douche,<br />
Une alternative solution,<br />
Est un rapide <a href="http://www.bing.com/images/search?q=bain+de+bouche&amp;go=&amp;qs=n&amp;form=QBLH&amp;filt=all&amp;pq=bain+de+bouche&amp;sc=0-0&amp;sp=-1&amp;sk=">bain de bouche</a>.</p>
<p>L&#8217;haleine fraiche et mentholée,<br />
Et l&#8217;assurance d&#8217;un baisé sain,<br />
Vous assurera une soirée,<br />
Enjouée jusqu&#8217;au petit matin.</p>
<p>Multipliez les partenaires,<br />
Vous n&#8217;avez plus rien à craindre,<br />
De ces plaisirs éphémères,<br />
Que de les entendre geindre.</p>
<p>N&#8217;oubliez pas cependant,<br />
N&#8217;abusez pas de la potion magique,<br />
Qui abreuvera chacune des dents,<br />
De sa puissance antiseptique.</p>
<p>La délicate faune buccale,<br />
Est en effet bien maltraitée,<br />
Par chaque gorgée qui dévale,<br />
Les rigoles de votre dentier.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5540&amp;md5=1c3f7c9258c676abf2e85fb28118698c" 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=5535
title: 10 sites Web découverts au cours de l’année passée
uri: 10-sites-Web-découverts-au-cours-de-l-année-passée
url: http://sametmax.com/10-sites-web-decouverts-au-cours-de-lannee-passee/
content:
<p>Les sites vont et viennent, et ces 12 derniers mois j&#8217;ai fais beaucoup moins de découvertes qu&#8217;avant alors que l&#8217;information n&#8217;a jamais autant circulé. Preuve s&#8217;il en est besoin que la quantité du contenu a aujourd&#8217;hui largement dépassé la capacité des humains à le traiter et qu&#8217;il est de plus en plus difficile de se faire sa place en tant que petit nouveau. Internet mute, d&#8217;un outil de bidouilleurs passionnés vers un torrent de bits de moins en moins démocratique. C&#8217;est triste, mais dans le lot on trouve toujours quelques perles.</p>
<p><a href="https://imgur.com/">Imgur</a></p>
<p>Trop de temps perdu sur Stumble Uppon. Alors j&#8217;ai arrêté. Puis sur 4chan, alors j&#8217;ai arrêté. Puis sur Reddit. Alors j&#8217;ai arrêté. Maintenant je perds mon temps sur Imgur.</p>
<p>C&#8217;est un simple site de partages d&#8217;images sur lequel on peut naviguer paresseusement au clavier. On enchaine les choses belles, drôles, curieuses, inutiles&#8230; On y retrouve le meilleur de reddit et 4chan, ainsi que des meme inédits, et des commentaires funs.  La communauté est une des plus sympathiques que je connaisse, drôle, pertinente, et globalement bienveillante.</p>
<p>Ce site est un pot de nutella.</p>
<p><a href="http://www.covoiturage.fr/">Covoiturage.fr</a></p>
<p>Un site ergonomique, rapide et efficace pour trouver des covoiturages dans toutes la France et les pays limitrophes. Sa force est qu&#8217;il arrive à cumuler une simplicité d&#8217;utilisation, un grand nombre d&#8217;utilisateurs et un certains sérieux : ils ont réussit à rendre payant ce qui était avant gratuit. Chapeau, car je suis heureux de payer.</p>
<p>Le système de réputation, de question / réponse et d&#8217;alertes SMS et vraiment rassurant. Si vous voulez traverser le pays pour la moitié du prix d&#8217;un billet de train, c&#8217;est top.</p>
<p><a href="https://www.bitcoin.de">Bitcoin.de</a></p>
<p>[Insérer cliché sur la fiabilité allemande ici]</p>
<p>Avant j&#8217;utilisais bitmarket.eu pour acheter et vendre des <a href="http://sametmax.com/quest-ce-que-bitcoin/">bitcoins</a>. Mais ça c&#8217;était avant.</p>
<p>C&#8217;était avant que le mec de bitmarket joue avec l&#8217;argent de ses utilisateurs et perdent tout. Ce sera jamais que le 5eme site de ce genre à se vautrer. J&#8217;ai eu de la chance car je ne laisse jamais de crédit sur ces sites, mais faites gaffe quand vous les utiliser.</p>
<p>Bref, le nouvel outil que j&#8217;utilise est bitcoin.de (le btc  est à 80 euros l&#8217;unité à l&#8217;heure où j&#8217;écris ce post, alors c&#8217;est un peu la folie sur les exchanges en ce moment) et après 3 ventes, aucun problème. Je recommande. Jusqu&#8217;au prochain incident :-)</p>
<p><a href="http://www.memrise.com/">Memrize</a></p>
<p>Apprenez quelque chose de nouveau chaque jour. C&#8217;est leur slogan.</p>
<p>Memrize vous donne une liste de sujets (les langues, l&#8217;histoire, etc) et vous permet de chaque jour travailler quelques minutes dessus. C&#8217;est ludique. C&#8217;est facile. C&#8217;est pas intrusif. L&#8217;idée est excellente.</p>
<p><a href="http://spamgourmet.com/">Spamgourmet</a></p>
<p>J&#8217;en ai parlé plus en détails <a href="http://sametmax.com/spamgourmet-mon-amour/">ici</a> donc je ne vais pas me répéter. C&#8217;est une bonne solution antispam. Point. Merci Sebsauvage pour me l&#8217;avoir fait découvrir.</p>
<p><a href="http://odieuxconnard.wordpress.com/">Le blog de l&#8217;odieux connard</a></p>
<p>Il y a peu de choses qui me font rire tout seul devant mon écran. Bashfr. Le joueur du grenier. Et aussi l&#8217;odieux connard.</p>
<p>Hilarant, intelligent, impertinent, l&#8217;auteur maitrise l&#8217;art délicat du sarcarsme vulgo-classe et de la parodie critique avec goût.</p>
<p>Rire et réfléchir en même temps, c&#8217;est si rare. C&#8217;est si bon.</p>
<p><a href="http://www.seriesyonkis.com/">Seriesyonki</a></p>
<p>Je parles parfaitement anglais, et les sous-titres, c&#8217;est pour les pédés. Alors je regarde toutes les séries sur des tubes sud américains qui ont les derniers épisodes de tout, en VO, sous-titré espagnol. Pas de censure, pas de bridage. La belle vie.</p>
<p><a href="http://www.hushmail.com/">Hushmail</a></p>
<p><a href="http://sametmax.com/quitter-google-recherche-email-et-chat/">Opera est un très bon fournisseur de mail généraliste</a>. En parallèle, on peut utiliser Hushmail qui lui fournit des boîtes mails dont le contenu est chiffré côté client. Alors évidement, ça veut dire pas de recherche dans vos mails à la Gmail, mais ça veut aussi dire des communications sûres, sans avoir à installer GPG et tout le toutim.</p>
<p><a href="http://fr.slideshare.net/">Slideshare</a></p>
<p>Uploadez un PDF, un ODS ou un PPT, et boum, vous avez une présentation en ligne embedable. Chouette.</p>
<p><a href="http://jsfiddle.net/">JsFiddle</a></p>
<p>Quand on veut montrer un bout de JS + HTML + CSS à quelqu&#8217;un, ce service est 100 fois mieux qu&#8217;un pastebin. Parce qu&#8217;il vous montre les résultats en temps réels. Parce que les snippets sont modifiables. Par qu&#8217;on peut faire un embed. Et aussi parce que le nom du site rime avec noodle.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5535&amp;md5=1682cb5d6ea6573a0ca98c96e8f595d1" 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=3261
title: De l’inutilité de <dl>
uri: De-l-inutilité-de
url: http://sametmax.com/de-linutilite-de/
content:
<p>Sémantiquement c&#8217;est génial :</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;dl&gt;
&lt;dt&gt;Couleurs disponibles :&lt;/dt&gt;
&lt;dd&gt;Bleue&lt;/dd&gt;
&lt;dd&gt;Rouge&lt;/dd&gt;
&lt;dt&gt;Pas de RAM&lt;/dt&gt;
&lt;dt&gt;Pays : &lt;/dt&gt;
&lt;dd&gt;France&lt;/dd&gt;
&lt;dd&gt;Espagne&lt;/dd&gt;
&lt;dd&gt;Wonderland&lt;/dd&gt;
&lt;/dl&gt;</pre></div></div>

<p>On peut faire une liste avec des sortes de titres, et on sait que les éléments de la liste sont liés par leur titre.</p>
<p>Sauf que :</p>
<ul>
<li>Les moteurs de recherche en ont rien à foutre. On a constaté aucune différence en passant de ça à un &lt;ul&gt; ou même une imbrication de &lt;div&gt;.</li>
<li>C&#8217;est impossible à styler : on ne peut pas grouper en CSS un &lt;dt&gt; et ses &lt;dd&gt;. Et les foutre dans des conteneurs rend le code invalide.</li>
<li>On ne peut pas mettre de balise block dans le &lt;dt&gt;. WTF ? C&#8217;est une putain de balise de titre !</li>
</ul>
<p>Bref, la definition list est la balise la plus inutile de tous les temps. J&#8217;ai essayé de l&#8217;utiliser dans un millions de cas de figure, au final un &lt;ul&gt; avec un &lt;strong&gt; et un &lt;span&gt; dans le &lt;li&gt; ou des &lt;div&gt; pour les gros morceaux sont toujours plus facile à style. Les développeurs front end peuvent se mettre la sémantique au cul.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=3261&amp;md5=5180fe5383ce7fa671ce91cb694301ce" 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=4416
title: Initiation à Varnish – Accélerer un blog WordPress
uri: Initiation-à-Varnish-Accélerer-un-blog-WordPress
url: http://sametmax.com/initiation-a-varnish-accelerer-un-blog-wordpress/
content:
<p><a href="https://www.varnish-cache.org/">Varnish</a> est un service qui permet de mettre en cache (sur disque ou en mémoire) certains contenus de votre site. Beaucoup de gros sites l&#8217;utilise pour sa puissance et ses options de configuration.<br />
Il est plutôt facile à installer mais ça se corse lorsqu&#8217;il faut le configurer car il peut ne rien cacher du tout, surtout avec la config par défaut.</p>
<p>Nous allons voir ici une configuration pour un site sous WordPress avec un serveur Nginx, Varnish étant placé en Front c&#8217;est à dire devant Nginx (il y a aussi le mode sandwich Nginx / Varnish / Backend).</p>
<p><img class="aligncenter size-full wp-image-4417" title="Varnish en Front" src="media/2a96371f.varnish.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/02/varnish.png" alt="" width="580" height="272" /></p>
<p><strong>Installation de Varnish sous ubuntu:<br />
</strong></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> varnish</pre></div></div>

<p>Il y a 2 fichiers qu&#8217;il faut retenir pour Varnish, le fichier avec les règles et le fichier de config du service.<br />
<strong><br />
Configurer le service, On va faire en sorte que Varnish écoute sur le port 80:</strong></p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">vi</span> <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>default<span style="color: #000000; font-weight: bold;">/</span>varnish</pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #007800;">DAEMON_OPTS</span>=<span style="color: #ff0000;">&quot;-a :80 <span style="color: #000099; font-weight: bold;">\
</span>             -T localhost:6082 <span style="color: #000099; font-weight: bold;">\
</span>             -f /etc/varnish/default.vcl <span style="color: #000099; font-weight: bold;">\
</span>             -S /etc/varnish/secret <span style="color: #000099; font-weight: bold;">\
</span>             -s malloc,256m&quot;</span></pre></div></div>

<p>Trouvez cette ligne dans le fichier de conf et mettez 80 pour l&#8217;option -a.<br />
<em>malloc</em> va sauver le cache en mémoire à hauteur de 256 MB, on peut sauvegarder sur disque si on a un SSD (ex: -s file,/var/lib/varnish/varnish_storage.bin,1G&#8221;).</p>
<p><strong>Configurer les règles de cache:</strong></p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">vi</span> <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>varnish<span style="color: #000000; font-weight: bold;">/</span>default.vcl</pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># Varnish 3 configuration for Wordpress</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># On Debian OS:  /etc/varnish/default.vcl</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># Nicolas Hennion (aka) Nicolargo</span>
<span style="color: #666666; font-style: italic;">#</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Set the default backend (Nginx server for me)</span>
backend default <span style="color: #7a0874; font-weight: bold;">&#123;</span>
	<span style="color: #666666; font-style: italic;"># My Nginx server listen on IP address 127.0.0.1 and TCP port 8080</span>
	.host = <span style="color: #ff0000;">&quot;127.0.0.1&quot;</span>;
	.port = <span style="color: #ff0000;">&quot;8080&quot;</span>;
	<span style="color: #666666; font-style: italic;"># Increase guru timeout</span>
	<span style="color: #666666; font-style: italic;"># http://vincentfretin.ecreall.com/articles/varnish-guru-meditation-on-timeout</span>
	.first_byte_timeout = 300s;
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># This function is used when a request is send by a HTTP client (Browser) </span>
sub vcl_recv <span style="color: #7a0874; font-weight: bold;">&#123;</span>
	<span style="color: #666666; font-style: italic;"># Block the forbidden IP addresse</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>client.ip ~ forbidden<span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
        	error <span style="color: #000000;">403</span> <span style="color: #ff0000;">&quot;Forbidden&quot;</span>;
	<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;"># Only cache the following sites</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#40;</span>req.http.host ~ <span style="color: #ff0000;">&quot;(sametmax.com)&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span> 
		<span style="color: #000000; font-weight: bold;">set</span> req.backend = default; 
	<span style="color: #7a0874; font-weight: bold;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span> 
		<span style="color: #7a0874; font-weight: bold;">return</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>pass<span style="color: #7a0874; font-weight: bold;">&#41;</span>; 
	<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;"># Normalize the header, remove the port (in case you're testing this on various TCP ports)</span>
	<span style="color: #000000; font-weight: bold;">set</span> req.http.Host = regsub<span style="color: #7a0874; font-weight: bold;">&#40;</span>req.http.Host, <span style="color: #ff0000;">&quot;:[0-9]+&quot;</span>, <span style="color: #ff0000;">&quot;&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>;
&nbsp;
	<span style="color: #666666; font-style: italic;"># Post requests will not be cached</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>req.http.Authorization <span style="color: #000000; font-weight: bold;">||</span> req.request == <span style="color: #ff0000;">&quot;POST&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
		<span style="color: #7a0874; font-weight: bold;">return</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>pass<span style="color: #7a0874; font-weight: bold;">&#41;</span>;
	<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;"># --- Wordpress specific configuration</span>
&nbsp;
	<span style="color: #666666; font-style: italic;"># Did not cache the RSS feed</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>req.url ~ <span style="color: #ff0000;">&quot;/feed&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
		<span style="color: #7a0874; font-weight: bold;">return</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>pass<span style="color: #7a0874; font-weight: bold;">&#41;</span>;
	<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;"># Blitz hack</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>req.url ~ <span style="color: #ff0000;">&quot;/mu-.*&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
                <span style="color: #7a0874; font-weight: bold;">return</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>pass<span style="color: #7a0874; font-weight: bold;">&#41;</span>;
        <span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
&nbsp;
	<span style="color: #666666; font-style: italic;"># Did not cache the admin and login pages</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>req.url ~ <span style="color: #ff0000;">&quot;/wp-(login|admin)&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
		<span style="color: #7a0874; font-weight: bold;">return</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>pass<span style="color: #7a0874; font-weight: bold;">&#41;</span>;
	<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;"># Remove the &quot;has_js&quot; cookie</span>
	<span style="color: #000000; font-weight: bold;">set</span> req.http.Cookie = regsuball<span style="color: #7a0874; font-weight: bold;">&#40;</span>req.http.Cookie, <span style="color: #ff0000;">&quot;has_js=[^;]+(; )?&quot;</span>, <span style="color: #ff0000;">&quot;&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>;
&nbsp;
	<span style="color: #666666; font-style: italic;"># Remove any Google Analytics based cookies</span>
	<span style="color: #000000; font-weight: bold;">set</span> req.http.Cookie = regsuball<span style="color: #7a0874; font-weight: bold;">&#40;</span>req.http.Cookie, <span style="color: #ff0000;">&quot;__utm.=[^;]+(; )?&quot;</span>, <span style="color: #ff0000;">&quot;&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>;
&nbsp;
	<span style="color: #666666; font-style: italic;"># Remove the Quant Capital cookies (added by some plugin, all __qca)</span>
	<span style="color: #000000; font-weight: bold;">set</span> req.http.Cookie = regsuball<span style="color: #7a0874; font-weight: bold;">&#40;</span>req.http.Cookie, <span style="color: #ff0000;">&quot;__qc.=[^;]+(; )?&quot;</span>, <span style="color: #ff0000;">&quot;&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>;
&nbsp;
	<span style="color: #666666; font-style: italic;"># Remove the wp-settings-1 cookie</span>
	<span style="color: #000000; font-weight: bold;">set</span> req.http.Cookie = regsuball<span style="color: #7a0874; font-weight: bold;">&#40;</span>req.http.Cookie, <span style="color: #ff0000;">&quot;wp-settings-1=[^;]+(; )?&quot;</span>, <span style="color: #ff0000;">&quot;&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>;
&nbsp;
	<span style="color: #666666; font-style: italic;"># Remove the wp-settings-time-1 cookie</span>
	<span style="color: #000000; font-weight: bold;">set</span> req.http.Cookie = regsuball<span style="color: #7a0874; font-weight: bold;">&#40;</span>req.http.Cookie, <span style="color: #ff0000;">&quot;wp-settings-time-1=[^;]+(; )?&quot;</span>, <span style="color: #ff0000;">&quot;&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>;
&nbsp;
	<span style="color: #666666; font-style: italic;"># Remove the wp test cookie</span>
	<span style="color: #000000; font-weight: bold;">set</span> req.http.Cookie = regsuball<span style="color: #7a0874; font-weight: bold;">&#40;</span>req.http.Cookie, <span style="color: #ff0000;">&quot;wordpress_test_cookie=[^;]+(; )?&quot;</span>, <span style="color: #ff0000;">&quot;&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>;
&nbsp;
	<span style="color: #666666; font-style: italic;"># Are there cookies left with only spaces or that are empty?</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>req.http.cookie ~ <span style="color: #ff0000;">&quot;^ *$&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
		    <span style="color: #7a0874; font-weight: bold;">unset</span> req.http.cookie;
	<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;"># Cache the following files extensions </span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>req.url ~ <span style="color: #ff0000;">&quot;\.(css|js|png|gif|jp(e)?g|swf|ico)&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
		<span style="color: #7a0874; font-weight: bold;">unset</span> req.http.cookie;
	<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;"># Normalize Accept-Encoding header and compression</span>
	<span style="color: #666666; font-style: italic;"># https://www.varnish-cache.org/docs/3.0/tutorial/vary.html</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>req.http.Accept-Encoding<span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
		<span style="color: #666666; font-style: italic;"># Do no compress compressed files...</span>
		<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>req.url ~ <span style="color: #ff0000;">&quot;\.(jpg|png|gif|gz|tgz|bz2|tbz|mp3|ogg)$&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
			   	remove req.http.Accept-Encoding;
		<span style="color: #7a0874; font-weight: bold;">&#125;</span> elsif <span style="color: #7a0874; font-weight: bold;">&#40;</span>req.http.Accept-Encoding ~ <span style="color: #ff0000;">&quot;gzip&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
		    	<span style="color: #000000; font-weight: bold;">set</span> req.http.Accept-Encoding = <span style="color: #ff0000;">&quot;gzip&quot;</span>;
		<span style="color: #7a0874; font-weight: bold;">&#125;</span> elsif <span style="color: #7a0874; font-weight: bold;">&#40;</span>req.http.Accept-Encoding ~ <span style="color: #ff0000;">&quot;deflate&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
		    	<span style="color: #000000; font-weight: bold;">set</span> req.http.Accept-Encoding = <span style="color: #ff0000;">&quot;deflate&quot;</span>;
		<span style="color: #7a0874; font-weight: bold;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
			remove req.http.Accept-Encoding;
		<span style="color: #7a0874; font-weight: bold;">&#125;</span>
	<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;"># Check the cookies for wordpress-specific items</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>req.http.Cookie ~ <span style="color: #ff0000;">&quot;wordpress_&quot;</span> <span style="color: #000000; font-weight: bold;">||</span> req.http.Cookie ~ <span style="color: #ff0000;">&quot;comment_&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
		<span style="color: #7a0874; font-weight: bold;">return</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>pass<span style="color: #7a0874; font-weight: bold;">&#41;</span>;
	<span style="color: #7a0874; font-weight: bold;">&#125;</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000; font-weight: bold;">!</span>req.http.cookie<span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
		<span style="color: #7a0874; font-weight: bold;">unset</span> req.http.cookie;
	<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;"># --- End of Wordpress specific configuration</span>
&nbsp;
	<span style="color: #666666; font-style: italic;"># Did not cache HTTP authentication and HTTP Cookie</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>req.http.Authorization <span style="color: #000000; font-weight: bold;">||</span> req.http.Cookie<span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
		<span style="color: #666666; font-style: italic;"># Not cacheable by default</span>
		<span style="color: #7a0874; font-weight: bold;">return</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>pass<span style="color: #7a0874; font-weight: bold;">&#41;</span>;
	<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;"># Define the default grace period to serve cached content</span>
	<span style="color: #000000; font-weight: bold;">set</span> req.grace = 30s;
&nbsp;
	<span style="color: #666666; font-style: italic;"># Cache all others requests</span>
	<span style="color: #7a0874; font-weight: bold;">return</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>lookup<span style="color: #7a0874; font-weight: bold;">&#41;</span>;
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
sub vcl_pipe <span style="color: #7a0874; font-weight: bold;">&#123;</span>
	<span style="color: #7a0874; font-weight: bold;">return</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>pipe<span style="color: #7a0874; font-weight: bold;">&#41;</span>;
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
sub vcl_pass <span style="color: #7a0874; font-weight: bold;">&#123;</span>
	<span style="color: #7a0874; font-weight: bold;">return</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>pass<span style="color: #7a0874; font-weight: bold;">&#41;</span>;
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># The data on which the hashing will take place</span>
sub vcl_hash <span style="color: #7a0874; font-weight: bold;">&#123;</span>
 	hash_data<span style="color: #7a0874; font-weight: bold;">&#40;</span>req.url<span style="color: #7a0874; font-weight: bold;">&#41;</span>;
 	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>req.http.host<span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
     	hash_data<span style="color: #7a0874; font-weight: bold;">&#40;</span>req.http.host<span style="color: #7a0874; font-weight: bold;">&#41;</span>;
 	<span style="color: #7a0874; font-weight: bold;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
     	hash_data<span style="color: #7a0874; font-weight: bold;">&#40;</span>server.ip<span style="color: #7a0874; font-weight: bold;">&#41;</span>;
 	<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;"># If the client supports compression, keep that in a different cache</span>
    	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>req.http.Accept-Encoding<span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
        	hash_data<span style="color: #7a0874; font-weight: bold;">&#40;</span>req.http.Accept-Encoding<span style="color: #7a0874; font-weight: bold;">&#41;</span>;
	<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
	<span style="color: #7a0874; font-weight: bold;">return</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">hash</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>;
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># This function is used when a request is sent by our backend (Nginx server)</span>
sub vcl_fetch <span style="color: #7a0874; font-weight: bold;">&#123;</span>
	<span style="color: #666666; font-style: italic;"># Remove some headers we never want to see</span>
	<span style="color: #7a0874; font-weight: bold;">unset</span> beresp.http.Server;
	<span style="color: #7a0874; font-weight: bold;">unset</span> beresp.http.X-Powered-By;
&nbsp;
	<span style="color: #666666; font-style: italic;"># For static content strip all backend cookies</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>req.url ~ <span style="color: #ff0000;">&quot;\.(css|js|png|gif|jp(e?)g)|swf|ico&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
		<span style="color: #7a0874; font-weight: bold;">unset</span> beresp.http.cookie;
	<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;"># Only allow cookies to be set if we're in admin area</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>beresp.http.Set-Cookie <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> req.url <span style="color: #000000; font-weight: bold;">!</span>~ <span style="color: #ff0000;">&quot;^/wp-(login|admin)&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
        	<span style="color: #7a0874; font-weight: bold;">unset</span> beresp.http.Set-Cookie;
    	<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;"># don't cache response to posted requests or those with basic auth</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span> req.request == <span style="color: #ff0000;">&quot;POST&quot;</span> <span style="color: #000000; font-weight: bold;">||</span> req.http.Authorization <span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
        	<span style="color: #7a0874; font-weight: bold;">return</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>hit_for_pass<span style="color: #7a0874; font-weight: bold;">&#41;</span>;
    	<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
    	<span style="color: #666666; font-style: italic;"># don't cache search results</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span> req.url ~ <span style="color: #ff0000;">&quot;\?s=&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#123;</span>
		<span style="color: #7a0874; font-weight: bold;">return</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>hit_for_pass<span style="color: #7a0874; font-weight: bold;">&#41;</span>;
	<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;"># only cache status ok</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span> beresp.status <span style="color: #000000; font-weight: bold;">!</span>= <span style="color: #000000;">200</span> <span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
		<span style="color: #7a0874; font-weight: bold;">return</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>hit_for_pass<span style="color: #7a0874; font-weight: bold;">&#41;</span>;
	<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;"># A TTL of 24h</span>
	<span style="color: #000000; font-weight: bold;">set</span> beresp.ttl = 24h;
&nbsp;
	<span style="color: #7a0874; font-weight: bold;">return</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>deliver<span style="color: #7a0874; font-weight: bold;">&#41;</span>;
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># The routine when we deliver the HTTP request to the user</span>
<span style="color: #666666; font-style: italic;"># Last chance to modify headers that are sent to the client</span>
sub vcl_deliver <span style="color: #7a0874; font-weight: bold;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>obj.hits <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000;">0</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span> 
		<span style="color: #000000; font-weight: bold;">set</span> resp.http.X-Cache = <span style="color: #ff0000;">&quot;cached&quot;</span>;
	<span style="color: #7a0874; font-weight: bold;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
		<span style="color: #000000; font-weight: bold;">set</span> resp.http.x-Cache = <span style="color: #ff0000;">&quot;uncached&quot;</span>;
	<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;"># Remove some headers: PHP version</span>
	<span style="color: #7a0874; font-weight: bold;">unset</span> resp.http.X-Powered-By;
&nbsp;
	<span style="color: #666666; font-style: italic;"># Remove some headers: Apache version &amp; OS</span>
	<span style="color: #7a0874; font-weight: bold;">unset</span> resp.http.Server;
&nbsp;
	<span style="color: #666666; font-style: italic;"># Remove some heanders: Varnish</span>
	<span style="color: #7a0874; font-weight: bold;">unset</span> resp.http.Via;
	<span style="color: #7a0874; font-weight: bold;">unset</span> resp.http.X-Varnish;
&nbsp;
	<span style="color: #7a0874; font-weight: bold;">return</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>deliver<span style="color: #7a0874; font-weight: bold;">&#41;</span>;
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
sub vcl_init <span style="color: #7a0874; font-weight: bold;">&#123;</span>
 	<span style="color: #7a0874; font-weight: bold;">return</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>ok<span style="color: #7a0874; font-weight: bold;">&#41;</span>;
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
sub vcl_fini <span style="color: #7a0874; font-weight: bold;">&#123;</span>
 	<span style="color: #7a0874; font-weight: bold;">return</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>ok<span style="color: #7a0874; font-weight: bold;">&#41;</span>;
<span style="color: #7a0874; font-weight: bold;">&#125;</span></pre></div></div>

<p>Avant toute chose voici la doc :) : <a href="https://www.varnish-cache.org/docs/3.0/">https://www.varnish-cache.org/docs/3.0/</a><br />
Ce qu&#8217;il faut retenir de ce fichier de règle c&#8217;est les parties normalisation, enlever les cookies inutiles (car si cookie alors pas de cache) et ne pas mettre en cache l&#8217;admin. Cette config tourne actuellement sur S&#038;M.</p>
<p>Un point interressant c&#8217;est le debug, vous pouvez mettre un <em>set resp.http.X-Cache = &#8220;cached&#8221;;</em> et vérifier les header de votre serveur dans le debug de votre navigateur pour savoir si oui ou non la page servit est en cache.</p>
<p><strong>L&#8217;admin varnish en ligne de commande:</strong><br />
Varnish possède une admin en ligne de commande où l&#8217;on peut par exemple purger le cache d&#8217;une ou plusieurs pages.<br />
Tapez <em>varnishadm</em> dans le shell:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">varnishadm
<span style="color: #000000;">200</span>        
<span style="color: #660033;">-----------------------------</span>
Varnish Cache CLI <span style="color: #000000;">1.0</span>
<span style="color: #660033;">-----------------------------</span>
Linux,3.2.0-<span style="color: #000000;">25</span>-virtual,x86_64,-smalloc,-smalloc,-hcritbit
&nbsp;
Type <span style="color: #ff0000;">'help'</span> <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #7a0874; font-weight: bold;">command</span> list.
Type <span style="color: #ff0000;">'quit'</span> to close CLI session.
&nbsp;
varnish<span style="color: #000000; font-weight: bold;">&gt;</span> ban.url <span style="color: #000000; font-weight: bold;">/</span>toto<span style="color: #000000; font-weight: bold;">/</span>ma-page.php</pre></div></div>

<p>Pour purger une page on va utiliser la commande ban.url et y ajouter une partie de l&#8217;url à purger. On peut utiliser un ban en appelant également une url de purge avec Curl ou Wget pour les automations, il y a un excellent article <a href="http://binbash.fr/2011/11/15/purger-le-cache-de-varnish-3/">sur la purge ici.</a></p>
<p><strong>Configurer Nginx:</strong><br />
Une fois varnish installé, on va modifier un peu nginx pour que la liaison puisse se faire. Ci-dessous l&#8217;exemple de notre conf nginx.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">&nbsp;
server <span style="color: #7a0874; font-weight: bold;">&#123;</span>
    listen      <span style="color: #000000;">8080</span>;
    server_name  sametmax.com  ;
    root         <span style="color: #000000; font-weight: bold;">/</span>unrep<span style="color: #000000; font-weight: bold;">/</span>sametmax<span style="color: #000000; font-weight: bold;">/</span>;  <span style="color: #666666; font-style: italic;"># absolute path to your WordPress installation</span>
    index index.php index.html;
    set_real_ip_from        127.0.0.1;
    real_ip_header          X-Forwarded-For;
&nbsp;
    location ~ \.php$ <span style="color: #7a0874; font-weight: bold;">&#123;</span>
        include        <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>nginx<span style="color: #000000; font-weight: bold;">/</span>fastcgi_params;
        fastcgi_pass   127.0.0.1:<span style="color: #000000;">53217</span>;
        fastcgi_index index.php;
        fastcgi_buffers <span style="color: #000000;">8</span> 16k;
        fastcgi_buffer_size 32k;
        fastcgi_param  SCRIPT_FILENAME  <span style="color: #007800;">$document_root</span><span style="color: #007800;">$fastcgi_script_name</span>;
    <span style="color: #7a0874; font-weight: bold;">&#125;</span></pre></div></div>

<p>Pour PHP on utilise spawn-fcgi que l&#8217;on gère avec <a href="http://supervisord.org/">supervisor</a> dont voici la conf dans /etc/supervisord.conf</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#91;</span>program:php5-cgi<span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #007800;">command</span>=<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>spawn-fcgi <span style="color: #660033;">-u</span> adolf <span style="color: #660033;">-n</span> <span style="color: #660033;">-a</span> 127.0.0.1 <span style="color: #660033;">-p</span> <span style="color: #000000;">53217</span> <span style="color: #660033;">-P</span> <span style="color: #000000; font-weight: bold;">/</span>tmp<span style="color: #000000; font-weight: bold;">/</span>fastcgi-php.pid <span style="color: #660033;">-F</span> <span style="color: #000000;">4</span> <span style="color: #660033;">--</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>php-cgi
<span style="color: #007800;">redirect_stderr</span>=<span style="color: #c20cb9; font-weight: bold;">true</span>          ; redirect proc stderr to stdout <span style="color: #7a0874; font-weight: bold;">&#40;</span>default <span style="color: #c20cb9; font-weight: bold;">false</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #007800;">user</span>=sametmax
<span style="color: #007800;">autostart</span>=<span style="color: #c20cb9; font-weight: bold;">true</span>
<span style="color: #007800;">autorestart</span>=<span style="color: #c20cb9; font-weight: bold;">true</span>
<span style="color: #007800;">startsecs</span>=<span style="color: #000000;">10</span>
<span style="color: #007800;">startretries</span>=<span style="color: #000000;">9999999999999</span>
<span style="color: #007800;">stdout_logfile</span>=<span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>log<span style="color: #000000; font-weight: bold;">/</span>php5-cgi<span style="color: #000000; font-weight: bold;">/</span>php5-cgi.log
<span style="color: #007800;">stdout_logfile_maxbytes</span>=10MB   ; max <span style="color: #666666; font-style: italic;"># logfile bytes b4 rotation (default 50MB)</span></pre></div></div>

<p><strong>Pour résumer:</strong></p>
<p>Dans cette configuration Varnish est en front end et va décider quand servir une page prise dans le cache (disque dur ou RAM) et quand intéroger le backend pour servir une nouvelle page.<br />
Sur d&#8217;autres sites à fort trafic on a mis Nginx en front end car il encaisse beaucoup plus les hits et qu&#8217;il fait très bien le boulot pour servir des pages statiques.</p>
<p><strong>Attention!</strong><br />
Même si Varnish n&#8217;est pas compliqué à installer il peut être un vrai casse tête quand il s&#8217;agit de cacher des pages. Pensez donc bien à normaliser vos headers (user-agent, gzip, etc), utilisez le debug.<br />
Bien configuré Varnish vous booste un serveur avec une réélle efficacité, il nous a sauvé 2 sites jusqu&#8217;à présent, ça sera d&#8217;ailleurs un standard sur nos prochains sites.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=4416&amp;md5=f22290422327559763efcf827e1a219f" 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>


