# articles

feed_id: http://sametmax.com/?p=7658
title: A quoi sert Ellipsis en Python ?
uri: A-quoi-sert-Ellipsis-en-Python
url: http://sametmax.com/a-quoi-sert-ellipsis-en-python/
content:
<p>A rien.</p>
<p><br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/><br />
<br/></p>
<p>Nan mais revenez, je déconnais.</p>
<p>Mais, sérieusement, <a href="<br />
http://docs.python.org/3.3/library/constants.html?highlight=ellipsis#Ellipsis">Ellipsis</a>, à la base, ne sert à rien.</p>
<p>Il existe, c&#8217;est tout.</p>
<p>En Python 2:</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;">Ellipsis</span>
<span style="color: #008000;">Ellipsis</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> ... <span style="color: #808080; font-style: italic;"># pas de forme abrégée </span>
  File <span style="color: #483d8b;">&quot;&lt;stdin&gt;&quot;</span>, line <span style="color: #ff4500;">1</span>
    ...
    ^
<span style="color: #008000;">SyntaxError</span>: invalid syntax
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <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: black;">&#91;</span>...<span style="color: black;">&#93;</span> <span style="color: #808080; font-style: italic;"># mais ceci n'est pas une syntaxe error</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&lt;stdin&gt;&quot;</span>, line <span style="color: #ff4500;">1</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #66cc66;">&lt;</span>module<span style="color: #66cc66;">&gt;</span>
<span style="color: #008000;">TypeError</span>: <span style="color: #008000;">range</span> indices must be integers <span style="color: #ff7700;font-weight:bold;">or</span> slices, <span style="color: #ff7700;font-weight:bold;">not</span> ellipsis
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span><span style="color: #008000;">Ellipsis</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'Ellipsis'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">Ellipsis</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># ce truc ne sert à rien</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&lt;stdin&gt;&quot;</span>, line <span style="color: #ff4500;">1</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #66cc66;">&lt;</span>module<span style="color: #66cc66;">&gt;</span>
<span style="color: #008000;">TypeError</span>: <span style="color: #483d8b;">'ellipsis'</span> <span style="color: #008000;">object</span> <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">callable</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">Ellipsis</span> + <span style="color: #008000;">Ellipsis</span> <span style="color: #808080; font-style: italic;"># a rien je vous dis</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&lt;stdin&gt;&quot;</span>, line <span style="color: #ff4500;">1</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #66cc66;">&lt;</span>module<span style="color: #66cc66;">&gt;</span>
<span style="color: #008000;">TypeError</span>: unsupported operand <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>s<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> +: <span style="color: #483d8b;">'ellipsis'</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #483d8b;">'ellipsis'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">Ellipsis</span> <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">Ellipsis</span> <span style="color: #808080; font-style: italic;"># c'est un singleton</span>
<span style="color: #008000;">True</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">bool</span><span style="color: black;">&#40;</span><span style="color: #008000;">Ellipsis</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># c'est comme None, mais en True</span>
<span style="color: #008000;">True</span></pre></div></div>

<p>En Python 3:</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;">Ellipsis</span></pre></div></div>

<p>Comme je vous le disais, ça ne sert à rien.</p>
<p>Du coup on peut en faire ce qu&#8217;on veut ! <a href="http://www.youtube.com/watch?v=E0L8f1IY1Vk">It&#8217;s toasted !</a></p>
<p>Les libs comme NumPy s&#8217;en servent pour faire du slicing étendu. Elles ré-implementent <a href="http://docs.python.org/2/reference/datamodel.html?highlight=__index__#object.__getitem__">__getitem__</a> et quand elles voient <code>Ellipsis</code>, elles interprètent ça comme un &#8220;<code>:</code>&#8221; <a href="http://wiki.scipy.org/Tentative_NumPy_Tutorial">pour toutes les dimensions non spécifiées</a>.</p>
<p>Il y a des gens qui l&#8217;utilisent en lieu et place de <code>pass</code> pour dire &#8220;j&#8217;écrirai ce truc plus tard&#8221;:</p>

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

<p>Bien entendu, ça ne marche qu&#8217;en Python 3.</p>
<p>Personnellement je m&#8217;en sers comme valeur quand j&#8217;ai besoin d&#8217;un truc neutre qui ne soit pas <code>None</code> si <code>None</code> peut être une valeur attendue. Au final quand on veut faire propre, il vaut mieux faire un objet dédié qui s&#8217;appelle <code>NotAValue</code> ou autre, mais le quick and dirty a la vie dure.</p>
<p>Attention, les références récursives sont signalées par le shell Python comme <code>...</code>, mais ça n&#8217;a rien à avoir avec la choucroute :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> l = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> l.<span style="color: black;">append</span><span style="color: black;">&#40;</span>l<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> l
<span style="color: black;">&#91;</span><span style="color: black;">&#91;</span>...<span style="color: black;">&#93;</span><span style="color: black;">&#93;</span></pre></div></div>

 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7658&amp;md5=9b9feb583198a7cc65430795aecad77e" 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=9137
title: Le namedtuple, la structure mal aimée
uri: Le-namedtuple-la-structure-mal-aimée
url: http://sametmax.com/le-namedtuple-la-structure-mal-aimee/
content:
<p>Figurez-vous qu&#8217;on a un chat IRC. Si, si ! freenode#sametmax administré par foxmask, qui est aussi le seul participant du chan.</p>
<p>Bon j&#8217;exagère, d&#8217;ailleurs tout à l&#8217;heure un lien de JEDI_BC m&#8217;a donné l&#8217;idée de cet article : qu&#8217;est-ce qu&#8217;un namedtuple et à quoi ça sert.</p>
<p>Les tuples, vous connaissez : c&#8217;est une séquence ordonnées <strong>non modifiable</strong> d&#8217;éléments hétérogènes.</p>
<p>Pardon, je recommence. C&#8217;est comme une liste, mais plus rapide, et pas modifiable. Ca se créer avec l&#8217;opérateur &#8220;<code>,</code>&#8221; :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> un_tuple = <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>un_tuple<span style="color: black;">&#41;</span>
<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>un_tuple<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>type <span style="color: #483d8b;">'tuple'</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> un_tuple<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
<span style="color: #ff4500;">1</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> un_tuple<span style="color: black;">&#91;</span>:-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
<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: #66cc66;">&gt;&gt;&gt;</span> autre_tuple = <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;pomme&quot;</span>, <span style="color: #ff4500;">1</span>, <span style="color: #008000;">True</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Les parenthèses sont optionnelles mais permettent d&#8217;éviter les ambiguïtés.</p>
<p>Bref, les tuples, c&#8217;est top : on peut les slicer, les indexer, et en plus c&#8217;est très très rapide car non modifiable :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> autre_tuple<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">&quot;banane&quot;</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&lt;stdin&gt;&quot;</span>, line <span style="color: #ff4500;">1</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #66cc66;">&lt;</span>module<span style="color: #66cc66;">&gt;</span>
<span style="color: #008000;">TypeError</span>: <span style="color: #483d8b;">'tuple'</span> <span style="color: #008000;">object</span> does <span style="color: #ff7700;font-weight:bold;">not</span> support item assignment</pre></div></div>

<p>Le tuple est donc une bonne alternative aux listes si on sait que le contenu ne bougera pas. Ca prend moins de mémoire, c&#8217;est plus rapide, c&#8217;est tout aussi flexible, et comme c&#8217;est un itérable on peut le plugger un peu partout.</p>
<p>Un gros défaut du tuple, néanmoins, c&#8217;est l&#8217;absence d&#8217;attributs nommés. Il faut connaitre les indices des valeurs, et c&#8217;est pas évident à lire si le tuple est gros.</p>
<p>Pour cette raison, la lib standard vient avec le namedtuple, qui est simplement un tuple dont les valeurs sont nommées. </p>
<p>Ca s&#8217;utilise en deux étapes. D&#8217;abord, définir un nouveau type de namedtuple avec la liste des attributs qu&#8217;il va contenir. Un peu comme définir une classe :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">collections</span> <span style="color: #ff7700;font-weight:bold;">import</span> namedtuple
<span style="color: #66cc66;">&gt;&gt;&gt;</span> Joueur = namedtuple<span style="color: black;">&#40;</span><span style="color: #483d8b;">'Joueur'</span>, <span style="color: black;">&#91;</span><span style="color: #483d8b;">'nom'</span>, <span style="color: #483d8b;">'age'</span>, <span style="color: #483d8b;">'signe_particulier'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>À partir de là nous avons une nouvelle &#8220;classe&#8221; de namedtuple appelée <code>Joueur</code> qui peut créer des namedtuples avec 3 attributs : &#8216;nom&#8217;, &#8216;age&#8217; et &#8216;signe_particulier&#8217;.</p>
<p>Et ça s&#8217;utilise comme un tuple :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> jdg = Joueur<span style="color: black;">&#40;</span><span style="color: #483d8b;">'M. Grenier'</span>, <span style="color: #ff4500;">31</span>, <span style="color: #483d8b;">'Un langage fleuri'</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> jdg<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
<span style="color: #483d8b;">'M. Grenier'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> nom, age, signe = jdg
<span style="color: #66cc66;">&gt;&gt;&gt;</span> nom
<span style="color: #483d8b;">'M. Grenier'</span></pre></div></div>

<p>Mais aussi comme un objet en read-only :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> jdg.<span style="color: black;">nom</span>
<span style="color: #483d8b;">'M. Grenier'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> sam = Joueur<span style="color: black;">&#40;</span>nom=<span style="color: #483d8b;">&quot;Sam&quot;</span>, age=<span style="color: #483d8b;">&quot;Tu sauras pas&quot;</span>, signe_particulier=<span style="color: #483d8b;">&quot;Est parfaitement impartial&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> sam.<span style="color: black;">age</span>
<span style="color: #483d8b;">'Tu sauras pas'</span></pre></div></div>

 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9137&amp;md5=ed2d28c21fb90544560dcee586496be4" 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=9143
title: Et pour quelques astuces de plus
uri: Et-pour-quelques-astuces-de-plus
url: http://sametmax.com/et-pour-quelques-astuces-de-plus/
content:
<p>Sublime Text n&#8217;en fini pas d&#8217;être sublime.</p>
<p>Depuis <a href="http://sametmax.com/10-astuces-pour-sublime-text-2/">le dernier article</a>, j&#8217;ai découvert d&#8217;autres trucs super géniaux.</p>
<h2>Echanger deux selections</h2>
<p><kbd>Ctrl</kbd> + <kbd>T</kbd>.</p>
<p><a href="media/488d10df.swap.gif" data-original-source="http://sametmax.com/wp-content/uploads/2014/02/swap.gif"><img src="media/488d10df.swap.gif" data-original-source="http://sametmax.com/wp-content/uploads/2014/02/swap.gif" alt="" title="swap" width="700" height="400" class="aligncenter size-full wp-image-9144" /></a></p>
<h2>Selection en colonne</h2>
<p><kbd>Shift</kbd> + Clic droit.</p>
<p><a href="media/be17a9c1.selection_verticale.gif" data-original-source="http://sametmax.com/wp-content/uploads/2014/02/selection_verticale.gif"><img src="media/be17a9c1.selection_verticale.gif" data-original-source="http://sametmax.com/wp-content/uploads/2014/02/selection_verticale.gif" alt="" title="selection_verticale" width="700" height="400" class="aligncenter size-full wp-image-9145" /></a></p>
<h2>Selection similaires</h2>
<p><kbd>Ctrl</kbd> + D</p>
<p><a href="media/69753f11.select_alike.gif" data-original-source="http://sametmax.com/wp-content/uploads/2014/02/select_alike.gif"><img src="media/69753f11.select_alike.gif" data-original-source="http://sametmax.com/wp-content/uploads/2014/02/select_alike.gif" alt="" title="select_alike" width="700" height="400" class="aligncenter size-full wp-image-9146" /></a></p>
<p>Attention, ça ne marche pas quand le champ &#8220;recherche&#8221; est activé.</p>
<h2>Déplacer une ligne</h2>
<p><kbd>Shift</kbd> + <kbd>Ctrl</kbd> + Flèche haut ou bas.</p>
<p><a href="media/2dd1934a.move_line.gif" data-original-source="http://sametmax.com/wp-content/uploads/2014/02/move_line.gif"><img src="media/2dd1934a.move_line.gif" data-original-source="http://sametmax.com/wp-content/uploads/2014/02/move_line.gif" alt="" title="move_line" width="700" height="400" class="aligncenter size-full wp-image-9147" /></a></p>
<h2>Supprimer une ligne</h2>
<p><kbd>Ctrl</kbd> + <kbd>k</kbd> deux fois pour supprimer la ligne après le curseur. On rajoute <kbd>shift</kbd> pour supprimer la ligne complete.</p>
<p><a href="media/275426c0.delete.gif" data-original-source="http://sametmax.com/wp-content/uploads/2014/02/delete.gif"><img src="media/275426c0.delete.gif" data-original-source="http://sametmax.com/wp-content/uploads/2014/02/delete.gif" alt="" title="delete" width="700" height="400" class="aligncenter size-full wp-image-9148" /></a></p>
<p>Je suppose que sous Mac plein de raccourcis sont différents avec des touches commandes à la place du shift et autre&#8230;</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9143&amp;md5=6327ff501a52beca02f2a3b7e7c43a91" 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=9165
title: Sondage! Aimeriez-vous un espace petites-annonces chez S&M ?
uri: Sondage-Aimeriez-vous-un-espace-petites-annonces-chez-S-M
url: http://sametmax.com/sondage-aimeriez-vous-un-espace-petites-annonces-chez-sm/
content:
<p>Pendant que Sam vous mijotte des bons petits <a href="http://sametmax.com/grosse-mise-a-jour-de-la-partie-cours-et-tutos/">tutos</a> à se lécher les babines moi je vais vour divertir un peu l&#8217;oignon avec ce petit vote.</p>
<p>On a quelques e-mails par mois assez surprenants, certains nous demandent si on ne veut pas bosser pour eux, d&#8217;autres veulent faire la publicité de leur app/produit, d&#8217;autres encore aimeraient nous rencontrer, voire même certaines coucher avec moi (ah non&#8230; merde)</p>
<p>On ne peut pas répondre favorablement à ces requêtes et c&#8217;est peut-être l&#8217;occasion de permettre à certains d&#8217;entre-vous d&#8217;échanger, vendre, se rencontrer via une sorte de pages jaunes/craiglist/ads (appelez ça comme vous voulez).</p>
<p>En gros des petites-annonces dans lesquelles nous définirons des catégories précises (on ne veut pas d&#8217;annonce pour vendre la recette miracle pour la repousse de la moustache).</p>
<p>On préfère vous demander avant car on estime que c&#8217;est une bonne chose de proposer plutôt que d&#8217;imposer. Et puis pour tâter le potentiel.</p>
<p>Les annonces sont bien évidement gratoches, on mettra peut-être des quotas si il y a des abus.</p>
<p><strong>Quelques catégories pour donner une idée:</strong><br />
- Lans (parties)<br />
- hack parties<br />
- ventes de matos info<br />
- trucs geek (gadgets, etc)<br />
- demande de cours d&#8217;info<br />
- donne des cours d&#8217;info<br />
- donne des cours de math<br />
- sallons info<br />
- propositions de collaboration<br />
- projets de conquête du monde<br />
- demande d&#8217;aide sur des sujets particuliers<br />
etc.</p>
<p>On a pas encore de liste précise des catégories mais il y a de quoi faire dans notre domaine. Si vous avez des idées quand aux catégories n&#8217;hésitez pas, balancez !</p>
<p>Aller, détente&#8230;.</p>
Note: There is a poll embedded within this post, please visit the site to participate in this post's poll.
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9165&amp;md5=88b8ba605c9a1a28f3d2ed9f555b5d7b" 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=9154
title: Mettez des fonctions dans vos structures de données
uri: Mettez-des-fonctions-dans-vos-structures-de-données
url: http://sametmax.com/mettez-des-fonctions-dans-vos-structures-de-donnees/
content:
<p>En Python les fonctions sont des objets de premier ordre. On peut les manipuler, copier les références, les supprimer&#8230;</p>
<p>Exemple :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># On definit une fonction.</span>
<span style="color: #808080; font-style: italic;"># Jusqu'ici tout va bien...</span>
<span style="color: #ff7700;font-weight:bold;">def</span> pizza<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;miam&quot;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>pizza<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;">## miam</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On peut assigner la référence de</span>
<span style="color: #808080; font-style: italic;"># la fonction à une variable.</span>
delice = pizza
&nbsp;
<span style="color: #808080; font-style: italic;"># Et utiliser la fonction depuis la variable</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>delice<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;">## miam</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On peut même supprimer la variable</span>
<span style="color: #808080; font-style: italic;"># originale.</span>
<span style="color: #ff7700;font-weight:bold;">del</span> pizza
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>delice<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;">## miam</span>
&nbsp;
pizza<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
---------------------------------------------------------------------------
<span style="color: #008000;">NameError</span>                                 Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>ipython-input-<span style="color: #ff4500;">3</span>-dc0f1f08233f<span style="color: #66cc66;">&gt;</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #66cc66;">&lt;</span>module<span style="color: #66cc66;">&gt;</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
----<span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">1</span> pizza<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #008000;">NameError</span>: name <span style="color: #483d8b;">'pizza'</span> <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #ff7700;font-weight:bold;">not</span> defined</pre></div></div>

<p>La fonction est un objet ordinaire qui peut donc se mettre dans une variable, mais aussi se passer en paramètre, se retourner comme valeur, etc. J&#8217;ai déjà expliqué ça dans <a href="http://sametmax.com/comprendre-les-decorateurs-python-pas-a-pas-partie-1/">le tuto sur les décorateurs</a> plus en détail, mais un rappel ne fait pas de mal.</p>
<p>Cela veut dire que l&#8217;on peut mettre la référence d&#8217;une fonction dans une structure de données.</p>
<p>Par exemple dans une liste :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> pizza<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;miam&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> epinard<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;miam aussi&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> arepas<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;decidement tout est miam&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On met les fonctions dans la liste :</span>
liste_de_fonctions = <span style="color: black;">&#91;</span>pizza, epinard, arepas<span style="color: black;">&#93;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Et du coup on peut boucler sur les fonctions</span>
<span style="color: #ff7700;font-weight:bold;">for</span> func <span style="color: #ff7700;font-weight:bold;">in</span> liste_de_fonctions:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>func<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;">## miam</span>
<span style="color: #808080; font-style: italic;">## miam aussi</span>
<span style="color: #808080; font-style: italic;">## decidement tout est miam</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Le monde des listes s'ouvre à vous</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>liste_de_fonctions<span style="color: black;">&#91;</span>-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</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;">## decidement tout est miam</span>
&nbsp;
f1, f2 = liste_de_fonctions<span style="color: black;">&#91;</span>:<span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>f2<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;">## miam aussi</span></pre></div></div>

<p>Mais aussi dans un dictionnaire :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">dico_de_fonction = <span style="color: black;">&#123;</span>
    <span style="color: #483d8b;">&quot;choix1&quot;</span>: pizza,
    <span style="color: #483d8b;">&quot;choix2&quot;</span>: epinard,
    <span style="color: #483d8b;">&quot;choix3&quot;</span>: arepas
<span style="color: black;">&#125;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>dico_de_fonction<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;choix2&quot;</span><span style="color: black;">&#93;</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;">## miam aussi</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> key, func <span style="color: #ff7700;font-weight:bold;">in</span> dico_de_fonction.<span style="color: black;">items</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;%s: %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>key, func<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">## choix1: miam</span>
<span style="color: #808080; font-style: italic;">## choix3: decidement tout est miam</span>
<span style="color: #808080; font-style: italic;">## choix2: miam aussi</span></pre></div></div>

<p>En fait, ça marche avec tout (les fonctions sont hashables) : les sets, les tuples, les <a href="http://sametmax.com/implementer-une-fenetre-glissante-en-python-avec-un-deque/">deques</a>&#8230;</p>
<p>On peut même faire un générateur qui yield des fonctions :</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;">random</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> fonctions_aleatoires<span style="color: black;">&#40;</span>nombre, fonctions=liste_de_fonctions<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>nombre<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #dc143c;">random</span>.<span style="color: black;">choice</span><span style="color: black;">&#40;</span>liste_de_fonctions<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> func <span style="color: #ff7700;font-weight:bold;">in</span> fonctions_aleatoires<span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>func<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;">## miam aussi</span>
<span style="color: #808080; font-style: italic;">## miam</span>
<span style="color: #808080; font-style: italic;">## decidement tout est miam</span>
<span style="color: #808080; font-style: italic;">## miam</span>
<span style="color: #808080; font-style: italic;">## miam aussi</span></pre></div></div>

<p>Python n&#8217;a certes pas les capacités de Lisp ou même Javascript pour faire de la programmation fonctionnelle, mais les fonctions restent des objets très puissants dans ce langage.</p>
<p>D&#8217;ailleurs, cet article est valable aussi pour les classes et les modules :)</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9154&amp;md5=c445d8ff342a150f78bb78f1ea952109" 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=9176
title: Un gros guide bien gras sur les tests unitaires en Python, partie 2
uri: Un-gros-guide-bien-gras-sur-les-tests-unitaires-en-Python-partie-2
url: http://sametmax.com/un-gros-guide-bien-gras-sur-les-tests-unitaires-en-python-partie-2/
content:
<p><a href="http://sametmax.com/un-gros-guide-bien-gras-sur-les-tests-unitaires-en-python-partie-1/">La partie précédente</a> vous a donné une vague idée de ce qu&#8217;était les tests unittaires, à quoi ça servait, et quelle forme ça avait.</p>
<p>Dans cette partie, nous allons aborder comment on rédige des tests unitaires avec la lib de standard de Python.</p>
<p>En effet, bien qu&#8217;on puisse se contenter de faire des <code>assert</code> et attendre que ça plante, ce n&#8217;est pas un moyen très efficace de faire ses tests. Des bibliothèques existent donc pour rendre le test plus puissant. En Python, c&#8217;est le module <a href="http://docs.python.org/2/library/unittest.html">unittest</a> qui s&#8217;en charge.</p>
<p>Article long, musique, tout ça&#8230;</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="420" height="315" src="//www.youtube.com/embed/BR4yQFZK9YM" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<h2>Le test le plus simple</h2>
<p>Pour l&#8217;exercice nous allons utiliser une fonction à tester qui soit un peu plus réaliste. Par exemple, les dictionnaires ont une méthode <code>get()</code> qui permet de récupérer une élément du dictionnaire. Si celui-ci n&#8217;existe pas, une valeur par défaut est retournée :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> simple_comme_bonjour = <span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;pomme&quot;</span>: <span style="color: #483d8b;">&quot;banane&quot;</span>, <span style="color: #483d8b;">&quot;geographie&quot;</span>: <span style="color: #483d8b;">&quot;litterature&quot;</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> simple_comme_bonjour.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;pomme&quot;</span>, <span style="color: #483d8b;">&quot;je laisse la main&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">&quot;banane&quot;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> simple_comme_bonjour.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;kamoulox&quot;</span>, <span style="color: #483d8b;">&quot;je laisse la main&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">&quot;je laisse la main&quot;</span></pre></div></div>

<p>Une telle fonction n&#8217;existe pas pour les itérables, nous allons donc en créer une :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> get<span style="color: black;">&#40;</span>lst, index, default=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
        Retourne l'élément de `lst` situé à `index`.
&nbsp;
        Si aucun n'élément ne se trouve à `index`,
        retourne la valeur par défaut.
    &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> lst<span style="color: black;">&#91;</span>index<span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">IndexError</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> default</pre></div></div>

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

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> simple_comme_bonjour = <span style="color: black;">&#40;</span><span style="color: #483d8b;">'pomme'</span>, <span style="color: #483d8b;">'banane'</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> get<span style="color: black;">&#40;</span>simple_comme_bonjour, <span style="color: #ff4500;">0</span>, <span style="color: #483d8b;">&quot;je laisse la main&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'pomme'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> get<span style="color: black;">&#40;</span>simple_comme_bonjour, <span style="color: #ff4500;">1000</span>, <span style="color: #483d8b;">&quot;je laisse la main&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'je laisse la main'</span></pre></div></div>

<p>Afin de sécuriser les futures améliorations de cette fonction, nous allons lui adjoindre des tests unitaires. Utiliser le module <code>unitest</code> est beaucoup plus verbeux que faire des <code>assert</code>, il suppose de faire une classe qui va regrouper tous les tests qu&#8217;on veut faire :</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;">unittest</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Le code à tester doit être importable. On</span>
<span style="color: #808080; font-style: italic;"># verra dans une autre partie comment organiser</span>
<span style="color: #808080; font-style: italic;"># son projet pour cela.</span>
<span style="color: #ff7700;font-weight:bold;">from</span> mon_module <span style="color: #ff7700;font-weight:bold;">import</span> get
&nbsp;
<span style="color: #808080; font-style: italic;"># Cette classe est un groupe de tests. Son nom DOIT commencer</span>
<span style="color: #808080; font-style: italic;"># par 'Test' et la classe DOIT hériter de unittest.TestCase.</span>
<span style="color: #ff7700;font-weight:bold;">class</span> TestFonctionGet<span style="color: black;">&#40;</span><span style="color: #dc143c;">unittest</span>.<span style="color: black;">TestCase</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;"># Chaque méthode dont le nom commence par 'test_'</span>
    <span style="color: #808080; font-style: italic;"># est un test.</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> test_get_element<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
&nbsp;
        simple_comme_bonjour = <span style="color: black;">&#40;</span><span style="color: #483d8b;">'pomme'</span>, <span style="color: #483d8b;">'banane'</span><span style="color: black;">&#41;</span>
        element = get<span style="color: black;">&#40;</span>simple_comme_bonjour, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Le test le plus simple est un test d'égalité. On se</span>
        <span style="color: #808080; font-style: italic;"># sert de la méthode assertEqual pour dire que l'on</span>
        <span style="color: #808080; font-style: italic;"># s'attend à ce que les deux éléments soient égaux. Sinon</span>
        <span style="color: #808080; font-style: italic;"># le test échoue.</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertEqual</span><span style="color: black;">&#40;</span>element, <span style="color: #483d8b;">'pomme'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Ceci lance le test si on exécute le script</span>
<span style="color: #808080; font-style: italic;"># directement.</span>
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    <span style="color: #dc143c;">unittest</span>.<span style="color: black;">main</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>On met tout ça dans un fichier nommé &#8220;test_quelquechose&#8221;, et on l&#8217;exécute :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ python test_get.py
.
<span style="color: #660033;">----------------------------------------------------------------------</span>
Ran <span style="color: #000000;">1</span> <span style="color: #7a0874; font-weight: bold;">test</span> <span style="color: #000000; font-weight: bold;">in</span> 0.000s
&nbsp;
OK</pre></div></div>

<p>Cela signifie qu&#8217;un test a été exécuté (il y a un point affiché par test). Il n&#8217;y a eu aucune erreur.</p>
<p>Ajoutons un test pour essayer le cas où l&#8217;élément n&#8217;existe pas :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> TestFonctionGet<span style="color: black;">&#40;</span><span style="color: #dc143c;">unittest</span>.<span style="color: black;">TestCase</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> test_get_element<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        simple_comme_bonjour = <span style="color: black;">&#40;</span><span style="color: #483d8b;">'pomme'</span>, <span style="color: #483d8b;">'banane'</span><span style="color: black;">&#41;</span>
        element = get<span style="color: black;">&#40;</span>simple_comme_bonjour, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertEqual</span><span style="color: black;">&#40;</span>element, <span style="color: #483d8b;">'pomme'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Il faut choisir un nom explicite pour chaque méthode de test</span>
    <span style="color: #808080; font-style: italic;"># car ça aide à débugger.</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> test_element_manquant<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        simple_comme_bonjour = <span style="color: black;">&#40;</span><span style="color: #483d8b;">'pomme'</span>, <span style="color: #483d8b;">'banane'</span><span style="color: black;">&#41;</span>
        element = get<span style="color: black;">&#40;</span>simple_comme_bonjour, <span style="color: #ff4500;">1000</span>, <span style="color: #483d8b;">'Je laisse la main'</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertEqual</span><span style="color: black;">&#40;</span>element, <span style="color: #483d8b;">'Je laisse la main'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>La sortie nous montre maintenant deux tests passés sans erreur :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ python test_get.py
..
<span style="color: #660033;">----------------------------------------------------------------------</span>
Ran <span style="color: #000000;">2</span> tests <span style="color: #000000; font-weight: bold;">in</span> 0.001s
&nbsp;
OK</pre></div></div>

<h2>Erreur durant le test</h2>
<p>Il y a deux types d&#8217;erreur : une erreur logique (le code plante) ou un test qui échoue.</p>
<p>Commençons par le premier cas. Je rajoute une erreur à la noix :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> TestFonctionGet<span style="color: black;">&#40;</span><span style="color: #dc143c;">unittest</span>.<span style="color: black;">TestCase</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> test_get_element<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        simple_comme_bonjour = <span style="color: black;">&#40;</span><span style="color: #483d8b;">'pomme'</span>, <span style="color: #483d8b;">'banane'</span><span style="color: black;">&#41;</span>
        element = get<span style="color: black;">&#40;</span>simple_comme_bonjour, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertEqual</span><span style="color: black;">&#40;</span>element, <span style="color: #483d8b;">'pomme'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> test_element_manquant<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        simple_comme_bonjour = <span style="color: black;">&#40;</span><span style="color: #483d8b;">'pomme'</span>, <span style="color: #483d8b;">'banane'</span><span style="color: black;">&#41;</span>
        element = get<span style="color: black;">&#40;</span>simple_comme_bonjour, <span style="color: #ff4500;">1000</span>, <span style="color: #483d8b;">'Je laisse la main'</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertEqual</span><span style="color: black;">&#40;</span>element, <span style="color: #483d8b;">'Je laisse la main'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Ce code ne peut pas marcher car il n'y a pas 1000</span>
    <span style="color: #808080; font-style: italic;"># éléments dans mon tuple.</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> test_avec_error<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        simple_comme_bonjour = <span style="color: black;">&#40;</span><span style="color: #483d8b;">'pomme'</span>, <span style="color: #483d8b;">'banane'</span><span style="color: black;">&#41;</span>
        simple_comme_bonjour<span style="color: black;">&#91;</span><span style="color: #ff4500;">1000</span><span style="color: black;">&#93;</span></pre></div></div>

<p>Et zou :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ python test_get.py
E..
======================================================================
ERROR: test_avec_error <span style="color: #7a0874; font-weight: bold;">&#40;</span>__main__.TestFonctionGet<span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #660033;">----------------------------------------------------------------------</span>
Traceback <span style="color: #7a0874; font-weight: bold;">&#40;</span>most recent call <span style="color: #c20cb9; font-weight: bold;">last</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>:
  File <span style="color: #ff0000;">&quot;test_get.py&quot;</span>, line <span style="color: #000000;">40</span>, <span style="color: #000000; font-weight: bold;">in</span> test_avec_error
    simple_comme_bonjour<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">1000</span><span style="color: #7a0874; font-weight: bold;">&#93;</span>
IndexError: tuple index out of range
&nbsp;
<span style="color: #660033;">----------------------------------------------------------------------</span>
Ran <span style="color: #000000;">3</span> tests <span style="color: #000000; font-weight: bold;">in</span> 0.001s
&nbsp;
FAILED <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #007800;">errors</span>=<span style="color: #000000;">1</span><span style="color: #7a0874; font-weight: bold;">&#41;</span></pre></div></div>

<p>Cette fois Python lance bien 3 tests, mais un génère une erreur. Il me signale laquelle par un &#8220;E&#8221; et donne la stacktrace qui permet de débugger le problème.</p>
<p>Vous voyez ici le premier intérêt d&#8217;utiliser un outil fait pour les tests plutôt que des <code>assert</code> à la main : Python n&#8217;a pas arrêté au premier plantage. Tous les tests ont été exécutés. Cela permet de savoir précisément quels tests parmi tous ceux que vous avez, sont touchés, et lesquels passent.</p>
<p>Retirons l&#8217;erreur logique, et ajoutons un un test qui échoue. Un test qui échoue c&#8217;est quand une méthode <code>assertQuelquechose</code> s’aperçoit que les valeurs ne correspondent pas à ce que le test voudrait.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> TestFonctionGet<span style="color: black;">&#40;</span><span style="color: #dc143c;">unittest</span>.<span style="color: black;">TestCase</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> test_get_element<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        simple_comme_bonjour = <span style="color: black;">&#40;</span><span style="color: #483d8b;">'pomme'</span>, <span style="color: #483d8b;">'banane'</span><span style="color: black;">&#41;</span>
        element = get<span style="color: black;">&#40;</span>simple_comme_bonjour, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertEqual</span><span style="color: black;">&#40;</span>element, <span style="color: #483d8b;">'pomme'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> test_element_manquant<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        simple_comme_bonjour = <span style="color: black;">&#40;</span><span style="color: #483d8b;">'pomme'</span>, <span style="color: #483d8b;">'banane'</span><span style="color: black;">&#41;</span>
        element = get<span style="color: black;">&#40;</span>simple_comme_bonjour, <span style="color: #ff4500;">1000</span>, <span style="color: #483d8b;">'Je laisse la main'</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertEqual</span><span style="color: black;">&#40;</span>element, <span style="color: #483d8b;">'Je laisse la main'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> test_avec_echec<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        simple_comme_bonjour = <span style="color: black;">&#40;</span><span style="color: #483d8b;">'pomme'</span>, <span style="color: #483d8b;">'banane'</span><span style="color: black;">&#41;</span>
        element = get<span style="color: black;">&#40;</span>simple_comme_bonjour, <span style="color: #ff4500;">1000</span>, <span style="color: #483d8b;">'Je laisse la main'</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># Ici j'ajoute ARTIFICIELLEMENT une erreur, mais on est bien d'accord</span>
        <span style="color: #808080; font-style: italic;"># que normalement, si ça échoue ici, c'est que votre code ne se comporte</span>
        <span style="color: #808080; font-style: italic;"># pas comme prévu. Personne ne nique ses tests volontairement, sauf</span>
        <span style="color: #808080; font-style: italic;"># les rédacteurs de tutos et les étudiants en histoire de l'art.</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertEqual</span><span style="color: black;">&#40;</span>element, <span style="color: #483d8b;">'Je tres clair, Luc'</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># element ne sera pas égal à &quot;Je tres clair, Luc&quot;, il sera égal à</span>
        <span style="color: #808080; font-style: italic;"># 'Je laisse la main'. assertEqual va s'en rendre compte et va</span>
        <span style="color: #808080; font-style: italic;"># déclarer que le test a échoué, puisque qu'elle vérifie l'égalité.</span></pre></div></div>

<p>Et voici là nouvelle sortie :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ python test_get.py
F..
======================================================================
FAIL: test_avec_echec <span style="color: #7a0874; font-weight: bold;">&#40;</span>__main__.TestFonctionGet<span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #660033;">----------------------------------------------------------------------</span>
Traceback <span style="color: #7a0874; font-weight: bold;">&#40;</span>most recent call <span style="color: #c20cb9; font-weight: bold;">last</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>:
  File <span style="color: #ff0000;">&quot;test_get.py&quot;</span>, line <span style="color: #000000;">45</span>, <span style="color: #000000; font-weight: bold;">in</span> test_avec_echec
    self.assertEqual<span style="color: #7a0874; font-weight: bold;">&#40;</span>element, <span style="color: #ff0000;">'Je tres clair, Luc'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
AssertionError: <span style="color: #ff0000;">'Je laisse la main'</span> <span style="color: #000000; font-weight: bold;">!</span>= <span style="color: #ff0000;">'Je tres clair, Luc'</span>
- Je laisse la main
+ Je tres clair, Luc
&nbsp;
&nbsp;
<span style="color: #660033;">----------------------------------------------------------------------</span>
Ran <span style="color: #000000;">3</span> tests <span style="color: #000000; font-weight: bold;">in</span> 0.002s
&nbsp;
FAILED <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #007800;">failures</span>=<span style="color: #000000;">1</span><span style="color: #7a0874; font-weight: bold;">&#41;</span></pre></div></div>

<p>L&#8217;échec est noté avec un F (pour Fail), et on vous donne le nom du test qui a échoué (c&#8217;est pour ça que je vous recommande de choisir un bon nom pour chaque test).</p>
<p>Là ça devient beaucoup plus intéressant qu&#8217;avec un <code>assert</code> à la main car vous voyez que non seulement on vous dit où est l&#8217;erreur, non seulement Python ne plante pas à la première erreur, mais en plus vous avez des informations supplémentaires.</p>
<p>Ici, cette information est :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">AssertionError: <span style="color: #ff0000;">'Je laisse la main'</span> <span style="color: #000000; font-weight: bold;">!</span>= <span style="color: #ff0000;">'Je tres clair, Luc'</span>
- Je laisse la main
+ Je tres clair, Luc</pre></div></div>

<p>On vous dit très explicitement que c&#8217;est un échec sur une égalité, et voici les deux valeurs testées. Cela vous permet de rapidement identifier ce qui a merdé.</p>
<p>Il existe de nombreuses méthodes <code>assertTruc</code>, et chacune d&#8217;elles produit des informations différentes en cas d&#8217;échec.</p>
<h2>Ah, certes</h2>
<p>Il y a pas mal de méthodes <code>assertBidule</code>. En rédigeant ce tuto, sous Python 3, j&#8217;ai fait ça :</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: black;">&#91;</span><span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">dir</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;">if</span> x.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'assert'</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
assertAlmostEqual
assertAlmostEquals
assertCountEqual
assertDictContainsSubset
assertDictEqual
assertEqual
assertEquals
assertFalse
assertGreater
assertGreaterEqual
assertIn
assertIs
assertIsInstance
assertIsNone
assertIsNot
assertIsNotNone
assertLess
assertLessEqual
assertListEqual
assertMultiLineEqual
assertNotAlmostEqual
assertNotAlmostEquals
assertNotEqual
assertNotEquals
assertNotIn
assertNotIsInstance
assertNotRegex
assertRaises
assertRaisesRegex
assertRaisesRegexp
assertRegex
assertRegexpMatches
assertSequenceEqual
assertSetEqual
assertTrue
assertTupleEqual
assertWarns
assertWarnsRegex</pre></div></div>

<p>Selon votre installation de Python, vous en aurez plus où moins de nombreuses, et je vous invite à vous taper <a href="http://docs.python.org/2/library/unittest.html?highlight=unittest2">la doc</a> pour voir tout ce qui s&#8217;offre à vous.</p>
<p>Voici quelques exemples des possibilités qui s&#8217;offrent à vous :</p>
<p><strong>assertAlmostEqual</strong></p>
<p>Va vérifier qu&#8217;un nombre est presque égal à un autre, à un arrondi près.</p>
<p><strong>assertDictContainsSubset</strong></p>
<p>Va vérifier que toutes les paires clé/valeur d&#8217;un dico sont contenues dans un autre.</p>
<p><strong>assertRaises</strong></p>
<p>Va vérifier que la fonction va lever une exception.</p>
<p><strong>assertRegex</strong></p>
<p>Va vérifier que la chaîne est validée par la regex donnée.</p>
<h2>Setup et TearDown</h2>
<p>Comme vous avez pu le constater dans notre exemple, à chaque test on recrée le tuple <code>simple_comme_bonjour = ('pomme', 'banane')</code>. Ce n&#8217;est pas très pratique. D&#8217;autant plus qu&#8217;on pourrait avoir des choses bien plus compliquées comme la connexion à une base de données ou une génération de données aléatoires.</p>
<p>Les méthodes <code>setUp</code> et <code>tearDown</code> sont là pour y pallier. Elles permettent respectivement de lancer un code avant chaque test et après chaque test.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> TestFonctionGet<span style="color: black;">&#40;</span><span style="color: #dc143c;">unittest</span>.<span style="color: black;">TestCase</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;"># Cette méthode sera appelée avant chaque test.</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> setUp<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">simple_comme_bonjour</span> = <span style="color: black;">&#40;</span><span style="color: #483d8b;">'pomme'</span>, <span style="color: #483d8b;">'banane'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Cette méthode sera appelée après chaque test.</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> tearDown<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Nettoyage !'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> test_get_element<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;"># plus besoin de créer le tuple ici</span>
        element = get<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">simple_comme_bonjour</span>, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertEqual</span><span style="color: black;">&#40;</span>element, <span style="color: #483d8b;">'pomme'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> test_element_manquant<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        element = get<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">simple_comme_bonjour</span>, <span style="color: #ff4500;">1000</span>, <span style="color: #483d8b;">'Je laisse la main'</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertEqual</span><span style="color: black;">&#40;</span>element, <span style="color: #483d8b;">'Je laisse la main'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> test_avec_echec<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        element = get<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">simple_comme_bonjour</span>, <span style="color: #ff4500;">1000</span>, <span style="color: #483d8b;">'Je laisse la main'</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertEqual</span><span style="color: black;">&#40;</span>element, <span style="color: #483d8b;">'Je tres clair, Luc'</span><span style="color: black;">&#41;</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">$ python test_get.<span style="color: black;">py</span>
Nettoyage <span style="color: #66cc66;">!</span>
FNettoyage <span style="color: #66cc66;">!</span>
.<span style="color: black;">Nettoyage</span> <span style="color: #66cc66;">!</span>
.
======================================================================
FAIL: test_avec_echec <span style="color: black;">&#40;</span><span style="color: #dc143c;">__main__</span>.<span style="color: black;">TestFonctionGet</span><span style="color: black;">&#41;</span>
----------------------------------------------------------------------
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;test_get.py&quot;</span>, line <span style="color: #ff4500;">37</span>, <span style="color: #ff7700;font-weight:bold;">in</span> test_avec_echec
    <span style="color: #008000;">self</span>.<span style="color: black;">assertEqual</span><span style="color: black;">&#40;</span>element, <span style="color: #483d8b;">'Je tres clair, Luc'</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">AssertionError</span>: <span style="color: #483d8b;">'Je laisse la main'</span> <span style="color: #66cc66;">!</span>= <span style="color: #483d8b;">'Je tres clair, Luc'</span>
- Je laisse la main
+ Je tres clair, Luc
&nbsp;
&nbsp;
----------------------------------------------------------------------
Ran <span style="color: #ff4500;">3</span> tests <span style="color: #ff7700;font-weight:bold;">in</span> 0.001s
&nbsp;
FAILED <span style="color: black;">&#40;</span>failures=<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Vous voyez qu&#8217;il n&#8217;y a plus besoin de créer le tuple 3 fois manuellement, c&#8217;est fait pour vous. De plus, la chaîne &#8220;Nettoyage !&#8221; est bien affichée 3 fois, malgré l&#8217;échec d&#8217;un test. En effet, ces méthodes sont toujours appelées, même en cas d&#8217;erreur. Cela permet de créer une environnement propre pour les tests, ou de nettoyer derrière (fermer un fichier, une connexion, etc).</p>
<h2>Lancer plusieurs modules de test</h2>
<p>Quand vous allez avoir plein de tests, vous n&#8217;allez pas tout mettre dans une classe, mais faire plein de fichiers avec des tests par sujet. Parfois vous ne lancerez qu&#8217;un fichier de test. Parfois vous voudrez tout lancer d&#8217;un coup.</p>
<p>Pour ce faire, assurez vous que vous vos modules de tests sont <a href="http://sametmax.com/les-imports-en-python/">importables</a> depuis le dossier où vous êtes. Tout doit être dans le PYTHON_PATH et les dossiers doivent contenir des fichiers <em>__init__.py</em>.</p>
<p>Ensuit, il suffit de lancer la commande :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">python <span style="color: #660033;">-m</span> unittest discover</pre></div></div>

<p>Python trouvera tous les fichiers de tests pour vous automatiquement, pourvu qu&#8217;ils soient nommés <em>test_quelquechose.py</em>.</p>
<h2>La ptit&#8217; clusion</h2>
<p>Vous voyez maintenant comment utiliser un outil pour rédiger des tests, mais probablement pas COMMENT rédiger un test, ni QUAND et POUR QUOI. C&#8217;est tout à fait normal.</p>
<p>Dans les premières parties, je vais faire un tour de tous les outils de tests à votre disposition. Puis, dans les parties suivantes, je ferai un topo sur les questions existentielles du genre &#8220;ok mais je teste quel code ?&#8221; ou &#8220;à quel moment je mets un test&#8221; ou &#8220;pourquoi c&#8217;est moi qui écrit les tests et pas bob cet enculé ?&#8221;.</p>
<p>Bref, pour le moment, vous nagez un peu dans le brouillard, et il ne faut pas s&#8217;inquiéter. Le dossier sur les tests sera long et comportera surement 8 parties ou plus. Donc on se détend, et on profite du voyage.</p>
<hr/>
<p><a href="https://github.com/sametmax/codes-des-articles/blob/master/2014/fevrier/test_get.py">Télécharger le code de l&#8217;article</a></p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9176&amp;md5=c4f366f78625d5ef1eeabf1795b32099" 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=9189
title: Attend, pourquoi il me colore vars lui ?
uri: Attend-pourquoi-il-me-colore-vars-lui
url: http://sametmax.com/attend-pourquoi-il-me-colore-vars-lui/
content:
<p>Je connais tout en Python. On peut rien m&#8217;apprendre. Je suis un Dieu.</p>
<p>Mais pourquoi mon éditeur de texte me colore le nom de variable <code>vars</code> comme si c&#8217;était une fonction ? Je n&#8217;ai pas défini de&#8230;</p>
<p>Attend&#8230;</p>
<p>Nan&#8230;</p>
<p>Putain c&#8217;est un built-in !</p>
<p>Il y a encore des fonctions built-in que je ne connais pas non de nom !</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> UneClasse<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
...     <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
...         <span style="color: #008000;">self</span>.<span style="color: black;">attribut</span> = <span style="color: #483d8b;">'valeur'</span>
...     <span style="color: #ff7700;font-weight:bold;">def</span> methode<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;">pass</span>
...     
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">vars</span><span style="color: black;">&#40;</span>UneClasse<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;"># wut ?</span>
<span style="color: black;">&#123;</span><span style="color: #483d8b;">'attribut'</span>: u<span style="color: #483d8b;">'valeur'</span><span style="color: black;">&#125;</span></pre></div></div>

<p>En fait c&#8217;est l&#8217;équivalent de faire <code>obj.__dict__</code>, mais en propre. Tout comme <code>next(iterable)</code> est la version propre de <code>iterable.__next__()</code>.</p>
<p>D&#8217;ailleurs on travaille sur une copie :</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;">id</span><span style="color: black;">&#40;</span><span style="color: #008000;">object</span>.<span style="color: #0000cd;">__dict__</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">33943288</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">id</span><span style="color: black;">&#40;</span><span style="color: #008000;">vars</span><span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">33942840</span></pre></div></div>

<p>A chaque fois que je commence à me sentir enfin un programmeur de la mort, y a un détail pour me rappeler qu&#8217;il me reste toujours des bases à apprendre.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9189&amp;md5=18cbcf9341bcb40cd9d6c39f0d079dfb" 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=9198
title: Les bases de Numpy
uri: Les-bases-de-Numpy
url: http://sametmax.com/les-bases-de-numpy/
content:
<p><a href="http://www.numpy.org/">Numpy</a> est une lib destinée à la manipulation de grands ensembles de nombres et est très utilisée par la communauté scientifique.</p>
<p>Elle propose des types et des opérations beaucoup plus performants que ceux de la lib standard, et possède des raccourcis pour les traitements de masse.</p>
<p>Malheureusement, c&#8217;est aussi une lib complexe, et, comme souvent dans le monde de la science, les tutos pourraient être plus clairs.</p>
<p>Cet article ne prétend pas à une couverture exhaustive de Numpy, d&#8217;autant que je n&#8217;ai pas le niveau en maths pour faire une simple dérivée alors des opérations matricielles complexes&#8230;</p>
<p>Mais ça devrait permettre de démystifier le truc pour les gens qui regardent ça de loin comme si c&#8217;était un pingouin au Mali.</p>
<p>Commencez par installer la bestiole avec un <code><a href="http://sametmax.com/votre-python-aime-les-pip/">pip</a> install numpy</code>. Faites-vous un café pendant que ça compile.</p>
<h2><code>array</code> sur image</h2>
<p>A la base de Numpy, il y a la manipulation d&#8217;ensembles ordonnés de nombres. On peut faire les opérations voulues sur un type <code>list</code> ordinaire, mais ce serait lent, et ça prendrait pas mal de mémoire.</p>
<p>L&#8217;alternative est d&#8217;utiliser un type optimisé comme <code>ndarray</code>, fourni par Numpy.</p>
<p>Cela se manipule comme une tuple, avec une différence majeure : il ne peut contenir qu&#8217;un seul type de données. Donc on ne met que des <code>int</code>, ou que des <code>str</code>, que des <code>bool</code>, etc.</p>
<p>On peut construire un array à partir de n&#8217;importe quel itérable :</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> numpy <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">array</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">array</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #dc143c;">array</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">array</span><span style="color: black;">&#40;</span>u<span style="color: #483d8b;">&quot;azerty&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #dc143c;">array</span><span style="color: black;">&#40;</span>u<span style="color: #483d8b;">'azerty'</span>,
      dtype=<span style="color: #483d8b;">'&lt;U6'</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">array</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1.0</span>, <span style="color: #ff4500;">2.0</span>, <span style="color: #ff4500;">3.0</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #dc143c;">array</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span> <span style="color: #ff4500;">1</span>.,  <span style="color: #ff4500;">2</span>.,  <span style="color: #ff4500;">3</span>.<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Mais souvent on utilisera une fonction générant un array automatiquement afin d&#8217;éviter de créer deux structures de données (la liste, puis l&#8217;array par exemple).</p>
<p>On peut utiliser <code>arange</code>, qui est l&#8217;équivalent de <code>range</code>, mais pour les arrays :</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> numpy <span style="color: #ff7700;font-weight:bold;">import</span> arange
<span style="color: #66cc66;">&gt;&gt;&gt;</span> arange<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">100</span>, <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
<span style="color: #dc143c;">array</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span> <span style="color: #ff4500;">1</span>,  <span style="color: #ff4500;">3</span>,  <span style="color: #ff4500;">5</span>,  <span style="color: #ff4500;">7</span>,  <span style="color: #ff4500;">9</span>, <span style="color: #ff4500;">11</span>, <span style="color: #ff4500;">13</span>, <span style="color: #ff4500;">15</span>, <span style="color: #ff4500;">17</span>, <span style="color: #ff4500;">19</span>, <span style="color: #ff4500;">21</span>, <span style="color: #ff4500;">23</span>, <span style="color: #ff4500;">25</span>, <span style="color: #ff4500;">27</span>, <span style="color: #ff4500;">29</span>, <span style="color: #ff4500;">31</span>, <span style="color: #ff4500;">33</span>,
       <span style="color: #ff4500;">35</span>, <span style="color: #ff4500;">37</span>, <span style="color: #ff4500;">39</span>, <span style="color: #ff4500;">41</span>, <span style="color: #ff4500;">43</span>, <span style="color: #ff4500;">45</span>, <span style="color: #ff4500;">47</span>, <span style="color: #ff4500;">49</span>, <span style="color: #ff4500;">51</span>, <span style="color: #ff4500;">53</span>, <span style="color: #ff4500;">55</span>, <span style="color: #ff4500;">57</span>, <span style="color: #ff4500;">59</span>, <span style="color: #ff4500;">61</span>, <span style="color: #ff4500;">63</span>, <span style="color: #ff4500;">65</span>, <span style="color: #ff4500;">67</span>,
       <span style="color: #ff4500;">69</span>, <span style="color: #ff4500;">71</span>, <span style="color: #ff4500;">73</span>, <span style="color: #ff4500;">75</span>, <span style="color: #ff4500;">77</span>, <span style="color: #ff4500;">79</span>, <span style="color: #ff4500;">81</span>, <span style="color: #ff4500;">83</span>, <span style="color: #ff4500;">85</span>, <span style="color: #ff4500;">87</span>, <span style="color: #ff4500;">89</span>, <span style="color: #ff4500;">91</span>, <span style="color: #ff4500;">93</span>, <span style="color: #ff4500;">95</span>, <span style="color: #ff4500;">97</span>, <span style="color: #ff4500;">99</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Ainsi que des choses plus perfectionnées comme <code>linspace</code>, qui retourne un array de n nombre de valeurs <strong>uniformément réparties</strong> entre deux bornes:</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> numpy <span style="color: #ff7700;font-weight:bold;">import</span> linspace
<span style="color: #66cc66;">&gt;&gt;&gt;</span> linspace<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">100</span>, <span style="color: #ff4500;">15</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># 15 valeur entre 0 et 100</span>
<span style="color: #dc143c;">array</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>   <span style="color: #ff4500;">0</span>.        ,    <span style="color: #ff4500;">7.14285714</span>,   <span style="color: #ff4500;">14.28571429</span>,   <span style="color: #ff4500;">21.42857143</span>,
         <span style="color: #ff4500;">28.57142857</span>,   <span style="color: #ff4500;">35.71428571</span>,   <span style="color: #ff4500;">42.85714286</span>,   <span style="color: #ff4500;">50</span>.        ,
         <span style="color: #ff4500;">57.14285714</span>,   <span style="color: #ff4500;">64.28571429</span>,   <span style="color: #ff4500;">71.42857143</span>,   <span style="color: #ff4500;">78.57142857</span>,
         <span style="color: #ff4500;">85.71428571</span>,   <span style="color: #ff4500;">92.85714286</span>,  <span style="color: #ff4500;">100</span>.        <span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Comme les tuples, les arrays sont itérables, sliceables, indexables et de  taille fixe :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> sistance = arange<span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> a: <span style="color: #808080; font-style: italic;"># iterable</span>
...     <span style="color: #ff7700;font-weight:bold;">print</span> x
...
<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: #66cc66;">&gt;&gt;&gt;</span> sistance<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span>:<span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span> <span style="color: #808080; font-style: italic;"># sliceable</span>
<span style="color: #dc143c;">array</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> sistance<span style="color: black;">&#91;</span>-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span> <span style="color: #808080; font-style: italic;"># indexable</span>
<span style="color: #ff4500;">9</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> sistance.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">11</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># taille fixe</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&lt;ipython-input-17-389b8ea2fe68&gt;&quot;</span>, line <span style="color: #ff4500;">1</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #66cc66;">&lt;</span>module<span style="color: #66cc66;">&gt;</span>
    sistance.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">11</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">AttributeError</span>: <span style="color: #483d8b;">'numpy.ndarray'</span> <span style="color: #008000;">object</span> has no attribute <span style="color: #483d8b;">'append'</span></pre></div></div>

<p>L&#8217;array représente donc une photographie figée de vos données, mais comme vous allez le voir, rapide et précise à manipuler.</p>
<h2>Opérations groupées</h2>
<p>La caractéristique marquante de l&#8217;array, c&#8217;est que si vous lui appliquez un opérateur mathématique, un nouvel array est retourné dont TOUTES les valeurs ont été modifiées.</p>
<p>Par exemple, si vous multipliez un array, un nouvel array est retourné avec toutes les valeurs multipliées :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> duku = <span style="color: #dc143c;">array</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> au_milieu = duku <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">2</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> au_milieu
<span style="color: #dc143c;">array</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">4</span>, <span style="color: #ff4500;">6</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>En fait, numpy fait une boucle implicite &#8211; et performante &#8211; sur tout l&#8217;array pour chaque opération mathématique. Et ça devient intéressant quand on veut faire des opérations entre plusieurs arrays entre eux :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> duku
<span style="color: #dc143c;">array</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> au_milieu
<span style="color: #dc143c;">array</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">4</span>, <span style="color: #ff4500;">6</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> de_tram = duku + au_milieu
<span style="color: #66cc66;">&gt;&gt;&gt;</span> de_tram
<span style="color: #dc143c;">array</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">3</span>, <span style="color: #ff4500;">6</span>, <span style="color: #ff4500;">9</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></pre></div></div>

<h2>Une autre dimension</h2>
<p>Si on travaille sur une liste plate, l&#8217;array est pratique, mais on en reste là. Néanmoins sa grande force est sa capacité à travailler sur plusieurs dimensions, et donc modifier tout aussi facilement des arrays d&#8217;arrays d&#8217;arrays d&#8217;arrays (arrête !) :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> thorique = <span style="color: #dc143c;">array</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span> <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span>, <span style="color: black;">&#91;</span><span style="color: #ff4500;">4</span>, <span style="color: #ff4500;">5</span>, <span style="color: #ff4500;">6</span><span style="color: black;">&#93;</span>, <span style="color: black;">&#91;</span><span style="color: #ff4500;">7</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: #66cc66;">&gt;&gt;&gt;</span> thorique
<span style="color: #dc143c;">array</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span>,
       <span style="color: black;">&#91;</span><span style="color: #ff4500;">4</span>, <span style="color: #ff4500;">5</span>, <span style="color: #ff4500;">6</span><span style="color: black;">&#93;</span>,
       <span style="color: black;">&#91;</span><span style="color: #ff4500;">7</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: #66cc66;">&gt;&gt;&gt;</span> thorique <span style="color: #66cc66;">**</span> <span style="color: #ff4500;">3</span>
<span style="color: #dc143c;">array</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#91;</span>  <span style="color: #ff4500;">1</span>,   <span style="color: #ff4500;">8</span>,  <span style="color: #ff4500;">27</span><span style="color: black;">&#93;</span>,
       <span style="color: black;">&#91;</span> <span style="color: #ff4500;">64</span>, <span style="color: #ff4500;">125</span>, <span style="color: #ff4500;">216</span><span style="color: black;">&#93;</span>,
       <span style="color: black;">&#91;</span><span style="color: #ff4500;">343</span>, <span style="color: #ff4500;">512</span>, <span style="color: #ff4500;">729</span><span style="color: black;">&#93;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>L&#8217;opération a été appliquée à tous les éléments sans faire de boucle, et en suivant l&#8217;imbrication de la structure de données récursivement.</p>
<p>Mais la partie la plus funky, c&#8217;est que le slicing AUSSI, peut se faire sur plusieurs dimensions.</p>
<p>Vous connaissez le slicing à une dimension :</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;">random</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> ticence = <span style="color: #dc143c;">array</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#91;</span><span style="color: #dc143c;">random</span>.<span style="color: black;">randint</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#41;</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> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> ticence
<span style="color: #dc143c;">array</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">77</span>, <span style="color: #ff4500;">44</span>, <span style="color: #ff4500;">93</span>, <span style="color: #ff4500;">65</span>,  <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span>,
       <span style="color: black;">&#91;</span> <span style="color: #ff4500;">8</span>, <span style="color: #ff4500;">64</span>, <span style="color: #ff4500;">36</span>, <span style="color: #ff4500;">80</span>, <span style="color: #ff4500;">77</span><span style="color: black;">&#93;</span>,
       <span style="color: black;">&#91;</span><span style="color: #ff4500;">69</span>, <span style="color: #ff4500;">24</span>, <span style="color: #ff4500;">57</span>, <span style="color: #ff4500;">18</span>, <span style="color: #ff4500;">99</span><span style="color: black;">&#93;</span>,
       <span style="color: black;">&#91;</span><span style="color: #ff4500;">60</span>, <span style="color: #ff4500;">33</span>, <span style="color: #ff4500;">63</span>, <span style="color: #ff4500;">71</span>, <span style="color: #ff4500;">99</span><span style="color: black;">&#93;</span>,
       <span style="color: black;">&#91;</span><span style="color: #ff4500;">33</span>, <span style="color: #ff4500;">60</span>, <span style="color: #ff4500;">98</span>, <span style="color: #ff4500;">85</span>, <span style="color: #ff4500;">70</span><span style="color: black;">&#93;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> ticence<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>:<span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span> <span style="color: #808080; font-style: italic;"># récupération des élément de 1 (inclus) à 4 (exclus)</span>
<span style="color: #dc143c;">array</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#91;</span> <span style="color: #ff4500;">8</span>, <span style="color: #ff4500;">64</span>, <span style="color: #ff4500;">36</span>, <span style="color: #ff4500;">80</span>, <span style="color: #ff4500;">77</span><span style="color: black;">&#93;</span>,
       <span style="color: black;">&#91;</span><span style="color: #ff4500;">69</span>, <span style="color: #ff4500;">24</span>, <span style="color: #ff4500;">57</span>, <span style="color: #ff4500;">18</span>, <span style="color: #ff4500;">99</span><span style="color: black;">&#93;</span>,
       <span style="color: black;">&#91;</span><span style="color: #ff4500;">60</span>, <span style="color: #ff4500;">33</span>, <span style="color: #ff4500;">63</span>, <span style="color: #ff4500;">71</span>, <span style="color: #ff4500;">99</span><span style="color: black;">&#93;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Mais avec un array numpy, on peut utiliser une <strong>virgule</strong> après le premier slicing, et mettre un nouveau slicing qui va travailler sur la dimension suivante.</p>
<p>Par exemple, ici j&#8217;applique le slice <code>1:4</code> sur la première dimension (je diminue le nombre de lignes) et ensuite j&#8217;applique le slicing <code>0:3</code> sur la seconde dimension (je diminue le nombre d&#8217;éléments de chaque lignes restantes, donc des colonnes).</p>
<pre lang=python>>>> ticence[1:4, 0:3]
array([[ 8, 64, 36],
       [69, 24, 57],
       [60, 33, 63]])</pre>
<p>Ca marche comme ça :</p>
<pre lang=python>array[slicing_sur_dimension1, slicing_sur_dimension2, slicing_sur_dimension3, etc]</pre>
<p>Si on commence à avoir beaucoup de dimensions et qu&#8217;on ne veut toucher que la dernière dimension, on peut utiliser Ellipsis.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> d2 = <span style="color: #dc143c;">array</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#91;</span><span style="color: #dc143c;">random</span>.<span style="color: black;">randint</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#41;</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> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> d3 = <span style="color: #dc143c;">array</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>d2.<span style="color: #dc143c;">copy</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> d4 = <span style="color: #dc143c;">array</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>d3.<span style="color: #dc143c;">copy</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>  <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> d5 = <span style="color: #dc143c;">array</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>d4.<span style="color: #dc143c;">copy</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>  <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> d6 = <span style="color: #dc143c;">array</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>d5.<span style="color: #dc143c;">copy</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>  <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> d6<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>:<span style="color: #ff4500;">3</span>,...,-<span style="color: #ff4500;">3</span>:-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
          <span style="color: black;">&#91;</span>... <span style="color: black;">plein</span> de trucs ...<span style="color: black;">&#93;</span>
          <span style="color: black;">&#91;</span><span style="color: black;">&#91;</span> <span style="color: #ff4500;">9</span>, <span style="color: #ff4500;">86</span><span style="color: black;">&#93;</span>,
           <span style="color: black;">&#91;</span><span style="color: #ff4500;">16</span>, <span style="color: #ff4500;">40</span><span style="color: black;">&#93;</span>,
           <span style="color: black;">&#91;</span><span style="color: #ff4500;">63</span>, <span style="color: #ff4500;">26</span><span style="color: black;">&#93;</span>,
           <span style="color: black;">&#91;</span><span style="color: #ff4500;">51</span>,  <span style="color: #ff4500;">5</span><span style="color: black;">&#93;</span>,
           <span style="color: black;">&#91;</span> <span style="color: #ff4500;">3</span>, <span style="color: #ff4500;">46</span><span style="color: black;">&#93;</span><span style="color: black;">&#93;</span>,
&nbsp;
          <span style="color: black;">&#91;</span><span style="color: black;">&#91;</span> <span style="color: #ff4500;">9</span>, <span style="color: #ff4500;">86</span><span style="color: black;">&#93;</span>,
           <span style="color: black;">&#91;</span><span style="color: #ff4500;">16</span>, <span style="color: #ff4500;">40</span><span style="color: black;">&#93;</span>,
           <span style="color: black;">&#91;</span><span style="color: #ff4500;">63</span>, <span style="color: #ff4500;">26</span><span style="color: black;">&#93;</span>,
           <span style="color: black;">&#91;</span><span style="color: #ff4500;">51</span>,  <span style="color: #ff4500;">5</span><span style="color: black;">&#93;</span>,
           <span style="color: black;">&#91;</span> <span style="color: #ff4500;">3</span>, <span style="color: #ff4500;">46</span><span style="color: black;">&#93;</span><span style="color: black;">&#93;</span><span style="color: black;">&#93;</span><span style="color: black;">&#93;</span><span style="color: black;">&#93;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>La dernière ligne, on prend un tableau à 6 dimensions, on applique un slicing <code>1:3</code> sur la première dimension, et un slicing <code>-3:-1</code> sur la <strong>dernière</strong> dimension.</p>
<p>Il est vrai que je ne m&#8217;en sers pas souvent.</p>
<p>Ok, je ne m&#8217;en suis jamais servi de toute ma vie. A part pour ce tuto. Mais c&#8217;est super classe non ?</p>
<p>Attention, cela ne marche que si toutes les dimensions ont le même nombre d&#8217;éléments. Cela se voit facilement en cas d&#8217;erreur car si le nombre d&#8217;éléments n&#8217;est pas bon, numpy va afficher votre array en ligne et pas sous forme de tabulaire :</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;">array</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">5</span>, <span style="color: #ff4500;">7</span>, <span style="color: #ff4500;">9</span>, <span style="color: #ff4500;">7</span>, <span style="color: #ff4500;">8</span><span style="color: black;">&#93;</span>,<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</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: #dc143c;">array</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">5</span>, <span style="color: #ff4500;">7</span>, <span style="color: #ff4500;">9</span>, <span style="color: #ff4500;">7</span>, <span style="color: #ff4500;">8</span><span style="color: black;">&#93;</span>, <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">9</span><span style="color: black;">&#93;</span><span style="color: black;">&#93;</span>, dtype=<span style="color: #008000;">object</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Vous voyez en plus qu&#8217;il précise ici <code>dtype=object</code>, alors qu&#8217;il ne l&#8217;a pas fait plus haut.</p>
<h2>Matplotlib pour afficher tout ça</h2>
<p>En théorie, la lib matplotlib n&#8217;a rien à voir avec numpy. En pratique les utilisateurs de numpy utilisent très souvent numpy + matplotlib + ipython pour avoir une équivalent de matlab en Python.</p>
<p>Matplotlib est une lib qui permet de dessiner des graphes, mais qui a la particularité d&#8217;être orienté interaction. C&#8217;est à dire qu&#8217;elle est plus destinée à fabriquer votre graphe à la main, en bidouillant vos données, et possède dont des facilités pour cela.</p>
<p>D&#8217;abord on <code>pip install matplotlib</code>, et on prie pour que ça marche car sur certains OS ça plante méchamment.</p>
<p>Et ensuite dans son shell, on peut créer un petit graphe facilement sans trop se soucier des réglages, ceux par défaut étant pas mal :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> pylab <span style="color: #ff7700;font-weight:bold;">import</span> plot, xlabel, ylabel, title, legend
<span style="color: #ff7700;font-weight:bold;">from</span> numpy <span style="color: #ff7700;font-weight:bold;">import</span> sin, pi, linspace
&nbsp;
<span style="color: #808080; font-style: italic;"># On active le mode interactif.</span>
<span style="color: #808080; font-style: italic;"># Cela permet de voir notre graph</span>
<span style="color: #808080; font-style: italic;"># en popup et de le modifier</span>
<span style="color: #808080; font-style: italic;"># en temps réel.</span>
ion<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Utilisation de mes vagues connaissances</span>
<span style="color: #808080; font-style: italic;"># de trigo pour pondre une sinusite...</span>
<span style="color: #808080; font-style: italic;"># Heu, une sinusoide.</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Un array de 50 points répartis uniformément</span>
<span style="color: #808080; font-style: italic;"># entre 0 et 2pi. Ca va nous servir de</span>
<span style="color: #808080; font-style: italic;"># première coordonnée pour nos points.</span>
x = linspace<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">2</span> <span style="color: #66cc66;">*</span> pi<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># La fonction sin() de numpy va</span>
<span style="color: #808080; font-style: italic;"># faire un nouvel array avec le sinus</span>
<span style="color: #808080; font-style: italic;"># des points de l'array précédent.</span>
<span style="color: #808080; font-style: italic;"># Ca nous fait notre deuxième coordonnée.</span>
y = sin<span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On dessine la courbe, et on lui donne un pti nom</span>
plot<span style="color: black;">&#40;</span>x, y, label=u<span style="color: #483d8b;">&quot;Moi&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># Si je me suis pas trop planté ça devrait osciller</span>
<span style="color: #808080; font-style: italic;"># entre 1 et -1</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On labellise les abscisses et les ordonnées</span>
<span style="color: #808080; font-style: italic;"># car des données sans une échelle claire ne</span>
<span style="color: #808080; font-style: italic;"># servent à rien.</span>
ylabel<span style="color: black;">&#40;</span>u<span style="color: #483d8b;">&quot;Self esteem (sur l'echelle de Richter)&quot;</span><span style="color: black;">&#41;</span>
xlabel<span style="color: black;">&#40;</span>u<span style="color: #483d8b;">'Temps passé sur Dota (en joule par km)'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On titre notre œuvre</span>
title<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Brace yourself, the graph is comming&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># On active la légende car le sujet est légendaire</span>
legend<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Ce qui nous affiche :</p>
<div id="attachment_9201" class="wp-caption aligncenter" style="width: 416px"><a href="media/e9243b4f.brace.png" data-original-source="http://sametmax.com/wp-content/uploads/2014/02/brace.png"><img src="media/e9243b4f.brace.png" data-original-source="http://sametmax.com/wp-content/uploads/2014/02/brace.png" alt="Graphe de courbe sinusoidale" title="J&#039;imagine toujours un petit train sur ce genre de courbe" width="406" height="306" class="size-full wp-image-9201" /></a><p class="wp-caption-text">J&#039;imagine toujours un petit train sur ce genre de courbe</p></div>
<p>Vous ne vous transformerez pas tout de suite en chercheur du CNRS après avoir lu ce tuto, mais j&#8217;espère qu&#8217;il vous aura donné un peu envie de faire mumuse avec Python pour manipuler vos données scientifiques.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9198&amp;md5=27060b8951094243a9c1056dc38f6922" 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=9210
title: Wrap in Try / Except dans Sublime Text
uri: Wrap-in-Try-Except-dans-Sublime-Text
url: http://sametmax.com/wrap-in-try-except-dans-sublime-text/
content:
<p>Très souvent il m&#8217;arrive de vouloir mettre un bout de mon code dans un blog <code>try / except</code>, et il faut couper le bloc de code, ecrire le <code>try/except</code>, coller le code, puis re-indenter au besoin.</p>
<p>C&#8217;est con, on a un éditeur pour faire le taff pour nous et d&#8217;ailleurs, PyDev le fait très bien. Soyons fainéant.</p>
<p>On va se rajouter une petit snippet qui permet de faire ça automatiquement. Il faut ouvrir le menu <em>Tools > new snippet</em> et un peu de xeumeuleu dedans :</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;snippet<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;content<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><span style="color: #339933;">&lt;![CDATA[</span>
<span style="color: #339933;">${SELECTION/^( *)([^ ].*)/$1/g}try:</span>
<span style="color: #339933;">${SELECTION/(^ *|\n *)/$1    /g}</span>
<span style="color: #339933;">${SELECTION/^( *)([^ ].*)/$1/g}except ${1:Exception as e}:</span>
<span style="color: #339933;">    ${SELECTION/^( *)([^ ].*)/$1/g}${2:import ipdb; ipdb.set_trace()}</span>
<span style="color: #339933;">]]&gt;</span><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/content<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>source.python<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Wrap in Try/Except<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/snippet<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>Ca récupère la selection, place le <code>try/except</code>, replace la sélection et reindente grâce à une regex. Et seulement si le fichier est du code Python. Joie.</p>
<p>On sauvegarde ça sous un nom clair genre &#8220;wrap_in_try_except.sublime-snippet&#8221;.</p>
<p>Puis on fait un petit tour dans <em>Préférence > Key Bindings &#8211; User</em> et on se rajoute un raccourci clavier pour profiter de notre nouveau joujou :</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">      <span style="color: #009900;">&#123;</span> <span style="color: #3366CC;">&quot;keys&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;ctrl+shift+y&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;command&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;insert_snippet&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;args&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><span style="color: #3366CC;">&quot;name&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Packages/User/wrap_in_try_except.sublime-snippet&quot;</span><span style="color: #009900;">&#125;</span> <span style="color: #009900;">&#125;</span></pre></div></div>

<p>Et voilà :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">ligne_qui_pouet</pre></div></div>

<p>Devient, après selection et un petit <kbd>ctrl</kbd> + <kbd>shift</kbd> + <kbd>y</kbd> :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">try</span>:
    ligne_qui_pouet
<span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">Exception</span> <span style="color: #ff7700;font-weight:bold;">as</span> e:
    <span style="color: #ff7700;font-weight:bold;">import</span> ipdb<span style="color: #66cc66;">;</span> ipdb.<span style="color: black;">set_trace</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>On peut tabuler entre la définition de l&#8217;exception à catcher et le contenu du block <code>except</code> pour les changer au besoin rapidement.</p>
<p>Par contre, ça ne marche que si on indente avec des espaces. Mais ceux qui utilisent des tabs pour indenter ne méritent pas qu&#8217;on les aide de toute façon (si c&#8217;est votre cas, quittez ce site, tout de suite, houste !).</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9210&amp;md5=3972f2b811557621b77576a8c34047c1" 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=9219
title: Explication de code : python-mss
uri: Explication-de-code-python-mss
url: http://sametmax.com/explication-de-code-python-mss/
content:
<p>Ca faisait longtemps qu&#8217;on avait pas eu une petite explication de code dans le cadre de notre politique &#8220;<a href="http://sametmax.com/notre-programme-envoyez-nous-les-scripts-que-vous-ne-pigez-pas-est-toujours-dactu/">envoyez nous les codes que vous ne pigez pas</a>&#8220;.</p>
<p>Celle-ci est un peu particulière.</p>
<p>D&#8217;abord parce qu&#8217;elle traine dans la boîte mail depuis un siècle ou deux. Je pense que l&#8217;auteur de la demande n&#8217;en a plus besoin&#8230;</p>
<p>Ensuite parce que le code est assez complexe, notamment à cause de l&#8217;utilisateur d&#8217;API C. Donc si vous n&#8217;avez pas des notions de C, vous n&#8217;allez rien piger. En effet je ne vais pas expliquer les bases de C ou de Python, ce n&#8217;est pas un tuto, donc il me faut des prérequis. Je vous invite quand même à vous rafraichir la mémoire en utilisant notre <a href="http://sametmax.com/appeler-du-code-c-depuis-python-avec-ctypes/">introduction au module ctypes</a> car il est massivement utilisé dans ce code.</p>
<p>Exceptionnellement, je ne vais pas pondre de version alternative car :</p>
<ul>
<li>le code est très très long, et j&#8217;ai déjà passé mon samedi matin à écrire cet article.</li>
<li>je n&#8217;ai pas de mac pour tester cette partie.</li>
</ul>
<p>Comme d&#8217;habitude, je vais faire des remarques parfois critiques sur le code, mais mon intention n&#8217;est bien entendu pas de faire du tord à l&#8217;auteur. C&#8217;est pédagogique pour les lecteurs. D&#8217;ailleurs ce bout de code est assez impressionnant et a du demander des heures et des heures de travail tant au niveau du code que de la recherche d&#8217;information. J&#8217;insiste donc sur mon respect pour l&#8217;auteur. On est pas sur bashfr.</p>
<p>Je tiens tout de même à prévenir que la lib ne fonctionne pas sur ma machine, plante sur certains appels, ou produits des screenshots illisibles. Je ne doute néanmoins pas de la compétence de l&#8217;auteur, ce qu&#8217;il essaye de faire est vraiment compliqué, et ne pense que Python n&#8217;est pas son premier langage.</p>
<p>On m&#8217;a signalé dans le twitcoutuer qu&#8217;il manque de la zik :</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="420" height="315" src="//www.youtube.com/embed/RV2NKk1ATew" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<p>Normalement le but de la lib est de permettre de faire des screenshots en pure Python sous Windows, Linux et Mac. Exemple de code sous Linux :</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> mss <span style="color: #ff7700;font-weight:bold;">import</span> MSSLinux
<span style="color: #66cc66;">&gt;&gt;&gt;</span> mss = MSSLinux<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> screnshots = mss.<span style="color: black;">save</span><span style="color: black;">&#40;</span>output=<span style="color: #483d8b;">'/tmp/screenshots'</span>, oneshot=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>screnshots<span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span>u<span style="color: #483d8b;">'/tmp/screenshots-full.png'</span><span style="color: black;">&#93;</span></pre></div></div>

<p>Et voici le code commenté. C&#8217;est un gros morceau, et bien complexes, avec des notions parfois que je ne maitrise pas. J&#8217;ai pu faire des erreurs et dire des bêtises. Si l&#8217;auteur passe par là, il a bien entendu un droit de réponse.</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;">''</span><span style="color: #483d8b;">' A cross-platform multi-screen shot module in pure python using ctypes.
&nbsp;
    This module is maintained by Mickaël Schoentgen &lt;contact@tiger-222.fr&gt;.
    If you find problems, please submit bug reports/patches via the
    GitHub issue tracker (https://github.com/BoboTiG/python-mss/issues).
&nbsp;
    Note: please keep this module compatible to Python 2.6.
&nbsp;
    Still needed:
    * support for additional systems
&nbsp;
    Many thanks to all those who helped (in no particular order):
&nbsp;
      Oros, Eownis
&nbsp;
    History:
&nbsp;
    &lt;see Git checkin messages for history&gt;
&nbsp;
    0.0.1 - first release
    0.0.2 - add support for python 3 on Windows and GNU/Linux
    0.0.3 - MSSImage: remove PNG filters
          - MSSImage: remove '</span>ext<span style="color: #483d8b;">' argument, using only PNG
          - MSSImage: do not overwrite existing image files
          - MSSImage: few optimizations into png()
          - MSSLinux: few optimizations into get_pixels()
    0.0.4 - MSSLinux: use of memoization =&gt; huge time/operations gains
    0.0.5 - MSSWindows: few optimizations into _arrange()
          - MSSImage: code simplified
&nbsp;
    You can always get the latest version of this module at:
&nbsp;
            https://raw.github.com/BoboTiG/python-mss/master/mss.py
&nbsp;
    If that URL should fail, try contacting the author.
'</span><span style="color: #483d8b;">''</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">__future__</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: black;">&#40;</span>unicode_literals, absolute_import,
                        division, print_function<span style="color: black;">&#41;</span>
&nbsp;
__version__ = <span style="color: #483d8b;">'0.0.5'</span>
__author__ = <span style="color: #483d8b;">&quot;Mickaël 'Tiger-222' Schoentgen&quot;</span>
__copyright__ = <span style="color: #483d8b;">''</span><span style="color: #483d8b;">'
    Copyright (c) 2013, Mickaël '</span>Tiger-<span style="color: #ff4500;">222</span><span style="color: #483d8b;">' Schoentgen
&nbsp;
    Permission to use, copy, modify, and distribute this software and its
    documentation for any purpose and without fee or royalty is hereby
    granted, provided that the above copyright notice appear in all copies
    and that both that copyright notice and this permission notice appear
    in supporting documentation or portions thereof, including
    modifications, that you make.
'</span><span style="color: #483d8b;">''</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Bon je vais pas vous expliquer ce que les lignes du dessus font hein...hein</span>
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;"># __all__ liste les objets importables si on fait from mss import *</span>
<span style="color: #808080; font-style: italic;"># ce qui limite la pollution du namespace avec tout un tas de choses inutiles</span>
<span style="color: #808080; font-style: italic;"># comme pack, isfile, system, etc. qui sont quelques lignes plus bas.</span>
__all__ = <span style="color: black;">&#91;</span><span style="color: #483d8b;">'MSSImage'</span>, <span style="color: #483d8b;">'MSSLinux'</span>, <span style="color: #483d8b;">'MSSMac'</span>, <span style="color: #483d8b;">'MSSWindows'</span><span style="color: black;">&#93;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Permet de trouve une bibliothèqe via son nom sur le système en cherchant</span>
<span style="color: #808080; font-style: italic;"># divers chemins standard à l'OS</span>
<span style="color: #ff7700;font-weight:bold;">from</span> ctypes.<span style="color: black;">util</span> <span style="color: #ff7700;font-weight:bold;">import</span> find_library
&nbsp;
<span style="color: #808080; font-style: italic;"># Permet une forme de sérialisation des types simples qui est compatible</span>
<span style="color: #808080; font-style: italic;"># entre Python et C</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">struct</span> <span style="color: #ff7700;font-weight:bold;">import</span> pack
&nbsp;
<span style="color: #808080; font-style: italic;"># Permet de vérifier si un fichier existe et n'est pas un dossier</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span> <span style="color: #ff7700;font-weight:bold;">import</span> isfile
&nbsp;
<span style="color: #808080; font-style: italic;"># Permet de récupérer le nom de l'OS</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">platform</span> <span style="color: #ff7700;font-weight:bold;">import</span> system
&nbsp;
<span style="color: #808080; font-style: italic;"># Divers opérations sur le système</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Compression zip</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">zlib</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On importe conditionnellement des packages selon le système sur lequel on</span>
<span style="color: #808080; font-style: italic;"># est. La raison de cela est que certains packages n'existe pas (ou ne sont pas</span>
<span style="color: #808080; font-style: italic;"># utiles) sur certains OS.</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Darwin, c'est l'OS open source qui sert de base au Mac. C'est</span>
<span style="color: #808080; font-style: italic;"># un mélange de NeXTSTEP et de FreeBSD.</span>
<span style="color: #ff7700;font-weight:bold;">if</span> system<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> == <span style="color: #483d8b;">'Darwin'</span>:
    <span style="color: #808080; font-style: italic;"># Quartz est la techno derrière l'affichage des Mac incluant notament</span>
    <span style="color: #808080; font-style: italic;"># le compositeur graphique et moteur de rendu 2D. Il a un binding Python</span>
    <span style="color: #808080; font-style: italic;"># intégré puisque les Mac utilisent Python un peu partout. A ce demander</span>
    <span style="color: #808080; font-style: italic;"># pourquoi ces neuneus nous ont collé objectifs C pour le dev.</span>
    <span style="color: #ff7700;font-weight:bold;">from</span> Quartz <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
    <span style="color: #808080; font-style: italic;"># On importe juste l'équivalent du mimetype sous Mac pour le PNG. C'est</span>
    <span style="color: #808080; font-style: italic;"># une &quot;constante&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">from</span> LaunchServices <span style="color: #ff7700;font-weight:bold;">import</span> kUTTypePNG
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">elif</span> system<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> == <span style="color: #483d8b;">'Linux'</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;"># Accès aux variables d'environnement</span>
    <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">os</span> <span style="color: #ff7700;font-weight:bold;">import</span> environ
    <span style="color: #808080; font-style: italic;"># Fonction pour transformer ~ dans les chemin d'accès en chemin vers</span>
    <span style="color: #808080; font-style: italic;"># le dossier utilisateur</span>
    <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span> <span style="color: #ff7700;font-weight:bold;">import</span> expanduser
    <span style="color: #808080; font-style: italic;"># Parseur de xml</span>
    <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">xml</span>.<span style="color: black;">etree</span>.<span style="color: black;">ElementTree</span> <span style="color: #ff7700;font-weight:bold;">as</span> ET
&nbsp;
    <span style="color: #808080; font-style: italic;"># 'byref' permet d'obtenir un pointer sur une fonction c,</span>
    <span style="color: #808080; font-style: italic;"># 'cast' est similaire à l'opérateur cast en c et permet le type casting</span>
    <span style="color: #808080; font-style: italic;"># d'un objet c, 'cdll' permet de charger des shared lib C</span>
    <span style="color: #ff7700;font-weight:bold;">from</span> ctypes <span style="color: #ff7700;font-weight:bold;">import</span> byref, cast, cdll
&nbsp;
    <span style="color: #808080; font-style: italic;"># je ne sais pas pourquoi ça n'a pas été fait une seule ligne...</span>
    <span style="color: #808080; font-style: italic;"># Tout ça représente les types c éponymes, mais en plus Structure est une</span>
    <span style="color: #808080; font-style: italic;"># classe abstraite dont on peut hériter faire une classe qui peut être</span>
    <span style="color: #808080; font-style: italic;"># passée en paramètre à une fonction C qui attend un struc.</span>
    <span style="color: #ff7700;font-weight:bold;">from</span> ctypes <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: black;">&#40;</span>
        c_char_p, c_int, c_int32, c_uint, c_uint32,
        c_ulong, c_void_p, POINTER, Structure
    <span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># On hérite de Structure ce qui nous fait pour le moment une structure</span>
    <span style="color: #808080; font-style: italic;"># vide</span>
    <span style="color: #ff7700;font-weight:bold;">class</span> Display<span style="color: black;">&#40;</span>Structure<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Une structure représentant les attributs d'une fenêtre pour le serveur</span>
    <span style="color: #808080; font-style: italic;"># d'affichage sous Linux.</span>
    <span style="color: #ff7700;font-weight:bold;">class</span> XWindowAttributes<span style="color: black;">&#40;</span>Structure<span style="color: black;">&#41;</span>:
        _fields_ = <span style="color: black;">&#91;</span>
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'x'</span>,                     c_int32<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'y'</span>,                     c_int32<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'width'</span>,                 c_int32<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'height'</span>,                c_int32<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'border_width'</span>,          c_int32<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'depth'</span>,                 c_int32<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'visual'</span>,                c_ulong<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'root'</span>,                  c_ulong<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'class'</span>,                 c_int32<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'bit_gravity'</span>,           c_int32<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'win_gravity'</span>,           c_int32<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'backing_store'</span>,         c_int32<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'backing_planes'</span>,        c_ulong<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'backing_pixel'</span>,         c_ulong<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'save_under'</span>,            c_int32<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'colourmap'</span>,             c_ulong<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'mapinstalled'</span>,          c_uint32<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'map_state'</span>,             c_uint32<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'all_event_masks'</span>,       c_ulong<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'your_event_mask'</span>,       c_ulong<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'do_not_propagate_mask'</span>, c_ulong<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'override_redirect'</span>,     c_int32<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'screen'</span>,                c_ulong<span style="color: black;">&#41;</span>
        <span style="color: black;">&#93;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># structure définissant une image telle qu'elle existe dans la mémoire</span>
    <span style="color: #808080; font-style: italic;"># d'un client du serveur d'affichage</span>
    <span style="color: #ff7700;font-weight:bold;">class</span> XImage<span style="color: black;">&#40;</span>Structure<span style="color: black;">&#41;</span>:
        _fields_ = <span style="color: black;">&#91;</span>
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'width'</span>            , c_int<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'height'</span>           , c_int<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'xoffset'</span>          , c_int<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'format'</span>           , c_int<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'data'</span>             , c_char_p<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'byte_order'</span>       , c_int<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'bitmap_unit'</span>      , c_int<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'bitmap_bit_order'</span> , c_int<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'bitmap_pad'</span>       , c_int<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'depth'</span>            , c_int<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'bytes_per_line'</span>   , c_int<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'bits_per_pixel'</span>   , c_int<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'red_mask'</span>         , c_ulong<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'green_mask'</span>       , c_ulong<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'blue_mask'</span>        , c_ulong<span style="color: black;">&#41;</span>
        <span style="color: black;">&#93;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Apparement la fonction pack avec ce format va être appelée souvent</span>
    <span style="color: #808080; font-style: italic;"># doc l'auteur se fait un raccourci. Le format en question est 'B', donc</span>
    <span style="color: #808080; font-style: italic;"># du unsigned char, et '&lt;', donc du little endian. Et là vous comprenez</span>
    <span style="color: #808080; font-style: italic;"># le bonheur de travailler dans un langage de haut niveau comme Python.</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> b<span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> pack<span style="color: black;">&#40;</span>b<span style="color: #483d8b;">'&lt;B'</span>, x<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">elif</span> system<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> == <span style="color: #483d8b;">'Windows'</span>:
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">from</span> ctypes <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: black;">&#40;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># 'memset' fait pareil que memset en C : on rempli un bloc de mémoire</span>
        <span style="color: #808080; font-style: italic;"># avec les bytes passés en param mais il n'est pas utilisé dans le code,</span>
        <span style="color: #808080; font-style: italic;"># donc je suppose que c'est un oubli. 'pointer' va créer une instance de</span>
        <span style="color: #808080; font-style: italic;"># la classe qui permet de manipuler un pointer sur un type c en Python.</span>
        <span style="color: #808080; font-style: italic;"># 'sizeof', même chose que l'opérateur c, ça retourne la taille en bytes</span>
        <span style="color: #808080; font-style: italic;"># d'un type</span>
        <span style="color: #808080; font-style: italic;"># c. 'windll', comme 'cdll' plus haut, mais l'appel des fonctions suit</span>
        <span style="color: #808080; font-style: italic;"># la convention stdcall typique de la win32api et pas la convention c</span>
        <span style="color: #808080; font-style: italic;"># standard.</span>
        byref, memset, pointer, sizeof, windll,
        <span style="color: #808080; font-style: italic;"># Représentation du type void en c, aliasé sous deux noms. Je n'ai pas</span>
        <span style="color: #808080; font-style: italic;"># vraiment compris l'interêt de le faire, excepté pour explicitement</span>
        <span style="color: #808080; font-style: italic;"># montrer quand on l'utilise dans un appel qui attend LPRECT (un pointer</span>
        <span style="color: #808080; font-style: italic;"># sur une struc qui représente un rectangle ou un pointer sur void)</span>
        c_void_p <span style="color: #ff7700;font-weight:bold;">as</span> LPRECT,
        c_void_p <span style="color: #ff7700;font-weight:bold;">as</span> LPVOID,
        <span style="color: #808080; font-style: italic;"># créer un array de char en c</span>
        create_string_buffer,
        <span style="color: #808080; font-style: italic;"># ça on a vu</span>
        Structure,
        POINTER,
        <span style="color: #808080; font-style: italic;"># Ceci est une fonction. Pourquoi c'est en majuscule, je n'en sais rien.</span>
        <span style="color: #808080; font-style: italic;"># Une incohérence dans l'API. En tout cas ça permet de retourner</span>
        <span style="color: #808080; font-style: italic;"># un prototype de fonction qui respecte la convention stdcall.</span>
        WINFUNCTYPE,
    <span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># Des &quot;constantes&quot; qui représentent des types spécifiques à l'API widows</span>
    <span style="color: #808080; font-style: italic;"># Notez que le PEP8 n'est pas respecté, mais bon, vu la taille du code,</span>
    <span style="color: #808080; font-style: italic;"># il y a forcément des coquilles, c'est normal. Certains comme SHORT</span>
    <span style="color: #808080; font-style: italic;"># et HANDLE ne sont pas utilisés.</span>
    <span style="color: #ff7700;font-weight:bold;">from</span> ctypes.<span style="color: black;">wintypes</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: black;">&#40;</span>
        BOOL, DOUBLE, DWORD, HANDLE, HBITMAP, HDC, HGDIOBJ,
        HWND, INT, LPARAM, LONG,RECT,SHORT, UINT, WORD
    <span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Structure contenant les information sur les dimentions et la couleur</span>
    <span style="color: #808080; font-style: italic;"># d'un BMP (on appelle ça aussi un bitmap ou DIB, donc dans les docs</span>
    <span style="color: #808080; font-style: italic;"># vous verrez l'une ou l'autre de ces appellations)</span>
    <span style="color: #ff7700;font-weight:bold;">class</span> BITMAPINFOHEADER<span style="color: black;">&#40;</span>Structure<span style="color: black;">&#41;</span>:
        _fields_ = <span style="color: black;">&#91;</span>
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'biSize'</span>,          DWORD<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'biWidth'</span>,         LONG<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'biHeight'</span>,        LONG<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'biPlanes'</span>,        WORD<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'biBitCount'</span>,      WORD<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'biCompression'</span>,   DWORD<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'biSizeImage'</span>,     DWORD<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'biXPelsPerMeter'</span>, LONG<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'biYPelsPerMeter'</span>, LONG<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'biClrUsed'</span>,       DWORD<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'biClrImportant'</span>,  DWORD<span style="color: black;">&#41;</span>
        <span style="color: black;">&#93;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Un wrapper sur la structure précédente, je suppose nécessaire pour</span>
    <span style="color: #808080; font-style: italic;"># être compatible avec une des bizarreries de l'API windows.</span>
    <span style="color: #ff7700;font-weight:bold;">class</span> BITMAPINFO<span style="color: black;">&#40;</span>Structure<span style="color: black;">&#41;</span>:
        _fields_ = <span style="color: black;">&#91;</span>
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'bmiHeader'</span>, BITMAPINFOHEADER<span style="color: black;">&#41;</span>,
            <span style="color: black;">&#40;</span><span style="color: #483d8b;">'bmiColors'</span>, DWORD <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>
        <span style="color: black;">&#93;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Là j’avoue je ne comprends pas trop le principe. Il tente de vérifier</span>
    <span style="color: #808080; font-style: italic;"># si le système est du Python 2, si oui il ne caste pas la string en bytes</span>
    <span style="color: #808080; font-style: italic;"># car le type de base des strings est déjà de type bytes (ce qui n'est</span>
    <span style="color: #808080; font-style: italic;"># pas le cas en Python 3 : c'est un type unicode). Donc il fabrique la</span>
    <span style="color: #808080; font-style: italic;"># fonction raccourcie selon la version. Sauf qu'il ne le fait pas</span>
    <span style="color: #808080; font-style: italic;"># dans la condition pour linux. Du coup je pige pas trop comment il</span>
    <span style="color: #808080; font-style: italic;"># s'en sort. Il est compatible que 2.7 sous Linux ?</span>
    <span style="color: #808080; font-style: italic;"># Dans tous les cas ces fonctions pourraient être en dehors de la clause</span>
    <span style="color: #808080; font-style: italic;"># if, tout comme certains imports pour des raisons de DRY.</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">sys</span>.<span style="color: black;">version</span> <span style="color: #66cc66;">&lt;</span> <span style="color: #483d8b;">'3'</span>:
        <span style="color: #ff7700;font-weight:bold;">def</span> b<span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">return</span> x
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #ff7700;font-weight:bold;">def</span> b<span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">return</span> pack<span style="color: black;">&#40;</span>b<span style="color: #483d8b;">'&lt;B'</span>, x<span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;"># Moi aussi j'adore mettre des commentaires comme ça dans mon code.mon</span>
<span style="color: #808080; font-style: italic;"># Que ceux qui n'aiment pas aillent se faire foutre.</span>
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;"># ----------------------------------------------------------------------</span>
<span style="color: #808080; font-style: italic;"># --- [ C'est parti mon kiki ! ] ---------------------------------------</span>
<span style="color: #808080; font-style: italic;"># ----------------------------------------------------------------------</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Comme précisé dans la docstring, c'est une classe de base. Ca implemente</span>
<span style="color: #808080; font-style: italic;"># essentiellement le logging du mode debug et la logique d'enregistrement</span>
<span style="color: #808080; font-style: italic;"># des fichiers.</span>
<span style="color: #ff7700;font-weight:bold;">class</span> MSS<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' This class will be overloaded by a system specific one.
        It checkes if there is a class available for the current system.
        Raise an exception if no one found.
    '</span><span style="color: #483d8b;">''</span>
&nbsp;
&nbsp;
    <span style="color: #808080; font-style: italic;"># De l'initialisation, pas super intéressant...</span>
    DEBUG = <span style="color: #008000;">False</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>, debug=<span style="color: #008000;">False</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' Global vars and class overload. '</span><span style="color: #483d8b;">''</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">DEBUG</span> = debug
        <span style="color: #008000;">self</span>.<span style="color: black;">monitors</span> = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">oneshot</span> = <span style="color: #008000;">False</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># L'init présuppose quand même qu'une classe fille a une fonction</span>
        <span style="color: #808080; font-style: italic;">#  init. Je vois pas trop l'interêt car ça peut se faire par héritage</span>
        <span style="color: #808080; font-style: italic;"># ou alors quitte à faire ça, autant faire en utilisant un système</span>
        <span style="color: #808080; font-style: italic;"># de call back sur des events genre &quot;oninit&quot;, c'est plus propre, plus</span>
        <span style="color: #808080; font-style: italic;"># découplé et ça tombe pas en marche si la fonction init() n'existe pas</span>
        <span style="color: #808080; font-style: italic;"># dans l'enfant.</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">init</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Une fonction print un peut élaborée qui permet d'afficher rapidement</span>
    <span style="color: #808080; font-style: italic;"># le contenu qu'on lui passe en paramètre de manière formatté pour le debug.</span>
    <span style="color: #808080; font-style: italic;"># Utiliser le module logging aurait été préférable, mais c'est tellement</span>
    <span style="color: #808080; font-style: italic;"># chiant à setup que je comprends qu'il ait eu la flemme.</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> debug<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, method=<span style="color: #483d8b;">''</span>, scalar=<span style="color: #008000;">None</span>, value=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' Simple debug output. '</span><span style="color: #483d8b;">''</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">DEBUG</span>:
            <span style="color: #ff7700;font-weight:bold;">if</span> scalar <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">None</span>:
                <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">':: '</span> + method + <span style="color: #483d8b;">'()'</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">else</span>:
                <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>method + <span style="color: #483d8b;">'()'</span>, scalar, <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>value<span style="color: black;">&#41;</span>.__name__, value<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># La fonction &quot;kifétou&quot;. Elle demande la création des screenshots, les</span>
    <span style="color: #808080; font-style: italic;"># sauvegarde dans des fichiers png dans un dossier. Il aurait été sympa</span>
    <span style="color: #808080; font-style: italic;"># de découper cette fonction en sous fonctions : une prendre le screen</span>
    <span style="color: #808080; font-style: italic;"># d'un moniteur, une pour recupérer le screenshot tout forme d'objet image,</span>
    <span style="color: #808080; font-style: italic;"># etc. Là la seule option c'est &quot;tu prends tout, tu sauves tout&quot;. C'est pas</span>
    <span style="color: #808080; font-style: italic;"># très souple, et dur à tester.</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> save<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, output=<span style="color: #483d8b;">'mss'</span>, oneshot=<span style="color: #008000;">False</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' For each monitor, grab a screen shot and save it to a file.
&nbsp;
            Parameters:
             - output - string - the output filename without extension
             - oneshot - boolean - grab only one screen shot of all monitors
&nbsp;
            This is a generator which returns created files:
                '</span>output-<span style="color: #ff4500;">1</span>.<span style="color: black;">png</span><span style="color: #483d8b;">',
                '</span>output-<span style="color: #ff4500;">2</span>.<span style="color: black;">png</span><span style="color: #483d8b;">',
                ...,
                '</span>output-NN.<span style="color: black;">png</span><span style="color: #483d8b;">'
                or
                '</span>output-full.<span style="color: black;">png</span><span style="color: #483d8b;">'
        '</span><span style="color: #483d8b;">''</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'save'</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Là on voit un antipattern très courrant en POO : mettre des paramètres</span>
        <span style="color: #808080; font-style: italic;"># pour un appel de méthode directement en attribut pour toute la classe.</span>
        <span style="color: #808080; font-style: italic;"># Cela veut dire qu'un appel à cette fonction &quot;lock&quot; la classe dans</span>
        <span style="color: #808080; font-style: italic;"># un état dépendant de cet appel. En plus de réduire à néant les possibilités</span>
        <span style="color: #808080; font-style: italic;"># de multithreading et rendre les tests compliqués, ça veut dire aussi</span>
        <span style="color: #808080; font-style: italic;"># que tout débuggage doit tenir compte de l'état de la classe. Et bien</span>
        <span style="color: #808080; font-style: italic;"># entendu, ça veut dire qu'on ne peut pas avoir plusieurs états en</span>
        <span style="color: #808080; font-style: italic;"># parallèles, à moins d'instancier plusieurs classes. Il vaudrait mieux</span>
        <span style="color: #808080; font-style: italic;"># que tout ça soit passé en paramètres, quitte à faire un autre objet</span>
        <span style="color: #808080; font-style: italic;"># nommé &quot;config&quot; qui contienne tout ça.</span>
        <span style="color: #808080; font-style: italic;">#</span>
        <span style="color: #808080; font-style: italic;"># En tout cas, ça stoque le param &quot;oneshot&quot; et la liste des moniteurs</span>
        <span style="color: #808080; font-style: italic;"># retournés par le code fourni par la classe fille puisque</span>
        <span style="color: #808080; font-style: italic;"># enum_display_monitors n'est pas défini dans cette classe.</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">oneshot</span> = oneshot
        <span style="color: #008000;">self</span>.<span style="color: black;">monitors</span> = <span style="color: #008000;">self</span>.<span style="color: black;">enum_display_monitors</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'save'</span>, <span style="color: #483d8b;">'oneshot'</span>, <span style="color: #008000;">self</span>.<span style="color: black;">oneshot</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># On lève une exception si il est impossible de trouver des écrans dont</span>
        <span style="color: #808080; font-style: italic;"># on peut faire la capture, ce qui est une bonne chose. Mais une bonne</span>
        <span style="color: #808080; font-style: italic;"># pratique serait de faire :</span>
        <span style="color: #808080; font-style: italic;"># class ScreenshotError(Exception):</span>
        <span style="color: #808080; font-style: italic;">#     pass</span>
        <span style="color: #808080; font-style: italic;"># Afin d'avoir quelque chose de plus significatif que ValueError.</span>
        <span style="color: #808080; font-style: italic;"># De plus, ce code est typique d'un programmeur d'un autre langage</span>
        <span style="color: #808080; font-style: italic;"># qui apprend encore les idiomes Python car cette condition pourrait</span>
        <span style="color: #808080; font-style: italic;"># se réduire à :</span>
        <span style="color: #808080; font-style: italic;"># if not self.monitors: &lt;- pas besoin de len</span>
        <span style="color: #808080; font-style: italic;">#     raise ScreenshotError('MSS: no monitor found.'))</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">monitors</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&lt;</span> <span style="color: #ff4500;">1</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;">'MSS: no monitor found.'</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Monitors screen shots!</span>
        <span style="color: #808080; font-style: italic;"># On itère sur les écrans, et on fait un screen par écran. Même remarque</span>
        <span style="color: #808080; font-style: italic;"># sur le fait que l'auteur cherche encore ses marques en Python (notez</span>
        <span style="color: #808080; font-style: italic;"># bien que c'est naturel, personne n'a la science infuse et mon style</span>
        <span style="color: #808080; font-style: italic;"># est horrible dans les autres langages), car ici le compteur i est</span>
        <span style="color: #808080; font-style: italic;"># aventageusement remplacé par :</span>
        <span style="color: #808080; font-style: italic;"># for i, monitor in enumerate(self.monitors)</span>
        i = <span style="color: #ff4500;">1</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> monitor <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">self</span>.<span style="color: black;">monitors</span>:
            <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'save'</span>, <span style="color: #483d8b;">'monitor'</span>, monitor<span style="color: black;">&#41;</span>
&nbsp;
            <span style="color: #808080; font-style: italic;"># Si on ne fait qu'un gros screenshot, on l'appelle name-full.png</span>
            <span style="color: #808080; font-style: italic;"># sinon name-numero_du_moniteur.png</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">oneshot</span>:
                filename = output + <span style="color: #483d8b;">'-full'</span>
            <span style="color: #ff7700;font-weight:bold;">else</span>:
                filename = output + <span style="color: #483d8b;">'-'</span> + <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#41;</span>
                i += <span style="color: #ff4500;">1</span>
            filename += <span style="color: #483d8b;">'.png'</span>
&nbsp;
            <span style="color: #808080; font-style: italic;"># Si le fichier n'existe pas, on l'écrit. Ceci est encore une</span>
            <span style="color: #808080; font-style: italic;"># erreur car une API métier ne doit pas faire ce genre de</span>
            <span style="color: #808080; font-style: italic;"># vérification. Il devrait écraser les fichiers. Il est en revanche</span>
            <span style="color: #808080; font-style: italic;"># possible de mettre un système de callback pour réagir si le</span>
            <span style="color: #808080; font-style: italic;"># fichier existe. Mais le comportement par défaut devrait être</span>
            <span style="color: #808080; font-style: italic;"># d'écraser le fichiers, sinon une personne qui ne lit pas le code</span>
            <span style="color: #808080; font-style: italic;"># source va croire que le code ne marche pas. De plus, il est plus</span>
            <span style="color: #808080; font-style: italic;"># rare de ne pas vouloir écraser les fichiers d'origine que</span>
            <span style="color: #808080; font-style: italic;"># l'inverse. Enfin, puisqu'on ne controle pas le nommage des fichiers</span>
            <span style="color: #808080; font-style: italic;"># depuis l'extérieur de la classe, il n'y a pas de moyen de réagir</span>
            <span style="color: #808080; font-style: italic;"># proprement pour dire &quot;je veux garder les anciens fichiers et</span>
            <span style="color: #808080; font-style: italic;"># avoir les nouveaux quand même&quot; à part utilise un dossier différent</span>
            <span style="color: #808080; font-style: italic;"># à chaque fois.</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> isfile<span style="color: black;">&#40;</span>filename<span style="color: black;">&#41;</span>:
&nbsp;
                <span style="color: #808080; font-style: italic;"># On récupère l'array de pixels en utilisant le code de la</span>
                <span style="color: #808080; font-style: italic;"># classe fille une fois de plus. C'est nécessaire puisque ça</span>
                <span style="color: #808080; font-style: italic;"># dépend de l'OS.</span>
                <span style="color: #808080; font-style: italic;"># Ce code ne fait pas du tout ce que vous croyez. get_pixels</span>
                <span style="color: #808080; font-style: italic;"># va sauvegarder l'image sans self.image, et retourner 1.</span>
                <span style="color: #808080; font-style: italic;"># C'est donc une fonction qui marche via ses effets de bords,</span>
                <span style="color: #808080; font-style: italic;"># ce qui est une très mauvaise pratique.</span>
                pixels = <span style="color: #008000;">self</span>.<span style="color: black;">get_pixels</span><span style="color: black;">&#40;</span>monitor<span style="color: black;">&#41;</span>
&nbsp;
                <span style="color: #808080; font-style: italic;"># Même remarque que sur l'autre exception. De plus l'exception</span>
                <span style="color: #808080; font-style: italic;"># devrait être levée au niveau de get_pixels, pas au niveau</span>
                <span style="color: #808080; font-style: italic;"># de save(). Il y a un mélange de base niveau et de haut</span>
                <span style="color: #808080; font-style: italic;"># niveau dans cette classe qui rend l'API assez maladroite.</span>
                <span style="color: #808080; font-style: italic;"># D'ailleurs get_pixels ne retourne jamais None...</span>
                <span style="color: #ff7700;font-weight:bold;">if</span> pixels <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">None</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;">'MSS: no data to process.'</span><span style="color: black;">&#41;</span>
&nbsp;
                <span style="color: #808080; font-style: italic;"># Bon, ça c'est super crade. En gros il délègue le save à une</span>
                <span style="color: #808080; font-style: italic;"># méthode si elle existe, et sinon le fait à la main.</span>
                <span style="color: #808080; font-style: italic;"># L'héritage est fait pour ça, et il aurait été préférable</span>
                <span style="color: #808080; font-style: italic;"># de faire une méthode save(pixels, size, filename) générique</span>
                <span style="color: #808080; font-style: italic;"># et ensuite l'écraser dans les enfants. Peut être que c'est un</span>
                <span style="color: #808080; font-style: italic;"># dev C et qu'il n'est pas encore très à l'aise avec le POO.</span>
                <span style="color: #808080; font-style: italic;"># Il est possible que l'auteur ait rencontré des problèmes du</span>
                <span style="color: #808080; font-style: italic;"># fait d'une inconsistance d'api et n'ai pas su le gérer en</span>
                <span style="color: #808080; font-style: italic;"># mettant un adapter par dessus. Quand je vous dis que les</span>
                <span style="color: #808080; font-style: italic;"># design pattern c'est parfois utile :)</span>
                <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">hasattr</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #483d8b;">'save_'</span><span style="color: black;">&#41;</span>:
                    img_out = <span style="color: #008000;">self</span>.<span style="color: black;">save_</span><span style="color: black;">&#40;</span>output=filename<span style="color: black;">&#41;</span>
                <span style="color: #ff7700;font-weight:bold;">else</span>:
                    img = MSSImage<span style="color: black;">&#40;</span>pixels, monitor<span style="color: black;">&#91;</span>b<span style="color: #483d8b;">'width'</span><span style="color: black;">&#93;</span>, monitor<span style="color: black;">&#91;</span>b<span style="color: #483d8b;">'height'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
                    img_out = img.<span style="color: black;">dump</span><span style="color: black;">&#40;</span>filename<span style="color: black;">&#41;</span>
                <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'save'</span>, <span style="color: #483d8b;">'img_out'</span>, img_out<span style="color: black;">&#41;</span>
                <span style="color: #ff7700;font-weight:bold;">if</span> img_out:
                    <span style="color: #808080; font-style: italic;"># Etant donné que la génération du screenshot prend du</span>
                    <span style="color: #808080; font-style: italic;"># temps et qu'il y en a plusieurs, l'auteur a intelligemment</span>
                    <span style="color: #808080; font-style: italic;"># choisit de faire un générateur, ce qui permet de ne pas</span>
                    <span style="color: #808080; font-style: italic;"># attendre que tous les screenshots soient terminé avant</span>
                    <span style="color: #808080; font-style: italic;"># de d'avoir un premier résultat.</span>
                    <span style="color: #ff7700;font-weight:bold;">yield</span> img_out
            <span style="color: #ff7700;font-weight:bold;">else</span>:
                <span style="color: #ff7700;font-weight:bold;">yield</span> filename + <span style="color: #483d8b;">' (already exists)'</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Les fameuses méthodes délégues aux classes filles. Un petit</span>
    <span style="color: #808080; font-style: italic;"># NotImplemented serait mieux que pass car c'est plus explicite, mais</span>
    <span style="color: #808080; font-style: italic;"># rien de grave.</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> enum_display_monitors<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' Get positions of all monitors.
&nbsp;
            If self.oneshot is True, this function has to return a dict
            with dimensions of all monitors at the same time.
            If the monitor has rotation, you have to deal with inside this method.
&nbsp;
            Must returns a dict with a minima:
            {
                '</span>left<span style="color: #483d8b;">':   the x-coordinate of the upper-left corner,
                '</span>top<span style="color: #483d8b;">':    the y-coordinate of the upper-left corner,
                '</span>width<span style="color: #483d8b;">':  the width,
                '</span>height<span style="color: #483d8b;">': the height
            }
        '</span><span style="color: #483d8b;">''</span>
        <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> get_pixels<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, monitor_infos<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' Retrieve screen pixels for a given monitor.
&nbsp;
            monitor_infos should contain at least:
            {
                '</span>left<span style="color: #483d8b;">':   the x-coordinate of the upper-left corner,
                '</span>top<span style="color: #483d8b;">':    the y-coordinate of the upper-left corner,
                '</span>width<span style="color: #483d8b;">':  the width,
                '</span>heigth<span style="color: #483d8b;">': the height
            }
&nbsp;
            Returns a dict with pixels.
        '</span><span style="color: #483d8b;">''</span>
        <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Maintenant on par dans les détails de l'implémentation de l'algo qui récupère</span>
<span style="color: #808080; font-style: italic;"># les screenshots qui est spécifique à chaque OS.</span>
<span style="color: #ff7700;font-weight:bold;">class</span> MSSMac<span style="color: black;">&#40;</span>MSS<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' Mutli-screen shot implementation for Mac OSX.
        It uses intensively the Quartz.
    '</span><span style="color: #483d8b;">''</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Bon, du coup plutôt que de faire une fonction init, il aurait mieux</span>
    <span style="color: #808080; font-style: italic;"># valut faire une fonction __init__ qui appelle super().</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> init<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' Mac OSX initialisations '</span><span style="color: #483d8b;">''</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'init'</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Là c'est le gros du boulot, et c'est là que je vous dis que l'auteur</span>
    <span style="color: #808080; font-style: italic;"># c'est vraiment super cassé le cul pour trouver toutes ces infos sur</span>
    <span style="color: #808080; font-style: italic;"># les APIS propres à chaque système, et en plus en C. Kudos.</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> enum_display_monitors<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' Get positions of one or more monitors.
            Returns a dict with minimal requirements (see MSS class).
        '</span><span style="color: #483d8b;">''</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'enum_display_monitors'</span><span style="color: black;">&#41;</span>
&nbsp;
        results = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
        <span style="color: #808080; font-style: italic;"># Si il y a un seul screen à prend, on se fait pas chier et on prend</span>
        <span style="color: #808080; font-style: italic;"># un rectangle de taille infinie pour les limites du screen. Je</span>
        <span style="color: #808080; font-style: italic;"># suppose que l'OS est capable de se démerder avec ça et borner</span>
        <span style="color: #808080; font-style: italic;"># à la taille du matos automatiquement. C'est un truc de faignasse, et</span>
        <span style="color: #808080; font-style: italic;"># c'est plutôt malin.</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">oneshot</span>:
            rect = CGRectInfinite
            results.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: black;">&#123;</span>
                b<span style="color: #483d8b;">'left'</span>  : <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>rect.<span style="color: black;">origin</span>.<span style="color: black;">x</span><span style="color: black;">&#41;</span>,
                b<span style="color: #483d8b;">'top'</span>   : <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>rect.<span style="color: black;">origin</span>.<span style="color: black;">y</span><span style="color: black;">&#41;</span>,
                b<span style="color: #483d8b;">'width'</span> : <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>rect.<span style="color: black;">size</span>.<span style="color: black;">width</span><span style="color: black;">&#41;</span>,
                b<span style="color: #483d8b;">'height'</span>: <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>rect.<span style="color: black;">size</span>.<span style="color: black;">height</span><span style="color: black;">&#41;</span>
            <span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            <span style="color: #808080; font-style: italic;"># Par contre là il faut se taper le calcul des coordonnées de</span>
            <span style="color: #808080; font-style: italic;"># rectangle à la main</span>
&nbsp;
            <span style="color: #808080; font-style: italic;"># Cette variable est requise par CGGetActiveDisplayList mais</span>
            <span style="color: #808080; font-style: italic;"># comme le suggère le commentaire de l'auteur ci-dessous : LOL.</span>
            max_displays = <span style="color: #ff4500;">32</span>  <span style="color: #808080; font-style: italic;"># Peut-être augmenté, si besoin...</span>
&nbsp;
            <span style="color: #808080; font-style: italic;"># Apparemment il est possible que l'affichage ait subit une</span>
            <span style="color: #808080; font-style: italic;"># rotation. Je suppose que MacOS anticipait déjà l’existence des</span>
            <span style="color: #808080; font-style: italic;"># tablettes à l'époque.</span>
            rotations = <span style="color: black;">&#123;</span><span style="color: #ff4500;">0.0</span>: <span style="color: #483d8b;">'normal'</span>, <span style="color: #ff4500;">90.0</span>: <span style="color: #483d8b;">'right'</span>, -<span style="color: #ff4500;">90.0</span>: <span style="color: #483d8b;">'left'</span><span style="color: black;">&#125;</span>
&nbsp;
            <span style="color: #808080; font-style: italic;"># On demande les affichages qui sont effectivement en court</span>
            <span style="color: #808080; font-style: italic;"># d'utilisation, et on récupère un identifiant unique pour chacun</span>
            <span style="color: #808080; font-style: italic;"># d'entre deux.</span>
            res, ids, count = CGGetActiveDisplayList<span style="color: black;">&#40;</span>max_displays, <span style="color: #008000;">None</span>, <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">for</span> display <span style="color: #ff7700;font-weight:bold;">in</span> ids:
                <span style="color: #808080; font-style: italic;"># On interroge l'API Mac pour avoir ses coordonnées, et on</span>
                <span style="color: #808080; font-style: italic;"># les extrait.</span>
                rect = CGRectStandardize<span style="color: black;">&#40;</span>CGDisplayBounds<span style="color: black;">&#40;</span>display<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
                left, top = rect.<span style="color: black;">origin</span>.<span style="color: black;">x</span>, rect.<span style="color: black;">origin</span>.<span style="color: black;">y</span>
                width, height = rect.<span style="color: black;">size</span>.<span style="color: black;">width</span>, rect.<span style="color: black;">size</span>.<span style="color: black;">height</span>
                <span style="color: #808080; font-style: italic;"># Correction des coordonnées en cas de rotation.</span>
                rot = CGDisplayRotation<span style="color: black;">&#40;</span>display<span style="color: black;">&#41;</span>
                rotation = rotations<span style="color: black;">&#91;</span>rot<span style="color: black;">&#93;</span>
                <span style="color: #ff7700;font-weight:bold;">if</span> rotation <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">'left'</span>, <span style="color: #483d8b;">'right'</span><span style="color: black;">&#93;</span>:
                    width, height = height, width
&nbsp;
                <span style="color: #808080; font-style: italic;"># Et on insère le résultat dans la liste des monitors. On</span>
                <span style="color: #808080; font-style: italic;"># aurait pu yielder aussi comme dans save(), mais bon, c'est</span>
                <span style="color: #808080; font-style: italic;"># parce que je yield partout que je dis ça.</span>
                results.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: black;">&#123;</span>
                    b<span style="color: #483d8b;">'left'</span>    : <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>left<span style="color: black;">&#41;</span>,
                    b<span style="color: #483d8b;">'top'</span>     : <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>top<span style="color: black;">&#41;</span>,
                    b<span style="color: #483d8b;">'width'</span>   : <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>width<span style="color: black;">&#41;</span>,
                    b<span style="color: #483d8b;">'height'</span>  : <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>height<span style="color: black;">&#41;</span>,
                    b<span style="color: #483d8b;">'rotation'</span>: rotation
                <span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> results
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> get_pixels<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, monitor<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' Retreive all pixels from a monitor. Pixels have to be RGB.
        '</span><span style="color: #483d8b;">''</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'get_pixels'</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># On récupère les coordonnées retournées par enum_display_monitors</span>
        <span style="color: #808080; font-style: italic;"># et on en fait un CGRect qui est nécessaire pour CGWindowListCreateImage.</span>
        width, height = monitor<span style="color: black;">&#91;</span>b<span style="color: #483d8b;">'width'</span><span style="color: black;">&#93;</span>, monitor<span style="color: black;">&#91;</span>b<span style="color: #483d8b;">'height'</span><span style="color: black;">&#93;</span>
        left, top = monitor<span style="color: black;">&#91;</span>b<span style="color: #483d8b;">'left'</span><span style="color: black;">&#93;</span>, monitor<span style="color: black;">&#91;</span>b<span style="color: #483d8b;">'top'</span><span style="color: black;">&#93;</span>
        rect = CGRect<span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>left, top<span style="color: black;">&#41;</span>, <span style="color: black;">&#40;</span>width, height<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># CGWindowListCreateImage retourne l'image à ces coordonnées.</span>
        <span style="color: #808080; font-style: italic;"># Les 3 derniers paramètres sont là grace à &quot;from Quartz import *&quot;</span>
        <span style="color: #808080; font-style: italic;"># (c'est pour ça que je vous dis de ne pas le faire, car c'est pas</span>
        <span style="color: #808080; font-style: italic;"># facile à retracer). kCGWindowListOptionOnScreenOnly force l'inclusion</span>
        <span style="color: #808080; font-style: italic;"># uniquement des fenêtre affichées et non celles hors écran.</span>
        <span style="color: #808080; font-style: italic;"># kCGNullWindowID est l'équivalent de None, dans ce contexte. C'est</span>
        <span style="color: #808080; font-style: italic;"># la fenêtre de référence, et on en veut aucune.</span>
        <span style="color: #808080; font-style: italic;"># kCGWindowImageDefault demande de capturer le fenêtre ET sa décoration</span>
        <span style="color: #808080; font-style: italic;"># (comme les ombres portées).</span>
        <span style="color: #808080; font-style: italic;"># Ces deux derniers params sont les valeurs par défaut donc je ne sais</span>
        <span style="color: #808080; font-style: italic;"># pas pourquoi il les passent.</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">image</span> = CGWindowListCreateImage<span style="color: black;">&#40;</span>
                    rect, kCGWindowListOptionOnScreenOnly,
                    kCGNullWindowID, kCGWindowImageDefault<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Comme je le disais dans save(), la fonction ne retourne PAS l'objet</span>
        <span style="color: #808080; font-style: italic;"># image mais 1. L'image est stockée dans self.image et ce sont les</span>
        <span style="color: #808080; font-style: italic;"># autres méthodes qui tapent dans cet attribut. C'est mal.</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #ff4500;">1</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># la fameurse méthode save_ utilisée par save()...</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> save_<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, output<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' Special method to not use MSSImage class. '</span><span style="color: #483d8b;">''</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'save_'</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># résolution du png</span>
        dpi = <span style="color: #ff4500;">72</span>
        <span style="color: #808080; font-style: italic;"># chemin du png. Tout est URL dans Mac OS. Un chemin de fichier</span>
        <span style="color: #808080; font-style: italic;"># est une URL file://</span>
        url = NSURL.<span style="color: black;">fileURLWithPath_</span><span style="color: black;">&#40;</span>output<span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># On fabrique l'objet fichier</span>
        dest = CGImageDestinationCreateWithURL<span style="color: black;">&#40;</span>url, kUTTypePNG, <span style="color: #ff4500;">1</span>, <span style="color: #008000;">None</span><span style="color: black;">&#41;</span>
        properties = <span style="color: black;">&#123;</span>
            kCGImagePropertyDPIWidth: dpi,
            kCGImagePropertyDPIHeight: dpi,
        <span style="color: black;">&#125;</span>
        <span style="color: #808080; font-style: italic;"># On met notre image dans l'objet fichier. Là il faut se souvenir</span>
        <span style="color: #808080; font-style: italic;"># que save() appelle get_pixel() qui remplit self.image puis appelle</span>
        <span style="color: #808080; font-style: italic;"># save_() derrière. Je vous l'avais dis que les effets de bord, ça</span>
        <span style="color: #808080; font-style: italic;"># craint).</span>
        CGImageDestinationAddImage<span style="color: black;">&#40;</span>dest, <span style="color: #008000;">self</span>.<span style="color: black;">image</span>, properties<span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># On écrit notre objet fichier sur le disk.</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> CGImageDestinationFinalize<span style="color: black;">&#40;</span>dest<span style="color: black;">&#41;</span>:
            output = <span style="color: #008000;">None</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># L'auteur vide ouput si CGImageDestinationFinalize à échoué. Il</span>
        <span style="color: #808080; font-style: italic;"># vaudrait mieux lever une exception.</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> output
&nbsp;
<span style="color: #808080; font-style: italic;"># On passe à l'implémentation Linux.</span>
<span style="color: #ff7700;font-weight:bold;">class</span> MSSLinux<span style="color: black;">&#40;</span>MSS<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' Mutli-screen shot implementation for GNU/Linux.
        It uses intensively the Xlib.
    '</span><span style="color: #483d8b;">''</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Fait un travail de nettoyage quand l'objet est garbage collecté, en</span>
    <span style="color: #808080; font-style: italic;"># l'occurence ferme la connection avec le serveur x. Je rappelle que</span>
    <span style="color: #808080; font-style: italic;"># l'appel à __del__ n'est pas garanti donc mieux faut faire une méthode</span>
    <span style="color: #808080; font-style: italic;"># close() officielle et un context manager avec un finally.</span>
    <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: #483d8b;">''</span><span style="color: #483d8b;">' Disconnect from X server '</span><span style="color: #483d8b;">''</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'__del__'</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;">display</span>:
            <span style="color: #008000;">self</span>.<span style="color: black;">XCloseDisplay</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">display</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> init<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' GNU/Linux initialisations '</span><span style="color: #483d8b;">''</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'init'</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># on charge la shared lib du serveur x</span>
        x11 = find_library<span style="color: black;">&#40;</span><span style="color: #483d8b;">'X11'</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> x11 <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">None</span>:
            <span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #008000;">OSError</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'MSSLinux: no X11 library found.'</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            xlib = cdll.<span style="color: black;">LoadLibrary</span><span style="color: black;">&#40;</span>x11<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'init'</span>, <span style="color: #483d8b;">'xlib'</span>, xlib<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Aliasing des méthode de xlib. Pourquoi ? Aucune idée.</span>
        <span style="color: #808080; font-style: italic;"># passer l'objet xlib le parait plus logique. Peut être qu'il y a</span>
        <span style="color: #808080; font-style: italic;"># une raison technique liée au mapping ctypes, mais je ne la connais</span>
        <span style="color: #808080; font-style: italic;"># pas.</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">XOpenDisplay</span> = xlib.<span style="color: black;">XOpenDisplay</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">XDefaultScreen</span> = xlib.<span style="color: black;">XDefaultScreen</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">XDefaultRootWindow</span> = xlib.<span style="color: black;">XDefaultRootWindow</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">XGetWindowAttributes</span> = xlib.<span style="color: black;">XGetWindowAttributes</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">XAllPlanes</span> = xlib.<span style="color: black;">XAllPlanes</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">XGetImage</span> = xlib.<span style="color: black;">XGetImage</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">XGetPixel</span> = xlib.<span style="color: black;">XGetPixel</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">XFree</span> = xlib.<span style="color: black;">XFree</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">XCloseDisplay</span> = xlib.<span style="color: black;">XCloseDisplay</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># ctypes permet de spécifier pour chaque fonction des types attendus</span>
        <span style="color: #808080; font-style: italic;"># en paramètre et en valeur de retour. Cela permet l'autocasting</span>
        <span style="color: #808080; font-style: italic;"># de types compatibles et une exception explicite en cas de passage</span>
        <span style="color: #808080; font-style: italic;"># de mauvais paramètres plutôt qu'un core dump.</span>
        <span style="color: #808080; font-style: italic;"># L'auteur ici à mis ce code un peu lourd dans des méthodes dédiées et</span>
        <span style="color: #808080; font-style: italic;"># préfixées de _ puisqu'à usage interne.</span>
        <span style="color: #008000;">self</span>._set_argtypes<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>._set_restypes<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># On récupère l'affichage en cours en tapant dans les variables</span>
        <span style="color: #808080; font-style: italic;"># d'environnement. Le jobby-jobba et du au fait qu'il veut garder</span>
        <span style="color: #808080; font-style: italic;"># la compatibilité Python 3 et 2.7 et qu'il faut accomoder</span>
        <span style="color: #808080; font-style: italic;"># les types str/unicode/bytes.</span>
        <span style="color: #808080; font-style: italic;"># C'est une vérification pour éviter un segfault si il n'y pas de</span>
        <span style="color: #808080; font-style: italic;"># serveur x qui tourne.</span>
        display = <span style="color: #008000;">None</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">display</span> = <span style="color: #008000;">None</span>
        <span style="color: #ff7700;font-weight:bold;">try</span>:
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">sys</span>.<span style="color: black;">version</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #483d8b;">'3'</span>:
                display = <span style="color: #dc143c;">bytes</span><span style="color: black;">&#40;</span>environ<span style="color: black;">&#91;</span><span style="color: #483d8b;">'DISPLAY'</span><span style="color: black;">&#93;</span>, <span style="color: #483d8b;">'utf-8'</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">else</span>:
                display = environ<span style="color: black;">&#91;</span><span style="color: #483d8b;">'DISPLAY'</span><span style="color: black;">&#93;</span>
        <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">KeyError</span>:
            err = <span style="color: #483d8b;">'MSSLinux: $DISPLAY not set. Stopping to prevent segfault.'</span>
            <span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #008000;">ValueError</span><span style="color: black;">&#40;</span>err<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'init'</span>, <span style="color: #483d8b;">'$DISPLAY'</span>, display<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># On récupère l'écran par défaut et la fenêtre racine sur l'affichage</span>
        <span style="color: #808080; font-style: italic;"># en cours.</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># At this point, if there is no running server, it could end on</span>
        <span style="color: #808080; font-style: italic;"># a segmentation fault. And we cannot catch it.</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">display</span> = <span style="color: #008000;">self</span>.<span style="color: black;">XOpenDisplay</span><span style="color: black;">&#40;</span>display<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'init'</span>, <span style="color: #483d8b;">'display'</span>, <span style="color: #008000;">self</span>.<span style="color: black;">display</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">screen</span> = <span style="color: #008000;">self</span>.<span style="color: black;">XDefaultScreen</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">display</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'init'</span>, <span style="color: #483d8b;">'screen'</span>, <span style="color: #008000;">self</span>.<span style="color: black;">screen</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">root</span> = <span style="color: #008000;">self</span>.<span style="color: black;">XDefaultRootWindow</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">display</span>, <span style="color: #008000;">self</span>.<span style="color: black;">screen</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'init'</span>, <span style="color: #483d8b;">'root'</span>, <span style="color: #008000;">self</span>.<span style="color: black;">root</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># les deux méthodes qui servent à manuellement définir les types</span>
    <span style="color: #808080; font-style: italic;"># des autres méthodes dont j'ai parlé plus haut.</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _set_argtypes<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' Functions arguments '</span><span style="color: #483d8b;">''</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'_set_argtypes'</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">XOpenDisplay</span>.<span style="color: black;">argtypes</span> = <span style="color: black;">&#91;</span>c_char_p<span style="color: black;">&#93;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">XDefaultScreen</span>.<span style="color: black;">argtypes</span> = <span style="color: black;">&#91;</span>POINTER<span style="color: black;">&#40;</span>Display<span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">XDefaultRootWindow</span>.<span style="color: black;">argtypes</span> = <span style="color: black;">&#91;</span>POINTER<span style="color: black;">&#40;</span>Display<span style="color: black;">&#41;</span>, c_int<span style="color: black;">&#93;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">XGetWindowAttributes</span>.<span style="color: black;">argtypes</span> = <span style="color: black;">&#91;</span>POINTER<span style="color: black;">&#40;</span>Display<span style="color: black;">&#41;</span>,
            POINTER<span style="color: black;">&#40;</span>XWindowAttributes<span style="color: black;">&#41;</span>, POINTER<span style="color: black;">&#40;</span>XWindowAttributes<span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">XAllPlanes</span>.<span style="color: black;">argtypes</span> = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">XGetImage</span>.<span style="color: black;">argtypes</span> = <span style="color: black;">&#91;</span>POINTER<span style="color: black;">&#40;</span>Display<span style="color: black;">&#41;</span>, POINTER<span style="color: black;">&#40;</span>Display<span style="color: black;">&#41;</span>,
            c_int, c_int, c_uint, c_uint, c_ulong, c_int<span style="color: black;">&#93;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">XGetPixel</span>.<span style="color: black;">argtypes</span> = <span style="color: black;">&#91;</span>POINTER<span style="color: black;">&#40;</span>XImage<span style="color: black;">&#41;</span>, c_int, c_int<span style="color: black;">&#93;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">XFree</span>.<span style="color: black;">argtypes</span> = <span style="color: black;">&#91;</span>POINTER<span style="color: black;">&#40;</span>XImage<span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">XCloseDisplay</span>.<span style="color: black;">argtypes</span> = <span style="color: black;">&#91;</span>POINTER<span style="color: black;">&#40;</span>Display<span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _set_restypes<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' Functions return type '</span><span style="color: #483d8b;">''</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'_set_restypes'</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">XOpenDisplay</span>.<span style="color: black;">restype</span> = POINTER<span style="color: black;">&#40;</span>Display<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">XDefaultScreen</span>.<span style="color: black;">restype</span> = c_int
        <span style="color: #008000;">self</span>.<span style="color: black;">XDefaultRootWindow</span>.<span style="color: black;">restype</span> = POINTER<span style="color: black;">&#40;</span>XWindowAttributes<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">XGetWindowAttributes</span>.<span style="color: black;">restype</span> = c_int
        <span style="color: #008000;">self</span>.<span style="color: black;">XAllPlanes</span>.<span style="color: black;">restype</span> = c_ulong
        <span style="color: #008000;">self</span>.<span style="color: black;">XGetImage</span>.<span style="color: black;">restype</span> = POINTER<span style="color: black;">&#40;</span>XImage<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">XGetPixel</span>.<span style="color: black;">restype</span> = c_ulong
        <span style="color: #008000;">self</span>.<span style="color: black;">XFree</span>.<span style="color: black;">restype</span> = c_void_p
        <span style="color: #008000;">self</span>.<span style="color: black;">XCloseDisplay</span>.<span style="color: black;">restype</span> = c_void_p
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> enum_display_monitors<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' Get positions of one or more monitors.
            Returns a dict with minimal requirements (see MSS class).
        '</span><span style="color: #483d8b;">''</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'enum_display_monitors'</span><span style="color: black;">&#41;</span>
&nbsp;
        results = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">oneshot</span>:
            <span style="color: #808080; font-style: italic;"># Dans le cas d'un seul screenshot pour tout, on récupère juste</span>
            <span style="color: #808080; font-style: italic;"># les coordonnées de la fenêtre racine.</span>
            gwa = XWindowAttributes<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">XGetWindowAttributes</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">display</span>, <span style="color: #008000;">self</span>.<span style="color: black;">root</span>, byref<span style="color: black;">&#40;</span>gwa<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            results.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: black;">&#123;</span>
                b<span style="color: #483d8b;">'left'</span>  : <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>gwa.<span style="color: black;">x</span><span style="color: black;">&#41;</span>,
                b<span style="color: #483d8b;">'top'</span>   : <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>gwa.<span style="color: black;">y</span><span style="color: black;">&#41;</span>,
                b<span style="color: #483d8b;">'width'</span> : <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>gwa.<span style="color: black;">width</span><span style="color: black;">&#41;</span>,
                b<span style="color: #483d8b;">'height'</span>: <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>gwa.<span style="color: black;">height</span><span style="color: black;">&#41;</span>
            <span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
&nbsp;
            <span style="color: #808080; font-style: italic;"># Sinon on parse le fichier XML de config pour essayer de</span>
            <span style="color: #808080; font-style: italic;"># trouver les coordonnées. Je ne suis pas certain que ce soit</span>
            <span style="color: #808080; font-style: italic;"># une bonne stratégie puisque le fichier monitors.xml contient</span>
            <span style="color: #808080; font-style: italic;"># tous les moniteurs jamais branché sur la machine, y compris ceux</span>
            <span style="color: #808080; font-style: italic;"># qu'on a pas branché depuis 1000 ans...</span>
&nbsp;
            <span style="color: #808080; font-style: italic;"># It is a little more complicated, we have to guess all stuff</span>
            <span style="color: #808080; font-style: italic;"># from ~/.config/monitors.xml, if present.</span>
            monitors = expanduser<span style="color: black;">&#40;</span><span style="color: #483d8b;">'~/.config/monitors.xml'</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> isfile<span style="color: black;">&#40;</span>monitors<span style="color: black;">&#41;</span>:
                <span style="color: #808080; font-style: italic;"># Ici, lever une exception serait pas mal.</span>
                <span style="color: #808080; font-style: italic;"># A la place, l'auteur choisit de mettre oneshot et de relancer</span>
                <span style="color: #808080; font-style: italic;"># la capture. Donc au lieu d'avoir ce qu'on demande ou une</span>
                <span style="color: #808080; font-style: italic;"># erreur, on a ce qu'on demande ou ce qu'on ne demande pas.</span>
                <span style="color: #808080; font-style: italic;"># Encore une fois, j'en profite pour souligner qu'il faut</span>
                <span style="color: #808080; font-style: italic;"># éviter ce genre de config à base de site effects. Devoir</span>
                <span style="color: #808080; font-style: italic;"># setter un attribut pour avoir un résultat différent à cette</span>
                <span style="color: #808080; font-style: italic;"># méthode n'est pas très propre.</span>
                <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'ERROR'</span>, <span style="color: #483d8b;">'MSSLinux: enum_display_monitors() failed (no monitors.xml).'</span><span style="color: black;">&#41;</span>
                <span style="color: #008000;">self</span>.<span style="color: black;">oneshot</span> = <span style="color: #008000;">True</span>
                <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">enum_display_monitors</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
            <span style="color: #808080; font-style: italic;"># Le XML est une collection de noeuds 'configuration' qui représentent</span>
            <span style="color: #808080; font-style: italic;"># chacun un moniteur. On récupère ici le premier noeud 'configurations'</span>
            tree = ET.<span style="color: black;">parse</span><span style="color: black;">&#40;</span>monitors<span style="color: black;">&#41;</span>
            root = tree.<span style="color: black;">getroot</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            config = root.<span style="color: black;">findall</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'configuration'</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span>-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
            conf = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
            <span style="color: #808080; font-style: italic;"># chaque noeud &quot;configurations&quot; à une série de noeuds ouput qui</span>
            <span style="color: #808080; font-style: italic;"># représentent chaque format de sortie (VGA, HDMI, etc). On</span>
            <span style="color: #808080; font-style: italic;"># boucle dessus.</span>
            <span style="color: #ff7700;font-weight:bold;">for</span> output <span style="color: #ff7700;font-weight:bold;">in</span> config.<span style="color: black;">findall</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'output'</span><span style="color: black;">&#41;</span>:
                name = output.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'name'</span><span style="color: black;">&#41;</span>
                <span style="color: #ff7700;font-weight:bold;">if</span> name <span style="color: #66cc66;">!</span>= <span style="color: #483d8b;">'default'</span>:
                    <span style="color: #808080; font-style: italic;"># On récupère les coordonnées, la rotation, on extrait,</span>
                    <span style="color: #808080; font-style: italic;"># on corrige, on ajoute à la liste... Bref, même topo</span>
                    <span style="color: #808080; font-style: italic;"># qu'avec MacOsX.</span>
                    x = output.<span style="color: black;">find</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'x'</span><span style="color: black;">&#41;</span>
                    y = output.<span style="color: black;">find</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'y'</span><span style="color: black;">&#41;</span>
                    width = output.<span style="color: black;">find</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'width'</span><span style="color: black;">&#41;</span>
                    height = output.<span style="color: black;">find</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'height'</span><span style="color: black;">&#41;</span>
                    rotation = output.<span style="color: black;">find</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'rotation'</span><span style="color: black;">&#41;</span>
                    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">None</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#91;</span>x, y, width, height<span style="color: black;">&#93;</span> <span style="color: #ff7700;font-weight:bold;">and</span> name <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> conf:
                        conf.<span style="color: black;">append</span><span style="color: black;">&#40;</span>name<span style="color: black;">&#41;</span>
                        <span style="color: #ff7700;font-weight:bold;">if</span> rotation.<span style="color: black;">text</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">'left'</span>, <span style="color: #483d8b;">'right'</span><span style="color: black;">&#93;</span>:
                            width, height = height, width
                        results.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: black;">&#123;</span>
                            b<span style="color: #483d8b;">'left'</span>    : <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>x.<span style="color: black;">text</span><span style="color: black;">&#41;</span>,
                            b<span style="color: #483d8b;">'top'</span>     : <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>y.<span style="color: black;">text</span><span style="color: black;">&#41;</span>,
                            b<span style="color: #483d8b;">'width'</span>   : <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>width.<span style="color: black;">text</span><span style="color: black;">&#41;</span>,
                            b<span style="color: #483d8b;">'height'</span>  : <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>height.<span style="color: black;">text</span><span style="color: black;">&#41;</span>,
                            b<span style="color: #483d8b;">'rotation'</span>: rotation.<span style="color: black;">text</span>
                        <span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> results
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> get_pixels<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, monitor<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' Retreive all pixels from a monitor. Pixels have to be RGB.
        '</span><span style="color: #483d8b;">''</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'get_pixels'</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># On récupère les coordonnées des monitors revoyées par enum_display_monitors</span>
        width, height = monitor<span style="color: black;">&#91;</span>b<span style="color: #483d8b;">'width'</span><span style="color: black;">&#93;</span>, monitor<span style="color: black;">&#91;</span>b<span style="color: #483d8b;">'height'</span><span style="color: black;">&#93;</span>
        left, top = monitor<span style="color: black;">&#91;</span>b<span style="color: #483d8b;">'left'</span><span style="color: black;">&#93;</span>, monitor<span style="color: black;">&#91;</span>b<span style="color: #483d8b;">'top'</span><span style="color: black;">&#93;</span>
        ZPixmap = <span style="color: #ff4500;">2</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># On récupère un masque de pixels pour l'ensemble de l'affichage</span>
        allplanes = <span style="color: #008000;">self</span>.<span style="color: black;">XAllPlanes</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'get_pixels'</span>, <span style="color: #483d8b;">'allplanes'</span>, allplanes<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Visiblement un fix. C'est ce qu'on appelle un commentaire utile.</span>
        <span style="color: #808080; font-style: italic;"># Fix for XGetImage: expected LP_Display instance instead of LP_XWindowAttributes</span>
        root = cast<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">root</span>, POINTER<span style="color: black;">&#40;</span>Display<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># On récupère un dump des pixels pour les coordonnées en cours, de</span>
        <span style="color: #808080; font-style: italic;"># l'affichage en cours, on lui applique le masque de pixel mais</span>
        <span style="color: #808080; font-style: italic;"># je ne sais pas pourquoi on doit le faire. x11 est une bestiole</span>
        <span style="color: #808080; font-style: italic;"># très tarabiscotée, et mes recherches n'ont rien donné. L'auteur</span>
        <span style="color: #808080; font-style: italic;"># a du bien s'amuser à trouver comment faire ce genre de chose.</span>
        image = <span style="color: #008000;">self</span>.<span style="color: black;">XGetImage</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">display</span>, root, left, top, width,
            height, allplanes, ZPixmap<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> image <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">None</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;">'MSSLinux: XGetImage() failed.'</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Les pixels doivent être récupérés en RGB. L'auteur fait donc une</span>
        <span style="color: #808080; font-style: italic;"># fonction de conversion (c'est une fonction inline, donc jetable)</span>
        <span style="color: #808080; font-style: italic;"># puis l'applique à la liste des pixels qu'il récupère dans l'image.</span>
        <span style="color: #808080; font-style: italic;"># Une simple boucle for aurait fait l'affaire mais l'auteur a mis</span>
        <span style="color: #808080; font-style: italic;"># en place une stratégie de mémoisation (mise en cache) dans la fonction.</span>
        <span style="color: #808080; font-style: italic;"># Vu que la fonction est inline, un simple dico aurait aussi fait</span>
        <span style="color: #808080; font-style: italic;"># l'affaire. Mais une il est très possible qu'on lui ait donné</span>
        <span style="color: #808080; font-style: italic;"># le truc et comme il n'est pas habitué à Python il a juste copié/collé.</span>
        <span style="color: #808080; font-style: italic;"># Je le fais souvent en Java / C donc je vais pas lui jeter la pierre.</span>
        <span style="color: #ff7700;font-weight:bold;">def</span> pix<span style="color: black;">&#40;</span>pixel, _resultats=<span style="color: black;">&#123;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>:
            <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' Apply shifts to a pixel to get the RGB values.
                This method uses of memoization.
            '</span><span style="color: #483d8b;">''</span>
            <span style="color: #808080; font-style: italic;"># La mise en cache se fait à ce niveau.</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> pixel <span style="color: #ff7700;font-weight:bold;">in</span> _resultats:
                <span style="color: #808080; font-style: italic;"># Là c'est du byte shifting, mais quelle logique exacte est</span>
                <span style="color: #808080; font-style: italic;"># implémentée, aucune idée. Il faudrait regarder les algos</span>
                <span style="color: #808080; font-style: italic;"># de conversion pixels vers RGB et trouver celui qui est</span>
                <span style="color: #808080; font-style: italic;"># appliqué. C'est le genre de truc que je copie/colle car</span>
                <span style="color: #808080; font-style: italic;"># je suis trop feignant et tester que ça marche est plus rapide</span>
                <span style="color: #808080; font-style: italic;"># que comprendre.</span>
                _resultats<span style="color: black;">&#91;</span>pixel<span style="color: black;">&#93;</span> = b<span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>pixel <span style="color: #66cc66;">&amp;</span> <span style="color: #ff4500;">16711680</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&gt;&gt;</span> <span style="color: #ff4500;">16</span><span style="color: black;">&#41;</span> + b<span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>pixel <span style="color: #66cc66;">&amp;</span> <span style="color: #ff4500;">65280</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&gt;&gt;</span> <span style="color: #ff4500;">8</span><span style="color: black;">&#41;</span> + b<span style="color: black;">&#40;</span>pixel <span style="color: #66cc66;">&amp;</span> <span style="color: #ff4500;">255</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">return</span> _resultats<span style="color: black;">&#91;</span>pixel<span style="color: black;">&#93;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Aliasing de la fonction pour gagner en vitesse en évitant un lookup</span>
        <span style="color: #808080; font-style: italic;"># d'attribut dans une boucle.</span>
        get_pix = <span style="color: #008000;">self</span>.<span style="color: black;">XGetPixel</span>
        <span style="color: #808080; font-style: italic;"># Boucle de conversion via une liste en intention.</span>
        pixels = <span style="color: black;">&#91;</span>pix<span style="color: black;">&#40;</span>get_pix<span style="color: black;">&#40;</span>image, x, y<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> y <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>height<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>width<span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Ici get_pixels retourne l'objet image plutôt que de la sauver</span>
        <span style="color: #808080; font-style: italic;"># dans un attribut self.image. Ouch.</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">XFree</span><span style="color: black;">&#40;</span>image<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> b<span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>pixels<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On passe maintenant à l'implémentation pour Windows</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> MSSWindows<span style="color: black;">&#40;</span>MSS<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' Mutli-screen shot implementation for Microsoft Windows. '</span><span style="color: #483d8b;">''</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Même topo que pour la version Linux. Même principe que son init.</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> init<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' Windows initialisations '</span><span style="color: #483d8b;">''</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'init'</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">GetSystemMetrics</span> = windll.<span style="color: black;">user32</span>.<span style="color: black;">GetSystemMetrics</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">EnumDisplayMonitors</span> = windll.<span style="color: black;">user32</span>.<span style="color: black;">EnumDisplayMonitors</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">GetWindowDC</span> = windll.<span style="color: black;">user32</span>.<span style="color: black;">GetWindowDC</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">CreateCompatibleDC</span> = windll.<span style="color: black;">gdi32</span>.<span style="color: black;">CreateCompatibleDC</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">CreateCompatibleBitmap</span> = windll.<span style="color: black;">gdi32</span>.<span style="color: black;">CreateCompatibleBitmap</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">SelectObject</span> = windll.<span style="color: black;">gdi32</span>.<span style="color: black;">SelectObject</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">BitBlt</span> = windll.<span style="color: black;">gdi32</span>.<span style="color: black;">BitBlt</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">GetDIBits</span> = windll.<span style="color: black;">gdi32</span>.<span style="color: black;">GetDIBits</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">DeleteObject</span> = windll.<span style="color: black;">gdi32</span>.<span style="color: black;">DeleteObject</span>
&nbsp;
        <span style="color: #008000;">self</span>._set_argtypes<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>._set_restypes<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _set_argtypes<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' Functions arguments '</span><span style="color: #483d8b;">''</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'_set_argtypes'</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">MONITORENUMPROC</span> = WINFUNCTYPE<span style="color: black;">&#40;</span>INT, DWORD, DWORD,
            POINTER<span style="color: black;">&#40;</span>RECT<span style="color: black;">&#41;</span>, DOUBLE<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">GetSystemMetrics</span>.<span style="color: black;">argtypes</span> = <span style="color: black;">&#91;</span>INT<span style="color: black;">&#93;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">EnumDisplayMonitors</span>.<span style="color: black;">argtypes</span> = <span style="color: black;">&#91;</span>HDC, LPRECT,
            <span style="color: #008000;">self</span>.<span style="color: black;">MONITORENUMPROC</span>, LPARAM<span style="color: black;">&#93;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">GetWindowDC</span>.<span style="color: black;">argtypes</span> = <span style="color: black;">&#91;</span>HWND<span style="color: black;">&#93;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">CreateCompatibleDC</span>.<span style="color: black;">argtypes</span> = <span style="color: black;">&#91;</span>HDC<span style="color: black;">&#93;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">CreateCompatibleBitmap</span>.<span style="color: black;">argtypes</span> = <span style="color: black;">&#91;</span>HDC, INT, INT<span style="color: black;">&#93;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">SelectObject</span>.<span style="color: black;">argtypes</span> = <span style="color: black;">&#91;</span>HDC, HGDIOBJ<span style="color: black;">&#93;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">BitBlt</span>.<span style="color: black;">argtypes</span> = <span style="color: black;">&#91;</span>HDC, INT, INT, INT, INT, HDC, INT, INT, DWORD<span style="color: black;">&#93;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">DeleteObject</span>.<span style="color: black;">argtypes</span> = <span style="color: black;">&#91;</span>HGDIOBJ<span style="color: black;">&#93;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">GetDIBits</span>.<span style="color: black;">argtypes</span> = <span style="color: black;">&#91;</span>HDC, HBITMAP, UINT, UINT, LPVOID,
            POINTER<span style="color: black;">&#40;</span>BITMAPINFO<span style="color: black;">&#41;</span>, UINT<span style="color: black;">&#93;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _set_restypes<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' Functions return type '</span><span style="color: #483d8b;">''</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'_set_restypes'</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">GetSystemMetrics</span>.<span style="color: black;">restypes</span> = INT
        <span style="color: #008000;">self</span>.<span style="color: black;">EnumDisplayMonitors</span>.<span style="color: black;">restypes</span> = BOOL
        <span style="color: #008000;">self</span>.<span style="color: black;">GetWindowDC</span>.<span style="color: black;">restypes</span> = HDC
        <span style="color: #008000;">self</span>.<span style="color: black;">CreateCompatibleDC</span>.<span style="color: black;">restypes</span> = HDC
        <span style="color: #008000;">self</span>.<span style="color: black;">CreateCompatibleBitmap</span>.<span style="color: black;">restypes</span> = HBITMAP
        <span style="color: #008000;">self</span>.<span style="color: black;">SelectObject</span>.<span style="color: black;">restypes</span> = HGDIOBJ
        <span style="color: #008000;">self</span>.<span style="color: black;">BitBlt</span>.<span style="color: black;">restypes</span> =  BOOL
        <span style="color: #008000;">self</span>.<span style="color: black;">GetDIBits</span>.<span style="color: black;">restypes</span> = INT
        <span style="color: #008000;">self</span>.<span style="color: black;">DeleteObject</span>.<span style="color: black;">restypes</span> = BOOL
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> enum_display_monitors<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' Get positions of one or more monitors.
            Returns a dict with minimal requirements (see MSS class).
        '</span><span style="color: #483d8b;">''</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'enum_display_monitors'</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># le code qui permet de récupérer les moniteurs est visiblement</span>
        <span style="color: #808080; font-style: italic;"># asynchrone, donc on fabrique un callback qui va remplir le tableau</span>
        <span style="color: #808080; font-style: italic;"># des résultats.</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">def</span> _callback<span style="color: black;">&#40;</span>monitor, dc, rect, data<span style="color: black;">&#41;</span>:
            rct = rect.<span style="color: black;">contents</span>
            results.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: black;">&#123;</span>
                b<span style="color: #483d8b;">'left'</span>  : <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>rct.<span style="color: black;">left</span><span style="color: black;">&#41;</span>,
                b<span style="color: #483d8b;">'top'</span>   : <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>rct.<span style="color: black;">top</span><span style="color: black;">&#41;</span>,
                b<span style="color: #483d8b;">'width'</span> : <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>rct.<span style="color: black;">right</span> - rct.<span style="color: black;">left</span><span style="color: black;">&#41;</span>,
                b<span style="color: #483d8b;">'height'</span>: <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>rct.<span style="color: black;">bottom</span> -rct.<span style="color: black;">top</span><span style="color: black;">&#41;</span>
            <span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #ff4500;">1</span>
&nbsp;
        results = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
        <span style="color: #808080; font-style: italic;"># si c'est juste un seul screenshot, c'est un appel synchrone</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">oneshot</span>:
            <span style="color: #808080; font-style: italic;"># ce sont des constantes qui déterminent quelle info ont veut que</span>
            <span style="color: #808080; font-style: italic;"># GetSystemMetrics renvoit. Ici on demande les coordonnées de tout</span>
            <span style="color: #808080; font-style: italic;"># l'écran, une par une.</span>
            SM_XVIRTUALSCREEN = <span style="color: #ff4500;">76</span>
            SM_YVIRTUALSCREEN = <span style="color: #ff4500;">77</span>
            SM_CXVIRTUALSCREEN = <span style="color: #ff4500;">78</span>
            SM_CYVIRTUALSCREEN = <span style="color: #ff4500;">79</span>
            left = <span style="color: #008000;">self</span>.<span style="color: black;">GetSystemMetrics</span><span style="color: black;">&#40;</span>SM_XVIRTUALSCREEN<span style="color: black;">&#41;</span>
            right = <span style="color: #008000;">self</span>.<span style="color: black;">GetSystemMetrics</span><span style="color: black;">&#40;</span>SM_CXVIRTUALSCREEN<span style="color: black;">&#41;</span>
            top = <span style="color: #008000;">self</span>.<span style="color: black;">GetSystemMetrics</span><span style="color: black;">&#40;</span>SM_YVIRTUALSCREEN<span style="color: black;">&#41;</span>
            bottom = <span style="color: #008000;">self</span>.<span style="color: black;">GetSystemMetrics</span><span style="color: black;">&#40;</span>SM_CYVIRTUALSCREEN<span style="color: black;">&#41;</span>
            results.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: black;">&#123;</span>
                b<span style="color: #483d8b;">'left'</span>  : <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>left<span style="color: black;">&#41;</span>,
                b<span style="color: #483d8b;">'top'</span>   : <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>top<span style="color: black;">&#41;</span>,
                b<span style="color: #483d8b;">'width'</span> : <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>right - left<span style="color: black;">&#41;</span>,
                b<span style="color: #483d8b;">'height'</span>: <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>bottom - top<span style="color: black;">&#41;</span>
            <span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            <span style="color: #808080; font-style: italic;"># On enrobe le callback Python dans un proxy qui le rend</span>
            <span style="color: #808080; font-style: italic;"># utilisable par le code C</span>
            callback = <span style="color: #008000;">self</span>.<span style="color: black;">MONITORENUMPROC</span><span style="color: black;">&#40;</span>_callback<span style="color: black;">&#41;</span>
            <span style="color: #808080; font-style: italic;"># On demande à windows de nous lister les moniteurs, et comme</span>
            <span style="color: #808080; font-style: italic;"># cet appel est asynchrone, on lui passe un callback pour qu'il</span>
            <span style="color: #808080; font-style: italic;"># replisse la liste au fur et à mesure</span>
            <span style="color: #008000;">self</span>.<span style="color: black;">EnumDisplayMonitors</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">0</span>, callback, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># On retourne la liste. A ce stade là, on ne sait pas si la liste</span>
        <span style="color: #808080; font-style: italic;"># est vide, à moitié remplie ou complètement remplie. Utiliser du</span>
        <span style="color: #808080; font-style: italic;"># code asynchrone au milieu d'une lib synchrone, c'est assez dangereux</span>
        <span style="color: #808080; font-style: italic;"># donc je me demande comment il retombe sur ses pieds.</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> results
&nbsp;
    <span style="color: #808080; font-style: italic;"># A ce stade là il est 13h, j'ai commencé à 9h et j'ai la dalle. J'en ai</span>
    <span style="color: #808080; font-style: italic;"># marre de commenter ce code. 'envoyez-vous les codes que vous pigez pas'</span>
    <span style="color: #808080; font-style: italic;"># est une idée à la con. Je vous hais tous. Mon coloc va me ramener des</span>
    <span style="color: #808080; font-style: italic;"># frites.</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> get_pixels<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, monitor<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' Retreive all pixels from a monitor. Pixels have to be RGB. '</span><span style="color: #483d8b;">''</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'get_pixels'</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Encore une fois on récupère les coordonnées des moniteurs filées</span>
        <span style="color: #808080; font-style: italic;"># par enum_display_monitors</span>
        width, height = monitor<span style="color: black;">&#91;</span>b<span style="color: #483d8b;">'width'</span><span style="color: black;">&#93;</span>, monitor<span style="color: black;">&#91;</span>b<span style="color: #483d8b;">'height'</span><span style="color: black;">&#93;</span>
        left, top = monitor<span style="color: black;">&#91;</span>b<span style="color: #483d8b;">'left'</span><span style="color: black;">&#93;</span>, monitor<span style="color: black;">&#91;</span>b<span style="color: #483d8b;">'top'</span><span style="color: black;">&#93;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Reajustement de la taille de la largeur. Je suppose que c'est</span>
        <span style="color: #808080; font-style: italic;"># empirique, mais je peux me tromper.</span>
        good_width = <span style="color: black;">&#40;</span>width <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">3</span> + <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&amp;</span> -<span style="color: #ff4500;">4</span>
        <span style="color: #808080; font-style: italic;"># Valeur de paramètre qui dit de copier directement dans le rectangle</span>
        <span style="color: #808080; font-style: italic;"># des destination.</span>
        SRCCOPY = 0xCC0020
        DIB_RGB_COLORS = <span style="color: #ff4500;">0</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Récupère le Device Context (title bar, menus, and scroll bars, etc)</span>
        srcdc = <span style="color: #008000;">self</span>.<span style="color: black;">GetWindowDC</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 fabrique une copie en mémoire.</span>
        memdc = <span style="color: #008000;">self</span>.<span style="color: black;">CreateCompatibleDC</span><span style="color: black;">&#40;</span>srcdc<span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># On fabrique un bitmap basé sur ce DC</span>
        bmp = <span style="color: #008000;">self</span>.<span style="color: black;">CreateCompatibleBitmap</span><span style="color: black;">&#40;</span>srcdc, width, height<span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># On injecte un bitmap dans le DC en mémoire.</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">SelectObject</span><span style="color: black;">&#40;</span>memdc, bmp<span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># On transfert les bits d'un DC à l'autre.</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">BitBlt</span><span style="color: black;">&#40;</span>memdc, <span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">0</span>, width, height, srcdc, left, top, SRCCOPY<span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># On fabrique le header du BMP</span>
        bmi = BITMAPINFO<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        bmi.<span style="color: black;">bmiHeader</span>.<span style="color: black;">biSize</span> = sizeof<span style="color: black;">&#40;</span>BITMAPINFOHEADER<span style="color: black;">&#41;</span>
        bmi.<span style="color: black;">bmiHeader</span>.<span style="color: black;">biWidth</span> = width
        bmi.<span style="color: black;">bmiHeader</span>.<span style="color: black;">biHeight</span> = height
        bmi.<span style="color: black;">bmiHeader</span>.<span style="color: black;">biBitCount</span> = <span style="color: #ff4500;">24</span>
        bmi.<span style="color: black;">bmiHeader</span>.<span style="color: black;">biPlanes</span> = <span style="color: #ff4500;">1</span>
        buffer_len = height <span style="color: #66cc66;">*</span> good_width
        <span style="color: #808080; font-style: italic;"># On fabrique un array de char</span>
        pixels = create_string_buffer<span style="color: black;">&#40;</span>buffer_len<span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># On récupère les bits du bitmap issu du DC</span>
        bits = <span style="color: #008000;">self</span>.<span style="color: black;">GetDIBits</span><span style="color: black;">&#40;</span>memdc, bmp, <span style="color: #ff4500;">0</span>, height, byref<span style="color: black;">&#40;</span>pixels<span style="color: black;">&#41;</span>,
            pointer<span style="color: black;">&#40;</span>bmi<span style="color: black;">&#41;</span>, DIB_RGB_COLORS<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'get_pixels'</span>, <span style="color: #483d8b;">'srcdc'</span>, srcdc<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'get_pixels'</span>, <span style="color: #483d8b;">'memdc'</span>, memdc<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'get_pixels'</span>, <span style="color: #483d8b;">'bmp'</span>, bmp<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'get_pixels'</span>, <span style="color: #483d8b;">'buffer_len'</span>, buffer_len<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'get_pixels'</span>, <span style="color: #483d8b;">'bits'</span>, bits<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'get_pixels'</span>, <span style="color: #483d8b;">'len(pixels.raw)'</span>, <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>pixels.<span style="color: black;">raw</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Nettoyage des objets.</span>
        <span style="color: #808080; font-style: italic;"># Clean up</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">DeleteObject</span><span style="color: black;">&#40;</span>srcdc<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">DeleteObject</span><span style="color: black;">&#40;</span>memdc<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">DeleteObject</span><span style="color: black;">&#40;</span>bmp<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Apparemment la récupération peut échouer et on peut vérifier</span>
        <span style="color: #808080; font-style: italic;"># cet échec en checkant la longueur. Après la cause de l'échec est</span>
        <span style="color: #808080; font-style: italic;"># un mystère</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> bits <span style="color: #66cc66;">!</span>= height <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>pixels.<span style="color: black;">raw</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">!</span>= buffer_len:
            <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;">'MSSWindows: GetDIBits() failed.'</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Réorganise les bits dans le bonne ordre et converti le format</span>
        <span style="color: #808080; font-style: italic;"># de couleur de BGR vers RGB</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Note that the origin of the returned image is in the</span>
        <span style="color: #808080; font-style: italic;"># bottom-left corner, 32-bit aligned. And it is BGR.</span>
        <span style="color: #808080; font-style: italic;"># Need to &quot;arrange&quot; that.</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>._arrange<span style="color: black;">&#40;</span>pixels.<span style="color: black;">raw</span>, good_width, height<span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _arrange<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, data, width, height<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' Reorganises data when the origin of the image is in the
            bottom-left corner and converts BGR triple to RGB. '</span><span style="color: #483d8b;">''</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'_arrange'</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># On crée une nouvelle liste pleine de zéro, et on la rempli</span>
        <span style="color: #808080; font-style: italic;"># avec la nouvelle position des pixels.</span>
        total = width <span style="color: #66cc66;">*</span> height
        scanlines = <span style="color: black;">&#91;</span>b<span style="color: #483d8b;">'0'</span><span style="color: black;">&#93;</span> <span style="color: #66cc66;">*</span> total
        <span style="color: #ff7700;font-weight:bold;">for</span> y <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>height<span style="color: black;">&#41;</span>:
            off = width <span style="color: #66cc66;">*</span> <span style="color: black;">&#40;</span>y + <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
            offset = total - off
            <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, width - <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>:
                <span style="color: #808080; font-style: italic;"># On inverse aussi la position du bleu et du rouge</span>
                scanlines<span style="color: black;">&#91;</span>off+x:off+x+<span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span> = b<span style="color: black;">&#40;</span>data<span style="color: black;">&#91;</span>offset+x+<span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>, b<span style="color: black;">&#40;</span>data<span style="color: black;">&#91;</span>offset+x+<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>, b<span style="color: black;">&#40;</span>data<span style="color: black;">&#91;</span>offset+x<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> b<span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>scanlines<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Un wrapper pour dumper un array de pixels dans un fichier</span>
<span style="color: #808080; font-style: italic;"># Typiquement un truc qui aurait pu tenir dans une fonction au lieu d'une classe.</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> MSSImage<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' This is a class to save data (raw pixels) to a picture file.
    '</span><span style="color: #483d8b;">''</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>, data=<span style="color: #008000;">None</span>, width=<span style="color: #ff4500;">1</span>, height=<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">data</span> = data
        <span style="color: #008000;">self</span>.<span style="color: black;">width</span> = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>width<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">height</span> = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>height<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;">data</span> <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">None</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;">'MSSImage: no data to process.'</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">elif</span> <span style="color: #008000;">self</span>.<span style="color: black;">width</span> <span style="color: #66cc66;">&lt;</span> <span style="color: #ff4500;">1</span> <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: #008000;">self</span>.<span style="color: black;">height</span> <span style="color: #66cc66;">&lt;</span> <span style="color: #ff4500;">1</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;">'MSSImage: width or height must be positive.'</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
    <span style="color: #808080; font-style: italic;"># Tout le boulot se passe ici.</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> dump<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, output<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">''</span><span style="color: #483d8b;">' Dump data to the image file.
            Pure python PNG implementation.
            Image represented as RGB tuples, no interlacing.
            http://inaps.org/journal/comment-fonctionne-le-png
        '</span><span style="color: #483d8b;">''</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># On ouvre le fichier en mode écriture binaire.</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>output, <span style="color: #483d8b;">'wb'</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> fileh:
            <span style="color: #808080; font-style: italic;"># Pour cette partie il faut connaitre les subtilités du format PNG</span>
            <span style="color: #808080; font-style: italic;"># pour comprendre, ce qui n'est pas mon cas. Donc je vais faire</span>
            <span style="color: #808080; font-style: italic;"># de la déduction au gros doigt mouillé.</span>
&nbsp;
            <span style="color: #808080; font-style: italic;"># Ca prend les données en pixel, ça en fait des morceaux de la bonne taille,</span>
            <span style="color: #808080; font-style: italic;"># organisés en rangés de pixels puisqu'il y a range(height) rangés.</span>
            to_take = <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">width</span> <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">3</span> + <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&amp;</span> -<span style="color: #ff4500;">4</span>
            padding = <span style="color: #ff4500;">0</span> <span style="color: #ff7700;font-weight:bold;">if</span> to_take <span style="color: #66cc66;">%</span> <span style="color: #ff4500;">8</span> == <span style="color: #ff4500;">0</span> <span style="color: #ff7700;font-weight:bold;">else</span> <span style="color: black;">&#40;</span>to_take <span style="color: #66cc66;">%</span> <span style="color: #ff4500;">8</span><span style="color: black;">&#41;</span> // <span style="color: #ff4500;">2</span>
            height, data = <span style="color: #008000;">self</span>.<span style="color: black;">height</span>, <span style="color: #008000;">self</span>.<span style="color: black;">data</span>
            scanlines = <span style="color: black;">&#91;</span>b<span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>b<span style="color: #483d8b;">'0'</span>, data<span style="color: black;">&#91;</span>to_take<span style="color: #66cc66;">*</span>y:to_take<span style="color: #66cc66;">*</span>y+to_take-padding<span style="color: black;">&#93;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> y <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>height<span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
&nbsp;
            <span style="color: #808080; font-style: italic;"># les &quot;magic bytes&quot;, le marqueur du début de fichier qui indique</span>
            <span style="color: #808080; font-style: italic;"># que c'est un fichier png</span>
            magic = pack<span style="color: black;">&#40;</span>b<span style="color: #483d8b;">'&gt;8B'</span>, <span style="color: #ff4500;">137</span>, <span style="color: #ff4500;">80</span>, <span style="color: #ff4500;">78</span>, <span style="color: #ff4500;">71</span>, <span style="color: #ff4500;">13</span>, <span style="color: #ff4500;">10</span>, <span style="color: #ff4500;">26</span>, <span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span>
&nbsp;
            <span style="color: #808080; font-style: italic;"># Les metadata du fichiers : taille de l'image, une somme de</span>
            <span style="color: #808080; font-style: italic;"># controle, la profondeur de couleur, méthode de compression,</span>
            <span style="color: #808080; font-style: italic;"># le mode d'entrelacement, etc.</span>
            <span style="color: #808080; font-style: italic;"># Header: size, marker, data, CRC32</span>
            ihdr = <span style="color: black;">&#91;</span>b<span style="color: #483d8b;">''</span>, b<span style="color: #483d8b;">'IHDR'</span>, b<span style="color: #483d8b;">''</span>, b<span style="color: #483d8b;">''</span><span style="color: black;">&#93;</span>
            ihdr<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span> = pack<span style="color: black;">&#40;</span>b<span style="color: #483d8b;">'&gt;2I5B'</span>, <span style="color: #008000;">self</span>.<span style="color: black;">width</span>, <span style="color: #008000;">self</span>.<span style="color: black;">height</span>, <span style="color: #ff4500;">8</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
            ihdr<span style="color: black;">&#91;</span><span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span> = pack<span style="color: black;">&#40;</span>b<span style="color: #483d8b;">'&gt;I'</span>, <span style="color: #dc143c;">zlib</span>.<span style="color: black;">crc32</span><span style="color: black;">&#40;</span>b<span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>ihdr<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>:<span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&amp;</span> 0xffffffff<span style="color: black;">&#41;</span>
            ihdr<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> = pack<span style="color: black;">&#40;</span>b<span style="color: #483d8b;">'&gt;I'</span>, <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>ihdr<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
            <span style="color: #808080; font-style: italic;"># l'image en elle même avec un marker de départ, les pixels</span>
            <span style="color: #808080; font-style: italic;"># et une somme de controle</span>
            <span style="color: #808080; font-style: italic;"># Data: size, marker, data, CRC32</span>
            idat = <span style="color: black;">&#91;</span>b<span style="color: #483d8b;">''</span>, b<span style="color: #483d8b;">'IDAT'</span>, b<span style="color: #483d8b;">''</span>, b<span style="color: #483d8b;">''</span><span style="color: black;">&#93;</span>
            idat<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span> = <span style="color: #dc143c;">zlib</span>.<span style="color: black;">compress</span><span style="color: black;">&#40;</span>b<span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>scanlines<span style="color: black;">&#41;</span>, <span style="color: #ff4500;">9</span><span style="color: black;">&#41;</span>
            idat<span style="color: black;">&#91;</span><span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span> = pack<span style="color: black;">&#40;</span>b<span style="color: #483d8b;">'&gt;I'</span>, <span style="color: #dc143c;">zlib</span>.<span style="color: black;">crc32</span><span style="color: black;">&#40;</span>b<span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>idat<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>:<span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&amp;</span> 0xffffffff<span style="color: black;">&#41;</span>
            idat<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> = pack<span style="color: black;">&#40;</span>b<span style="color: #483d8b;">'&gt;I'</span>, <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>idat<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
            <span style="color: #808080; font-style: italic;"># Les metadata à la fin du fichier qui sont vides.</span>
            <span style="color: #808080; font-style: italic;"># Footer: size, marker, None, CRC32</span>
            iend = <span style="color: black;">&#91;</span>b<span style="color: #483d8b;">''</span>, b<span style="color: #483d8b;">'IEND'</span>, b<span style="color: #483d8b;">''</span>, b<span style="color: #483d8b;">''</span><span style="color: black;">&#93;</span>
            iend<span style="color: black;">&#91;</span><span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span> = pack<span style="color: black;">&#40;</span>b<span style="color: #483d8b;">'&gt;I'</span>, <span style="color: #dc143c;">zlib</span>.<span style="color: black;">crc32</span><span style="color: black;">&#40;</span>iend<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&amp;</span> 0xffffffff<span style="color: black;">&#41;</span>
            iend<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> = pack<span style="color: black;">&#40;</span>b<span style="color: #483d8b;">'&gt;I'</span>, <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>iend<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
            <span style="color: #808080; font-style: italic;"># On écrit le fichier, et on retourne son nom</span>
            fileh.<span style="color: black;">write</span><span style="color: black;">&#40;</span>magic + b<span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>ihdr<span style="color: black;">&#41;</span> + b<span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>idat<span style="color: black;">&#41;</span> + b<span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>iend<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">return</span> output
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">None</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Un exemple d'usage avec l'habituel if __name__ pour éviter de</span>
<span style="color: #808080; font-style: italic;"># le lancer à l'import</span>
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
&nbsp;
    systems = <span style="color: black;">&#123;</span>
        <span style="color: #483d8b;">'Darwin'</span> : MSSMac,
        <span style="color: #483d8b;">'Linux'</span>  : MSSLinux,
        <span style="color: #483d8b;">'Windows'</span>: MSSWindows
    <span style="color: black;">&#125;</span>
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        MSS = systems<span style="color: black;">&#91;</span>system<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">KeyError</span>:
        err = <span style="color: #483d8b;">'System &quot;{0}&quot; not implemented.'</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>system<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #008000;">NotImplementedError</span><span style="color: black;">&#40;</span>err<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        mss = MSS<span style="color: black;">&#40;</span>debug=<span style="color: #008000;">False</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># One screen shot per monitor</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> filename <span style="color: #ff7700;font-weight:bold;">in</span> mss.<span style="color: black;">save</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'File &quot;{0}&quot; created.'</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>filename<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># A shot to grab them all :)</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> filename <span style="color: #ff7700;font-weight:bold;">in</span> mss.<span style="color: black;">save</span><span style="color: black;">&#40;</span>oneshot=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'File &quot;{0}&quot; created.'</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>filename<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">Exception</span> <span style="color: #ff7700;font-weight:bold;">as</span> ex:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>ex<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">raise</span></pre></div></div>

 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9219&amp;md5=f1eb1d23d5acc61bc090a71b3636e73d" 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=9224
title: Beuuuuuuuuuuu
uri: Beuuuuuuuuuuu
url: http://sametmax.com/beuuuuuuuuuuu/
content:
<p>J&#8217;ai une gueule de bois de connard.</p>
<p>Pas d&#8217;article aujourd&#8217;hui.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9224&amp;md5=88e2889f9bbfe9ad0566ef9627bd7580" 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=9228
title: Petit snippet pour obtenir un nom de fichier unique en Python
uri: Petit-snippet-pour-obtenir-un-nom-de-fichier-unique-en-Python
url: http://sametmax.com/petit-snippet-pour-obtenir-un-nom-de-fichier-unique-en-python/
content:
<p>Bidouillerie du jour, bonjour.</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;">re</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> get_unique_path<span style="color: black;">&#40;</span>path<span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;"># si le nom de fichier existe, on en cherche un autre</span>
    <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">exists</span><span style="color: black;">&#40;</span>path<span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;"># on vire l'extension</span>
        base, ext = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">splitext</span><span style="color: black;">&#40;</span>path<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">try</span>:
            <span style="color: #808080; font-style: italic;"># on extrait le compteur si il existe</span>
            base, counter, _ = <span style="color: #dc143c;">re</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">&quot; <span style="color: #000099; font-weight: bold;">\(</span>(<span style="color: #000099; font-weight: bold;">\d</span>+)<span style="color: #000099; font-weight: bold;">\)</span>$&quot;</span>, base<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">ValueError</span>:
            counter = <span style="color: #ff4500;">0</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># on reconstruit le path</span>
        path = <span style="color: #483d8b;">&quot;%s (%s)%s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>base, <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>counter<span style="color: black;">&#41;</span> + <span style="color: #ff4500;">1</span>, ext<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> path</pre></div></div>

<p>Le plus gros de l&#8217;astuce est dans :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">base, counter, _ = <span style="color: #dc143c;">re</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">&quot; <span style="color: #000099; font-weight: bold;">\(</span>(<span style="color: #000099; font-weight: bold;">\d</span>+)<span style="color: #000099; font-weight: bold;">\)</span>$&quot;</span>, base<span style="color: black;">&#41;</span></pre></div></div>

<p><code> \((\d+)\)$</code> va matcher &#8216;espace(un nombre)&#8217; à la fin d&#8217;une chaîne et <code>r.split</code> va retourner soit <code>['le chemin complet']</code> si il n&#8217;y a pas de compteur, soit <code>['base', 'compteur', '']</code> si il y en a un.</p>
<p>Du coup on <a href="http://sametmax.com/tag/unpacking/">unpack</a> tout ça, <code>_</code> étant utilisé pour signaler une variable inutilisée par convention et on a notre compteur, prêt à être incrémenté.</p>
<p>A l&#8217;usage, ça donne ça dans ipython :</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: #66cc66;">!</span>rm /tmp/<span style="color: #dc143c;">test</span><span style="color: #66cc66;">*</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> get_unique_path<span style="color: black;">&#40;</span><span style="color: #483d8b;">'/tmp/test.txt'</span><span style="color: black;">&#41;</span>
u<span style="color: #483d8b;">'/tmp/test.txt'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> get_unique_path<span style="color: black;">&#40;</span><span style="color: #483d8b;">'/tmp/test.txt'</span><span style="color: black;">&#41;</span>
u<span style="color: #483d8b;">'/tmp/test.txt'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #66cc66;">!</span>touch /tmp/<span style="color: #dc143c;">test</span>.<span style="color: black;">txt</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> get_unique_path<span style="color: black;">&#40;</span><span style="color: #483d8b;">'/tmp/test.txt'</span><span style="color: black;">&#41;</span>
u<span style="color: #483d8b;">'/tmp/test (1).txt'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #66cc66;">!</span>touch <span style="color: #483d8b;">&quot;/tmp/test (1).txt&quot;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> get_unique_path<span style="color: black;">&#40;</span><span style="color: #483d8b;">'/tmp/test.txt'</span><span style="color: black;">&#41;</span>
u<span style="color: #483d8b;">'/tmp/test (2).txt'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> get_unique_path<span style="color: black;">&#40;</span><span style="color: #483d8b;">'/tmp/test (101).txt'</span><span style="color: black;">&#41;</span>
u<span style="color: #483d8b;">'/tmp/test (101).txt'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #66cc66;">!</span>touch <span style="color: #483d8b;">'/tmp/test (101).txt'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> get_unique_path<span style="color: black;">&#40;</span><span style="color: #483d8b;">'/tmp/test (101).txt'</span><span style="color: black;">&#41;</span>
u<span style="color: #483d8b;">'/tmp/test (102).txt'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> get_unique_path<span style="color: black;">&#40;</span><span style="color: #483d8b;">'/tmp/test'</span><span style="color: black;">&#41;</span>
u<span style="color: #483d8b;">'/tmp/test'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #66cc66;">!</span>touch /tmp/<span style="color: #dc143c;">test</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> get_unique_path<span style="color: black;">&#40;</span><span style="color: #483d8b;">'/tmp/test'</span><span style="color: black;">&#41;</span>
u<span style="color: #483d8b;">'/tmp/test (1)'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> get_unique_path<span style="color: black;">&#40;</span><span style="color: #483d8b;">'/tmp/.test'</span><span style="color: black;">&#41;</span>
u<span style="color: #483d8b;">'/tmp/.test'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #66cc66;">!</span>touch <span style="color: #483d8b;">&quot;/tmp/.test&quot;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> get_unique_path<span style="color: black;">&#40;</span><span style="color: #483d8b;">'/tmp/.test'</span><span style="color: black;">&#41;</span>
u<span style="color: #483d8b;">'/tmp/.test (1)'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> get_unique_path<span style="color: black;">&#40;</span><span style="color: #483d8b;">'/tmp/test.path.text'</span><span style="color: black;">&#41;</span>
u<span style="color: #483d8b;">'/tmp/test.path.text'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #66cc66;">!</span>touch <span style="color: #483d8b;">'/tmp/test.path.text'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> get_unique_path<span style="color: black;">&#40;</span><span style="color: #483d8b;">'/tmp/test.path.text'</span><span style="color: black;">&#41;</span>
u<span style="color: #483d8b;">'/tmp/test.path (1).text'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> get_unique_path<span style="color: black;">&#40;</span><span style="color: #483d8b;">'/tmp/test.path (1)(1) (1).text'</span><span style="color: black;">&#41;</span>
u<span style="color: #483d8b;">'/tmp/test.path (1)(1) (1).text'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #66cc66;">!</span>touch <span style="color: #483d8b;">'/tmp/test.path (1)(1) (1).text'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> get_unique_path<span style="color: black;">&#40;</span><span style="color: #483d8b;">'/tmp/test.path (1)(1) (1).text'</span><span style="color: black;">&#41;</span>
u<span style="color: #483d8b;">'/tmp/test.path (1)(1) (2).text'</span></pre></div></div>

<p>Bien entendu, si vos fichiers ne seront jamais visibles par l&#8217;utilisateur, il vaut mieux se simplifier la vie et utiliser <a href="http://sametmax.com/quest-ce-quun-uuid-et-a-quoi-ca-sert/">uuid.uuid4()</a>.</p>
<p>Je pense qu&#8217;après le dossier sur les tests unitaires, je ferai un dossier regex. Aux alentours de 2018.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9228&amp;md5=c7a717aa1e9fed5ac078695f0d699a87" 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=9235
title: Templite, le moteur de template Python qui tient dans un fichier
uri: Templite-le-moteur-de-template-Python-qui-tient-dans-un-fichier
url: http://sametmax.com/templite-le-moteur-de-template-python-qui-tient-dans-un-fichier/
content:
<p><code><a href="http://sametmax.com/votre-python-aime-les-pip/">pip</a> install templite</code></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> templite <span style="color: #ff7700;font-weight:bold;">import</span> Templite
&nbsp;
template = <span style="color: #483d8b;">&quot;&quot;&quot;
This is the place where all the ${variable}$ go...
The time goes fast but everything is slow...
${for woho in whohos:}$
    ${woho}$
${:end-for}$
&quot;&quot;&quot;</span>
&nbsp;
t = Templite<span style="color: black;">&#40;</span>template<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> t.<span style="color: black;">render</span><span style="color: black;">&#40;</span>variable=<span style="color: #483d8b;">&quot;junkies&quot;</span>, whohos=<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;woo hoo&quot;</span>, <span style="color: #483d8b;">&quot;woo hoo&quot;</span>, <span style="color: #483d8b;">&quot;woo hoo hoo hoo&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Ce qui donne :</p>
<pre>This is the place where all the junkies go...
The time goes fast but everything is slow...

    woo hoo

    woo hoo

    woo hoo hoo hoo</pre>
<p>Je n&#8217;ai <a href="http://www.joonis.de/en/code/templite">pas écrit templite</a>, je l&#8217;ai juste mis sur <a href="https://pypi.python.org/pypi/templite/0.1.3">pypi</a> et <a href="https://github.com/sametmax/templite">github</a> en respectant sa paternité car il restait sous forme de snippet perdu depuis trop longtemps.</p>
<p>Vous pouvez le piper mais vraiment, ce n&#8217;est pas obligatoire, comme <a href="http://sametmax.com/sept-petites-libs-qui-changent-la-vie-dun-dev-python/">peewee</a> et <a href="http://sametmax.com/creer-un-site-avec-bottle-en-5-minutes-parceque-7-cest-impossible-voyons/">bottle</a>, il tient dans un fichier, donc on peut juste dumper le module dans son code source.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9235&amp;md5=7a8fb59429ceec1fe7ca988687ba8b22" 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=9603
title: Un planet Python Fr sur Sam et Max
uri: Un-planet-Python-Fr-sur-Sam-et-Max
url: http://sametmax.com/un-planet-python-fr-sur-sam-et-max/
content:
<p>Un planet, c&#8217;est une agrégation de flux RSS/Atom autour d&#8217;un sujet. Un planet Python Fr existe déjà sur l&#8217;AFPY, et il est à chier (no offense guys). On peut y lire beaucoup de news de l&#8217;AFPY et les état d&#8217;âmes de David Larlet, mais franchement question articles Python, on reste sur sa faim.</p>
<p>Du coup <a href="http://sametmax.com/planet-python-fr/">j&#8217;ai aggrégé toutes les sources Python Fr que j&#8217;avais sous la main.</a></p>
<p>Pour la veille informationelle, c&#8217;est beaucoup mieux. Certes, il y a encore du hors sujet, mais c&#8217;est le plus souvent des trucs que je lirais de toute façon.</p>
<p>On s&#8217;est mis dedans donc vous n&#8217;avez pas besoin de vous abonner aux deux.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9603&amp;md5=e1e3819d5cf4619f399823c41e611953" 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=9629
title: Le dossier sur la POO fait peau neuve
uri: Le-dossier-sur-la-POO-fait-peau-neuve
url: http://sametmax.com/le-dossier-sur-la-poo-fait-peau-neuve/
content:
<p>Je me répète, mais on doit énormément aux relecteurs sur ce blog. Ils ne font pas de bruit, mais ils passent derrière, tels des nettoyeurs de scènes de crimes sur notre prose sanglante.</p>
<p>Vous trouvez qu&#8217;il y a beaucoup de fautes sur le blog ? Imaginez si ils n&#8217;étaient pas là !</p>
<p>Comme le notre, leur boulot est 100% bénévole, et croyez-moi quand je vous dis que ça bouffe du temps.</p>
<p><strong>Foxmask</strong> et <strong>Kontre</strong> sont les plus actifs, donc j&#8217;aimerais les remercier particulièrement.</p>
<p>Mais il y a aussi ceux qui font ça en comment, et <strong>Réchèr</strong> vient tout juste de terminer un travail de malade sur la relecture le l&#8217;INTEGRALITE (8 parties super longues) du <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-1/">dossier sur la POO</a>. </p>
<p>Gloire aux relecteurs !</p>
<p>(Et vive le fromage)</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9629&amp;md5=3c6be67f1fe80d21d1b4833177d91e33" 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=9638
title: “C’est ton avis mec”
uri: C-est-ton-avis-mec
url: http://sametmax.com/cest-ton-avis-mec/
content:
<p>Oui connard, c&#8217;est mon avis. C&#8217;est mon compte twitter. C&#8217;est mon blog. C&#8217;est mon comment. Bien sûr que c&#8217;est mon avis. Bien sûr que c&#8217;est partial. Tu t&#8217;attendais à quoi ? Une déclaration de l&#8217;ONU ? Un truc lissé et sans couleur dont la lividité de la saveur n&#8217;a d&#8217;égale que l&#8217;aseptisation de la forme ?</p>
<p>Va te faire foutre.</p>
<p>Internet est fait pour ça. Internet est fait pour avoir de l&#8217;asymétrie et des surfaces rugueuses. Il est fait pour que les gens disent ce qu&#8217;ils pensent comme ils le pensent, pas comme on a envie de le lire.</p>
<p>Si ça ne te plait pas, c&#8217;est très simple, il suffit de bouger les cils. C&#8217;est pas un trop gros effort non ?</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9638&amp;md5=fbe59b60d7675436b02d8d56f3929ddc" 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=7363
title: Pour licencier quelqu’un, donnez lui une grosse cylindrée
uri: Pour-licencier-quelqu-un-donnez-lui-une-grosse-cylindrée
url: http://sametmax.com/pour-licencier-quelquun-donnez-lui-une-grosse-cylindree/
content:
<p>Un de mes colocs s&#8217;est trouvé une copine (très) belle, intelligente et dont la famille est (très, très, trèèèèèèès) riche. Et en plus super sympa. Attendez, ne ragequittez pas la vie tout de suite, c&#8217;est juste l&#8217;intro !</p>
<p>Comme elle est une femme libérée, tout ça, elle bosse quand même. Même pas pistonnée. Une fille bien je vous dis. Et une partie de son taff, c&#8217;est de licencier des gens. </p>
<p>C&#8217;est tout de suite moins marrant.</p>
<p>Mais en France, on ne peux pas licencier quelqu&#8217;un parce qu&#8217;il est nul à son job et vous coûte plus cher qu&#8217;il vous rapporte. Tant pis si ça coule votre boîte, soit vous vous coltinez votre boulet, soit vous le virez avec une indemnité qui vous empêchera de budgéter son remplaçant.</p>
<p>C&#8217;est génial. </p>
<p>Ah ces patrons, tous des salauds d&#8217;exploiteurs.</p>
<p>Évidement, il est rare qu&#8217;un boulet accepte de se faire détacher à l&#8217;amiable.</p>
<p>La meuf en question a donc une astuce en béton : donner une grosse voiture de fonction au mec. Oui parce qu’apparemment ça marche qu&#8217;avec les mecs.</p>
<p>Rapidement, il va se prendre des amendes pour excès de vitesse puisque  notre beau pays est truffé de radars pièges qui n&#8217;ont rien à voir avec la sécurité. Et la voiture a tellement de chevaux que passer la première est déjà un geste illégal sur la plupart des routes.</p>
<p>Le premier PV, c&#8217;est un avertissement. Le second sert à monter son dossier de renvoie pour faute. Car oui, quand c&#8217;est un véhicule de fonction, prendre une amende, c&#8217;est une faute.</p>
<p>Ouch.</p>
<p>Mais bon, c&#8217;est tellement con de devoir en arriver là. Moi je me suis fais viré de mon premier job pour avoir insulté mon employeur devant toute l&#8217;équipe (j&#8217;étais en période d&#8217;essai). Aujourd&#8217;hui, il m&#8217;arrive régulièrement de virer mes clients (si, si, mes clients).</p>
<p>Mais en France, on est encore en mode lutte des classes. Le boss est un enfoiré d&#8217;esclavagiste plein aux as. L&#8217;employé est un fainéant profiteur tire-au flanc. On ne peux pas rendre l&#8217;embauche et le renvoie ou la dem&#8217; facile, ça péterait tout le mythe. On risquerait de prendre les travailleurs pour des personnes intelligentes.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7363&amp;md5=3c816afcf3151402af683cb6749f03cb" 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=9656
title: Les exceptions sont itérables
uri: Les-exceptions-sont-itérables
url: http://sametmax.com/les-exceptions-sont-iterables/
content:
<p>Ok, c&#8217;est une bizarrerie, mais je tenais à la partager car ça m&#8217;a bien niqué : une exception est itérable 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;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">Exception</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Doh !'</span><span style="color: black;">&#41;</span>:
...     <span style="color: #ff7700;font-weight:bold;">print</span> x
...
<span style="color: black;">Doh</span> <span style="color: #66cc66;">!</span></pre></div></div>

<p>Pourquoi ? J&#8217;en ai aucune idée. Mais j&#8217;ai voulu faire un algo récursif sur des structures imbriquées contenant des exceptions. Et ça buggait. Parce que ça parcourait aussi les exceptions.</p>
<p>Le piège vicieux dans lequel peu de gens risquent de tomber vu qu&#8217;on programme pas ça tous les jours. Mais tout de même, une étrangetée de Python. Peut être un héritage de l&#8217;époque où on pouvait faire un <code>raise</code> sur une string.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9656&amp;md5=76b26b0241bc72460ee4e41b60f8516e" 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=9662
title: La plus belle manière de parser les arguments de script en python
uri: La-plus-belle-manière-de-parser-les-arguments-de-script-en-python
url: http://sametmax.com/la-plus-belle-maniere-de-parser-les-arguments-de-script-en-python/
content:
<p>On peut parser <code>sys.argv</code> à la main, mais c&#8217;est fragile.</p>
<p>On peut utiliser <a href="http://docs.python.org/2/library/getopt.html#module-getopt">getopt</a> ou <a href="http://docs.python.org/2/library/optparse.html">optpase</a>, mais c&#8217;est déprécié.</p>
<p>On peut adopter le nouveau module de la stdlib, vers <a href="http://docs.python.org/3.4/library/argparse.html">argparse</a>, mais c&#8217;est compliqué.</p>
<p>Alors j&#8217;installais toujours <a href="http://sametmax.com/sept-petites-libs-qui-changent-la-vie-dun-dev-python/">clize</a>.</p>
<p>Mais depuis que j&#8217;ai rencontré <a href="https://github.com/docopt/docopt/">docopt</a>, j&#8217;ai largué clize (c&#8217;est pas moi chérie, c&#8217;est toi) et on vit en amoureux tous les deux en élevant des scripts dans une ferme dans les Alpes.</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> docopt</pre></div></div>

<p>Docopt fonctionne à l&#8217;envers de la plupart des libs de ce genre : vous écrivez le message d&#8217;aide de votre script, et ça génère le parsing des arguments. La syntaxe de l&#8217;aide est de type posix, donc si vous avez utilisez un <code>-h</code> ou la commande <code>man</code> un jour, vous la connaissez déjà.</p>
<p>Voici comment ça marche :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #008000;">help</span> = <span style="color: #483d8b;">&quot;&quot;&quot;Le nom de mon programme trop cool
&nbsp;
Usage:
  nom_du_script.py &lt;argument_positionel&gt; [&lt;argument_positionel_optionel&gt;] [--flag-optionel]
&nbsp;
Options:
  -h --help          C'est généré automatiquement.
  --option=&lt;valeur&gt;  Description de l'option.
&nbsp;
Woot, un footer !
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> docopt <span style="color: #ff7700;font-weight:bold;">import</span> docopt
&nbsp;
arguments = docopt<span style="color: black;">&#40;</span><span style="color: #008000;">help</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>arguments<span style="color: black;">&#41;</span></pre></div></div>

<p>Si on passe rien de valide au script, l&#8217;usage est affiché automatiquement :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ python nom_du_script.py 
Usage:
  nom_du_script.py <span style="color: #000000; font-weight: bold;">&lt;</span>argument_positionel<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000; font-weight: bold;">&lt;</span>argument_positionel_optionel<span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>--flag-optionel<span style="color: #7a0874; font-weight: bold;">&#93;</span></pre></div></div>

<p>Si on demande l&#8217;aide, en option, ben, l&#8217;aide quoi :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ python nom_du_script.py <span style="color: #660033;">-h</span>
Le nom de mon programme trop cool
&nbsp;
Usage:
  nom_du_script.py <span style="color: #000000; font-weight: bold;">&lt;</span>argument_positionel<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000; font-weight: bold;">&lt;</span>argument_positionel_optionel<span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>--flag-optionel<span style="color: #7a0874; font-weight: bold;">&#93;</span>
&nbsp;
Options:
  <span style="color: #660033;">-h</span> <span style="color: #660033;">--help</span>          C<span style="color: #ff0000;">'est généré automatiquement.
  --option=&lt;valeur&gt;  Description de l'</span>option.
&nbsp;
Woot, un footer <span style="color: #000000; font-weight: bold;">!</span></pre></div></div>

<p>Et si on passe des arguments, on les récupère dans un simple dictionnaire :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ python nom_du_script.py yo
<span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #ff0000;">'--flag-optionel'</span>: False,
 <span style="color: #ff0000;">'&lt;argument_positionel&gt;'</span>: <span style="color: #ff0000;">'yo'</span>,
 <span style="color: #ff0000;">'&lt;argument_positionel_optionel&gt;'</span>: None<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
$ python nom_du_script.py yo <span style="color: #c20cb9; font-weight: bold;">man</span>
<span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #ff0000;">'--flag-optionel'</span>: False,
 <span style="color: #ff0000;">'&lt;argument_positionel&gt;'</span>: <span style="color: #ff0000;">'yo'</span>,
 <span style="color: #ff0000;">'&lt;argument_positionel_optionel&gt;'</span>: <span style="color: #ff0000;">'man'</span><span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
 $ python nom_du_script.py yo <span style="color: #660033;">--flag-optionel</span>
<span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #ff0000;">'--flag-optionel'</span>: True,
 <span style="color: #ff0000;">'&lt;argument_positionel&gt;'</span>: <span style="color: #ff0000;">'yo'</span>,
 <span style="color: #ff0000;">'&lt;argument_positionel_optionel&gt;'</span>: None<span style="color: #7a0874; font-weight: bold;">&#125;</span></pre></div></div>

<p>Ça peut générer des choses complexes avec des tas de combinaisons d&#8217;options, des sous-commandes et tout le bordel.</p>
<p>Généralement on en profite pour faire ça proprement, en mettant l&#8217;usage en docstring du script, en calant une version et en rajoutant un <code>if __main__</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot;Uber script.
&nbsp;
Usage:
  schnell.py scheisse 
  schnell.py bier 
&nbsp;
Options:
  -h --help      _o/
  --version      <span style="color: #000099; font-weight: bold;">\o</span>_
  --blitz=krieg  <span style="color: #000099; font-weight: bold;">\o</span>/
&nbsp;
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> docopt <span style="color: #ff7700;font-weight:bold;">import</span> docopt
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    <span style="color: #808080; font-style: italic;"># __doc__ contient automatiquement la docstring du module</span>
    <span style="color: #808080; font-style: italic;"># en cours</span>
    arguments = docopt<span style="color: black;">&#40;</span>__doc__, version=<span style="color: #483d8b;">'0.1'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>arguments<span style="color: black;">&#41;</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ python schnell.py <span style="color: #660033;">--version</span>
<span style="color: #000000;">0.1</span>
&nbsp;
$ python schnell.py bier
<span style="color: #7a0874; font-weight: bold;">&#123;</span><span style="color: #ff0000;">'bier'</span>: True,
 <span style="color: #ff0000;">'scheisse'</span>: False<span style="color: #7a0874; font-weight: bold;">&#125;</span></pre></div></div>

 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9662&amp;md5=d794d650afce14807a5b1485a808d91a" 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=9678
title: Le sourire du jour
uri: Le-sourire-du-jour
url: http://sametmax.com/le-sourire-du-jour/
content:
<p>Je me baladais dans le code source de path.py, et je suis tombé sur l&#8217;auteur essayant de résoudre le problème suivant :</p>
<p>&#8220;Soit une chaine &#8216;mode&#8217; représentant le mode d&#8217;ouverture du fichier, détecter si le fichier est demandé à être ouvert en écriture et dans ce cas lever une exception&#8221;</p>
<p>L&#8217;implémentation naïve serait:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">for</span> letter <span style="color: #ff7700;font-weight:bold;">in</span> mode:
    <span style="color: #ff7700;font-weight:bold;">if</span> letter <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #483d8b;">'wa+'</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;">'Only read-only file modes can be used'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Une implémentation un peu plus classe serait :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">any</span><span style="color: black;">&#40;</span>letter <span style="color: #ff7700;font-weight:bold;">for</span> letter <span style="color: #ff7700;font-weight:bold;">in</span> mode <span style="color: #ff7700;font-weight:bold;">if</span> letter <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #483d8b;">'wa+'</span><span style="color: black;">&#41;</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;">'Only read-only file modes can be used'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Mais l&#8217;auteur a choisit d&#8217;utiliser les sets, qui sont exactement fait pour ça. Et la solution est simple et élégante:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">set</span><span style="color: black;">&#40;</span>mode<span style="color: black;">&#41;</span>.<span style="color: black;">intersection</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'wa+'</span><span style="color: black;">&#41;</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;">'Only read-only file modes can be used'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Je sais, il m&#8217;en faut pas grand chose pour être heureux.</p>
<hr />
<p>Edit: explication demandée en comments :)</p>
<p>Un <code>set</code> permet de prendre n&#8217;importe quel itérable, et créer un ensemble avec. Il est capable de faire toutes les opérations ensemblistes (union, différence, etc) entre lui-même et un autre itérable.</p>
<p>Dans notre cas, si le mode contient un flag qui implique l&#8217;écriture, voici ce que ça donne en détails :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> mode = <span style="color: #483d8b;">'wb'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> set_de_mode = <span style="color: #008000;">set</span><span style="color: black;">&#40;</span>mode<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> set_de_mode
<span style="color: #008000;">set</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>u<span style="color: #483d8b;">'b'</span>, u<span style="color: #483d8b;">'w'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> set_de_mode.<span style="color: black;">intersection</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'wa+'</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">set</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>u<span style="color: #483d8b;">'w'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>On se retrouve donc avec un élément dans le <code>set</code> résultant de l&#8217;intersection. Un <code>set</code> non vide a une valeur <code>True</code> dans un contexte booléen en Python, donc la condition<code>if set(mode).intersection('wa+'):</code> sera remplie.</p>
<p>A l&#8217;inverse, si il n&#8217;y a pas de flag qui implique l&#8217;écriture :</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;">set</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'r'</span><span style="color: black;">&#41;</span>.<span style="color: black;">intersection</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'wa+'</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">set</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>On obtient un <code>set</code> vide, qui vaut <code>False</code> dans un contexte booléen.</p>
<p>Tout ceci marche car les chaînes de caractères sont itérables en Python, et que les sets acceptent n&#8217;importe quel itérable. Vive le duck typing.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9678&amp;md5=e7680ca28d8d5d7c58d25e80a2786d4a" 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=9688
title: Le point sur les derniers événements autour de Bitcoin
uri: Le-point-sur-les-derniers-événements-autour-de-Bitcoin
url: http://sametmax.com/le-point-sur-les-derniers-evenements-autour-de-bitcoin/
content:
<p>MtGox, la plus grande plateforme d&#8217;échange de Bitcoin, située au Japon, a connu une crise sans précédent. Ce n&#8217;est pas la première, même très grave, mais je pense que celle-ci lui sera fatale. Car les précédentes étaient techniques, et ici, il y a en plus une crise de confiance envers les humains derrière. Et avec Bitcoin, la confiance est tout.</p>
<p>D&#8217;autres plateformes connaissent des soucis, comme Flexcoin. Il y a en a eu d&#8217;autres par le passé. Il y en aura encore d&#8217;autres dans le futur.</p>
<p>Maintenant voici ce que personne ne semble vouloir dire dans les media en ce moment&#8230;</p>
<p><strong>Tout ceci est absolument normal.</strong></p>
<p>Comme Bitcoin est sulfureux, et en plus très technique, les fantasmes et les projections les plus grandes sont faites aux dépends de l&#8217;analyse et la rationalisation.</p>
<h2>Bitcoin est un projet expérimental</h2>
<p><a href="http://sametmax.com/quest-ce-que-bitcoin/">Je l&#8217;ai dit,</a> et je le répète, Bitcoin est une expérience. Et ce n&#8217;est PAS une expérience technique. C&#8217;est une expérience sociale.</p>
<p>Qui de surcroît touche la notion d&#8217;échange de biens et de services, la notion de richesse, de propriété, de circulation de ceux-ci et d&#8217;évaluation de valeurs.</p>
<p>Il est absolument normal que ça parte dans tous les sens. On ne peut pas faire quelque chose de radicalement nouveau affectant massivement un sujet des plus sensibles sans des conséquences importantes, et parfois graves.</p>
<p><a href="http://www.livestream.com/kaamelottwtv/video?clipId=flv_3e53a6ea-3f2e-4009-863f-e2edf5298be8">Quand on veut être sûr de son coup, Seigneur Dagonet… on plante des navets. On ne pratique pas le putsch.</a></p>
<p>Donc si on cherche la sécurité, on ne participe pas au projet Bitcoin. Le projet n&#8217;est PAS sûr. Il n&#8217;est pas fait pour ça. Il n&#8217;a JAMAIS été présenté comme ça.</p>
<h2>Bitcoin est un projet jeune</h2>
<p>La monnaie existe depuis <a href="http://fr.wikipedia.org/wiki/Histoire_de_la_monnaie">quelques milliers d&#8217;années</a>. On a donc de l&#8217;expérience avec : infrastructures, sécurisation, mécanisme de fluctuation, comportement de la population à son égard, stockage, conversion, utilisation, et tout le tutti quanti.</p>
<p>De millions d&#8217;arnaques, de vols, de fraudes, de manipulations et autres malversations. On commence à avoir l&#8217;habitude, parce qu&#8217;on a littéralement tout vu.</p>
<p>Et malgré ça, notre système économique n&#8217;est pas vraiment ce qu&#8217;on pourrait appeler en forme.</p>
<p>Avec Bitcoin on a 5 ans de pratique. Une poussière. Que dalle. Vous vous attendez à quoi ?</p>
<p>Quelques talentueux hackers mettent en place des plateformes d&#8217;échanges. Aussi malins qu&#8217;ils soient, ils ont en face d&#8217;eux des voleurs qui ont des milliers d&#8217;années d&#8217;expérience dans lesquelles puiser. Forcément, ça va se planter.</p>
<p>Ça arrive maintenant parce qu&#8217;il y du pognon en jeu. Parce que le Bitcoin vaut maintenant vraiment le coup de tabasser un mec et lui mettre un flingue sur la tempe. </p>
<p><strong>Précisément parce que le Bitcoin est en train de remplir sa mission, on se retrouve avec des explosions de partout.</strong></p>
<p>Le Bitcoin ne peut pas ne pas passer par là. Il ne peut pas devenir un outil crédible pour l&#8217;humanité sans qu&#8217;on passe par des phases de chaos. Auxquelles il devra survivre, ou mourir, tué par le darwinisme économique.</p>
<h2>Vous faites de la merde</h2>
<p>Les problèmes actuellement liés aux Bitcoin sont typiquement d&#8217;ordre PBCK.</p>
<p>Bitcoin n&#8217;est pas parfait, mais jusqu&#8217;ici son fonctionnement n&#8217;a pas encore été pris en défaut. Je ne dis pas que ça n&#8217;arrivera jamais, bien au contraire, je parie sur le fait que ça arrivera. Ça fait partie du deal. Évoluer ou crever.</p>
<p>Mais ce n&#8217;est pas le cas pour le moment.</p>
<p>Pour le moment, la raison pour laquelle il y a des tels problèmes, c&#8217;est que <strong>beaucoup d&#8217;utilisateurs de Bitcoin ne l&#8217;utilisent pas dans le but pour lequel il a été conçu</strong>.</p>
<p>D&#8217;abord, Bitcoin est actuellement massivement spéculatif. Il n&#8217;a pas été conçu pour ça. C&#8217;est un système fait pour échanger de la valeur, pas pour spéculer. Qui dit spéculation, dit manipulation.</p>
<p>Et vous avez en face des grosses entités qui sont spécialisées là dedans depuis des siècles. Ils savent influencer les marchés et se faire de la thune avec votre pognon depuis toujours. En n&#8217;utilisant pas Bitcoin pour acheter, mais pour spéculer, on se met à la merci de ces puissances.</p>
<p>Surprise, vous savez comment se comporte le cours du Bitcoin depuis la disparition de tous ces BTC ? Le cours remonte. Car quand on a acquis une grosse quantité de butin, il faut l&#8217;écouler à une valeur intéressante. Je ne serai donc pas surpris que le cours soit actuellement artificiellement poussé à la hausse par les mêmes personnes qui ont chouré le magot. Comment ils le feraient ? Aucune idée. Mais on a vu des trucs plus fous à la bourse. Nous sommes des noobs face à des pros du monde de la finance.</p>
<p>Ensuite, <strong>Bitcoin est décentralisé, et vous (enfin vous, si vous avez perdu du pognon sur MTGox), pauvres cons, vous le stockez sur des plateformes centralisées.</strong> En gros vous reproduisez le schéma bancaire classique avec une technologie qui est faite pour émanciper l&#8217;individu du système.</p>
<p>Ce genre d&#8217;attaque est doublement une bonne chose :</p>
<ul>
<li>Cela va renforcer notre expérience de la manipulation dans la vie réelle d&#8217;une telle puissance financière. D&#8217;autres échanges vont prendre le relais, plus sécurisés, plus robustes, plus souples, etc.</li>
<li>Cela sert de piqure de rappel aux utilisateurs que les bitcoins sont la responsabilité de LEUR PROPRIÉTAIRE. Le but est de mettre les finances dans les mains de tous, ça implique de se prendre en main.</li>
</ul>
<h2>Bref, Bitcoin n&#8217;est toujours pas mort</h2>
<p>L&#8217;expérience continue, avec ses hauts et ses bas. C&#8217;est plus passionnant que jamais, je pense que son créateur n&#8217;a jamais imaginé l&#8217;impact de ce qu&#8217;il a lancé. Bitcoin, un logiciel qui ne fait qu&#8217;envoyer des calculs mathématiques sans valeur concrète à travers des tuyaux, est en train d&#8217;influencer le monde entier.</p>
<p>Pour le meilleur, ou pour le pire, jusqu&#8217;à ce que sa mort nous sépare.</p>
<p>Et si vous croyez que l&#8217;on a vu le pire, c&#8217;est que vous n&#8217;avez pas encore compris. Si Bitcoin fini par être un succès, alors jusqu&#8217;ici, on a été dans la partie calme et facile de sa vie.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9688&amp;md5=19dc8c53f2333531d2e6a20795a976c1" 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=9703
title: Un petit goût de meteor.js en Python
uri: Un-petit-goût-de-meteor-js-en-Python
url: http://sametmax.com/un-petit-gout-de-meteor-js-en-python/
content:
<p>Je n&#8217;ai jamais caché ma jalousie envers les codeurs Javascript sous <a href="https://www.meteor.com/">meteor.js</a>. C&#8217;est à mon sens la techno la plus révolutionnaire en matière de dev Web depuis l&#8217;invention des frameworks HTTP.</p>
<p>Ca permet notamment de faire du PUB/SUB entre le navigateur et le serveur. C&#8217;est à dire qu&#8217;un navigateur déclenche un événement, le serveur le reçoit, et tous les browsers abonnés le reçoivent aussi. Du coup, on modifie une page, toutes les autres pages sont modifiées en temps réel.</p>
<p>Dommage que ce soit codé dans un langage pourri.</p>
<p>Heureusement depuis quelques temps, un standard est en train d&#8217;émerger autour du RPC et PUB/SUB entre navigateurs et serveurs : <a href="http://wamp.ws/">WAMP</a>. Il existe du coup des implémentations du protocole en plusieurs langages, donc une en Python avec <a href="http://autobahn.ws/python/">autobahn</a>.</p>
<p>Ca s&#8217;utilise ainsi : <code><a href="http://sametmax.com/votre-python-aime-les-pip/">pip</a> install autobahn</code>.</p>
<p>Puis, un petit coup de Python :</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;">from</span> twisted.<span style="color: black;">python</span> <span style="color: #ff7700;font-weight:bold;">import</span> log
<span style="color: #ff7700;font-weight:bold;">from</span> twisted.<span style="color: black;">internet</span> <span style="color: #ff7700;font-weight:bold;">import</span> reactor
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> autobahn.<span style="color: black;">twisted</span>.<span style="color: black;">websocket</span> <span style="color: #ff7700;font-weight:bold;">import</span> listenWS
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> autobahn.<span style="color: black;">wamp1</span>.<span style="color: black;">protocol</span> <span style="color: #ff7700;font-weight:bold;">import</span> WampServerFactory, WampServerProtocol
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> MyPubSubServerProtocol<span style="color: black;">&#40;</span>WampServerProtocol<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> onSessionOpen<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;"># On choisit un namespace pour enregistrer ses events PUB/SUB</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">registerForPubSub</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;http://example.com/events/bam&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
   <span style="color: #808080; font-style: italic;"># on lance notre serveur avec moult verbosité</span>
   log.<span style="color: black;">startLogging</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">stdout</span><span style="color: black;">&#41;</span>
   wampFactory = WampServerFactory<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;ws://127.0.0.1:9000&quot;</span>, debugWamp=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
   wampFactory.<span style="color: black;">protocol</span> = MyPubSubServerProtocol
   listenWS<span style="color: black;">&#40;</span>wampFactory<span style="color: black;">&#41;</span>
   reactor.<span style="color: black;">run</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>On lance le serveur directement :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">python votre_script.py</pre></div></div>

<p>Côté client (pas besoin de serveur, on peut l&#8217;ouvrir dans le browser cash pistache) :</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;script src=&quot;http://code.jquery.com/jquery-1.11.0.min.js&quot;&gt;&lt;/script&gt;
    &lt;script src=&quot;https://raw.github.com/tavendo/AutobahnPython/master/examples/twisted/wamp1/pubsub/simple/example1/autobahn.min.js&quot;&gt;&lt;/script&gt;
    &lt;script type=&quot;text/javascript&quot;&gt;
&nbsp;
    $(function(){
        ab.connect(&quot;ws://localhost:9000&quot;, function(session) {
&nbsp;
            $('#foo').click(function(){
                // au clic sur le bouton, on envoit un evenement BAM
                session.publish('http://example.com/events/bam', ['bam']);
&nbsp;
                // On ajoute bam à la liste en local car le publisher ne
                // reçoit pas ses propres events
                $('#doh').append('&lt;li&gt;bam&lt;/li&gt;');
            });
&nbsp;
            session.subscribe('http://example.com/events/bam', function(topic, evt){
                // on s'inscrit pour recevoir l'event quand il est
                // déclenché. Ceci marchera dans tout autre tab que celui
                // qui a déclenché l'event
                $('#doh').append('&lt;li&gt;bam&lt;/li&gt;');
            });
        })
&nbsp;
    });
&nbsp;
    &lt;/script&gt;
&nbsp;
&lt;/head&gt;
&nbsp;
&lt;body&gt;
&nbsp;
&lt;!-- Notre liste qui va se remplir de bam ! --&gt;
&lt;ul id=&quot;doh&quot;&gt;&lt;/ul&gt;
&lt;button id=&quot;foo&quot; value=&quot;Bam&quot;&gt;Bam&lt;/button&gt;
&nbsp;
&lt;/body&gt;
&lt;/html&gt;</pre></div></div>

<p>Ce qui ce passe, c&#8217;est que quand j&#8217;appuie sur le bouton &#8220;Bam&#8221;, ça envoit un événement Bam au serveur via Websocket, qui propage l&#8217;événement à tous les clients. Donc tous les tabs ouverts sur cette page récupèrent l&#8217;événement et peuvent y réagir. Ici, les deux pages sont mises à jour en simultané. </p>
<div id="attachment_9705" class="wp-caption aligncenter" style="width: 610px"><a href="media/3f82924b.out.gif" data-original-source="http://sametmax.com/wp-content/uploads/2014/03/out.gif"><img src="media/3f82924b.out.gif" data-original-source="http://sametmax.com/wp-content/uploads/2014/03/out.gif" alt="Mise à jour de deux pages web en simultané avec autobahn" title="Chez moi ça marche" width="600" height="160" class="size-full wp-image-9705" /></a><p class="wp-caption-text">Chez moi ça marche</p></div>
<p>Bien entendu, ceci est un exemple très basique fait pour vous donner un avant goût de la techno. D&#8217;ailleurs, meteor.js, c&#8217;est bien plus que du PUB/SUB. Il y a de la gestion de la deco, la synchro de la base côté client, le hot push de code, etc. Ils ont fait un vrai travail de fond sur les problématiques concrètes. </p>
<p>Donc on en est encore loin, surtout que même leur techno est toujours expérimentale. Mais on a enfin de quoi rattraper le temps perdu. Et avec asyncio, îl n&#8217;y aura même pas besoin de dépendre de twisted pour ce faire. 2014 va être trop fun !</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9703&amp;md5=3683e98d24820ccc9578ee452ba96981" 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=9687
title: One myth down, pass it around
uri: One-mythe-down-pass-it-around
url: http://sametmax.com/one-mythe-down-pass-it-around/
content:
<p>Elle existe. Je l&#8217;ai rencontrée.</p>
<p>On avait demandé un coup de main à des amis pour des travaux, et elle avait proposé de venir. L&#8217;ambiance était plutôt poussière et transpiration en mode vêtement de clodo, alors quand elle s&#8217;est pointé avec des talons hauts et une bouteille de rosé, on a un peu tiqué.</p>
<p>Mais bon, mon coloc me la présente comme une copine, et c&#8217;était le moment de faire une pause de toute façon, alors pourquoi se prendre la tête ? Et puis il n&#8217;y a jamais assez de jolies rouquines sur les chantiers.</p>
<p>Assez rapidement on se rend compte qu&#8217;elle est complètement déchirée et n&#8217;a pas vraiment compris le principe du mot &#8220;travaux&#8221;. Elle demande un tire-bouchon, mais y en pas dans la boîte à outil. Elle a l&#8217;air vraiment déçue, alors j&#8217;entreprends de l&#8217;ouvrir à la savate.</p>
<p>Pour ceux qui ne connaissent pas cette technique de vieux sioux alcoolique, ça consiste à mettre la bouteille dans une chaussure de manière à ce que son cul touche la semelle côté talon, et ensuite taper l&#8217;extérieur du dit talon contre un mur jusqu&#8217;à ce que le bouchon sorte, ce qui peut prendre quelques minutes.</p>
<p>C&#8217;est fatiguant, et ça secoue méchamment le vin, donc je ne recommande pas ça à la soirée de monsieur Duran.</p>
<p>Bref, j&#8217;arrive avec le bouchon à moitié sorti, ses yeux se mettent à briller. J&#8217;explique que je vais l&#8217;ouvrir dans les chiottes parce que j&#8217;ai peur d&#8217;en mettre partout. J&#8217;entre, elle entre avec moi et et ferme la porte.</p>
<p>Je précise que je ne la connais toujours pas. En fait, je ne sais même pas comment elle s&#8217;appelle.</p>
<p>Elle se penche vers moi pour me rouler une pelle, puis recule et me demande :</p>
<p>&#8220;Attend, t&#8217;es venu avec qui déjà ?&#8221;</p>
<p>Prise de conscience.</p>
<p>&#8220;La bouteille.&#8221;</p>
<p>Je l&#8217;ouvre, on sort. Elle est déjà en train d&#8217;enlacer un autre pote. Dans la seconde. La seconde, je vous dis.</p>
<p>Qui est un peu gêné parce que sa copine à lui est à approximativement 3 mètres en train d&#8217;halluciner.</p>
<p>Notre personnage principal va donc faire du body-body avec tous les mecs présents en environ 15 minutes, puis, réalisant que personne n&#8217;étaient vraiment chauds, s&#8217;allonge sur le canapé, et s’endort pour le reste de la soirée.</p>
<p>Mon coloc m&#8217;expliquera plus tard :</p>
<p>&#8220;Elle est gentille mais elle peut rapidement te flinguer une soirée. Elle va pas faire gaffe aux couples et ça peut vite partir en fight. Par contre si tu t’ennuies ce soir&#8230;&#8221;</p>
<p>&#8220;Mais pourquoi tu l&#8217;as invité aujourd&#8217;hui ?&#8221;</p>
<p>&#8220;Je sais pas, elle a proposé, je me suis dis, plus on a de bras&#8230;&#8221;</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9687&amp;md5=f38eebd85ad2ffdfff5be7bbb467ee6b" 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=9725
title: Configurer un outil de merge pour git sous Windows
uri: Configurer-un-outil-de-merge-pour-git-sous-Windows
url: http://sametmax.com/configurer-un-outil-de-merge-pour-git-sous-windows/
content:
<p>Si vous utilisez msysgit, il n&#8217;y a pas d&#8217;outil pratique préinstallé pour gérer ce qui suit un  <code>git mergetool</code>. Le plus simple à configurer est kdiff3. Il suffit de le <a href="http://sourceforge.net/projects/kdiff3/files/">télécharger</a> et installer, puis de rajouter ceci dans votre fichier .gitconfig :</p>

<div class="wp_syntax"><div class="code"><pre class="ini" style="font-family:monospace;"><span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>diff<span style="">&#93;</span></span>
    <span style="color: #000099;">tool</span> <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> kdiff3</span>
	<span style="color: #000099;">keepBackup</span> <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> false</span>
	<span style="color: #000099;">prompt</span> <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> false</span>
<span style="color: #000066; font-weight:bold;"><span style="">&#91;</span>merge<span style="">&#93;</span></span>
    <span style="color: #000099;">tool</span> <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> kdiff3</span>
	<span style="color: #000099;">keepBackup</span> <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> false</span>
	<span style="color: #000099;">prompt</span> <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> false</span>
<span style="">&#91;</span>mergetool <span style="color: #933;">&quot;kdiff3&quot;</span><span style="">&#93;</span>
    <span style="color: #000099;">path</span> <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> C:/Program Files <span style="">&#40;</span>x86<span style="">&#41;</span>/KDiff3/kdiff3.exe</span>
    <span style="color: #000099;">trustExitCode</span> <span style="color: #000066; font-weight:bold;">=</span><span style="color: #660066;"> false</span></pre></div></div>

<p>Remplacez &#8220;C:/Program Files (x86)/KDiff3/kdiff3.exe&#8221; par le bon chemin selon votre système, bien entendu.</p>
<p>kdiff3 a tendance à laisser trainer des fichiers *.orig après le merge, et ça peut se régler dans <code>Configure/Options > Directory Merge > Backup Files (*.orig).<br />
</code><br />
Ainsi votre prochain merge ouvrira tranquilement kdiff3 pour chaque conflit.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9725&amp;md5=aefd8758728a3545ca02489e695b6f6f" 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=9731
title: Faire manger du datetime à JSON en Python
uri: Faire-manger-du-datetime-à-JSON-en-Python
url: http://sametmax.com/faire-manger-du-datetime-a-json-en-python/
content:
<p>La guerre de la <a href="http://sametmax.com/yaml-xml-json-csv-ini-quest-ce-que-cest-et-a-quoi-ca-sert/">sérialisation</a> a plus ou moins été gagnée par JSON. Le XML est relégué aux documents très riches et aux systèmes legacy. Le YML est cantonné a des niches (et en plus souvent des niches en Ruby, c&#8217;est dire !). Et les formats binaires, sont gardés pour les besoins de perf. Le reste, c&#8217;est du JSON, du JSON et du JSON.</p>
<p>Seulement le JSON ne permet pas de sauvegarder des dates, seulement des chaînes, des entiers, des booléens et null. Heureusement on peut créer son propre dialecte au dessus de JSON pour y remédier, mais il faut avoir un un parseur qui le gère.</p>
<p>En Python on peut créer sa propre classe d&#8217;encodeur et décodeur de JSON et donc techniquement ajouter n&#8217;importe quel type.</p>
<p>Voici une recette pour en créer un qui gère le type <code>datetime</code> de manière transparente :</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;">re</span>
<span style="color: #ff7700;font-weight:bold;">import</span> json
&nbsp;
<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;
<span style="color: #808080; font-style: italic;"># On hérite simplement de l'encodeur de base pour faire son propre encodeur</span>
<span style="color: #ff7700;font-weight:bold;">class</span> JSONEncoder<span style="color: black;">&#40;</span>json.<span style="color: black;">JSONEncoder</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;"># Cette méthode est appelée pour serialiser les objets en JSON</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> default<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, obj<span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;"># Si l'objet est de type datetime, on retourne une chaîne formatée</span>
        <span style="color: #808080; font-style: italic;"># représentant l'instant de manière classique</span>
        <span style="color: #808080; font-style: italic;"># ex: &quot;2014-03-09 19:51:32.7689&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>obj, <span style="color: #dc143c;">datetime</span><span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">return</span> obj.<span style="color: black;">strftime</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'%Y-%m-%d %H:%M:%S.%f'</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> json.<span style="color: black;">JSONEncoder</span>.<span style="color: black;">default</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, obj<span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;"># On fait l'opération exactement inverse pour le décodeur</span>
<span style="color: #ff7700;font-weight:bold;">class</span> JSONDecoder<span style="color: black;">&#40;</span>json.<span style="color: black;">JSONDecoder</span><span style="color: black;">&#41;</span>:
&nbsp;
&nbsp;
    <span style="color: #808080; font-style: italic;"># On écrase la méthode qui permet de décoder les paires clé / valeur</span>
    <span style="color: #808080; font-style: italic;"># du format JSON afin que chaque valeur passe par notre moulinette</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> object_pairs_hook<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, obj<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">dict</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>k, <span style="color: #008000;">self</span>.<span style="color: black;">decode_on_match</span><span style="color: black;">&#40;</span>v<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> k, v <span style="color: #ff7700;font-weight:bold;">in</span> obj<span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
    <span style="color: #808080; font-style: italic;"># notre moulinette</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> decode_on_match<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, obj<span style="color: black;">&#41;</span>:
&nbsp;
        <span style="color: #808080; font-style: italic;"># une petite regex permet de savoir si la chaine est une date</span>
        <span style="color: #808080; font-style: italic;"># sérialisée selon notre format précédent</span>
        match = <span style="color: #dc143c;">re</span>.<span style="color: black;">search</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\d</span>{4}-<span style="color: #000099; font-weight: bold;">\d</span>{2}-<span style="color: #000099; font-weight: bold;">\d</span>{2} <span style="color: #000099; font-weight: bold;">\d</span>{2}:<span style="color: #000099; font-weight: bold;">\d</span>{2}:<span style="color: #000099; font-weight: bold;">\d</span>{2}<span style="color: #000099; font-weight: bold;">\.</span><span style="color: #000099; font-weight: bold;">\d</span>{6}'</span>, <span style="color: #008000;">unicode</span><span style="color: black;">&#40;</span>obj<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># si oui, on parse et on retourne le datetime</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> match:
            <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #dc143c;">datetime</span>.<span style="color: black;">strptime</span><span style="color: black;">&#40;</span>match.<span style="color: #dc143c;">string</span>, <span style="color: #008000;">self</span>.<span style="color: black;">datetime_format</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># sinon on retourne l'objet tel quel</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> obj
&nbsp;
<span style="color: #808080; font-style: italic;"># On se fait des raccourcis pour loader et dumper le json</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> json_dumps<span style="color: black;">&#40;</span>data<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> JSONEncoder<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">encode</span><span style="color: black;">&#40;</span>data<span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> json_loads<span style="color: black;">&#40;</span><span style="color: #dc143c;">string</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> JSONDecoder<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">decode</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">string</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Usage :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> res = json_dumps<span style="color: black;">&#40;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">'test'</span>: <span style="color: #dc143c;">datetime</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2000</span>, <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>, <span style="color: #483d8b;">'autre'</span>: <span style="color: black;">&#91;</span><span style="color: #008000;">True</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #008000;">type</span><span style="color: black;">&#40;</span>res<span style="color: black;">&#41;</span>, res<span style="color: black;">&#41;</span>
<span style="color: black;">&#40;</span><span style="color: #66cc66;">&lt;</span>type <span style="color: #483d8b;">'str'</span><span style="color: #66cc66;">&gt;</span>, <span style="color: #483d8b;">'{&quot;test&quot;: &quot;2000-01-01 01:01:01.000000&quot;, &quot;autre&quot;: [true, 1]}'</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> res = json_loads<span style="color: black;">&#40;</span>res<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #008000;">type</span><span style="color: black;">&#40;</span>res<span style="color: black;">&#41;</span>, res<span style="color: black;">&#41;</span>
<span style="color: black;">&#40;</span><span style="color: #66cc66;">&lt;</span>type <span style="color: #483d8b;">'dict'</span><span style="color: #66cc66;">&gt;</span>, <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'test'</span>: u<span style="color: #483d8b;">'2000-01-01 01:01:01.000000'</span>, u<span style="color: #483d8b;">'autre'</span>: <span style="color: black;">&#91;</span><span style="color: #008000;">True</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span></pre></div></div>

<p><a href="http://sametmax.com/minibelt-la-petite-soeur-de-batbelt/">Minibelt</a> contient une version un peu plus élaborée de ce code qui prend en compte les types <code>date</code>, <code>time</code> et <code>timedelta</code> ainsi que pas mal d&#8217;options de configuration.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9731&amp;md5=41f8d7e40b6cca36be4589bea0a171c8" 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=9739
title: Travailler via des start up éphémères
uri: Travailler-via-des-start-up-éphémères
url: http://sametmax.com/travailler-via-des-start-up-ephemeres/
content:
<p>Petite correspondance à la gare d&#8217;Austerlitz. Il fait beau, des ados massacrent joyeusement &#8220;No woman, no cry&#8221; sur le piano en libre service de la station, et ça me met de très bonne humeur. J&#8217;ai rendez-vous avez <a href="http://sametmax.com/author/cortex/">Cortex</a>, dont vous n&#8217;avez pas entendu parler depuis longtemps, pour un verre en compagnie du Stégosaure en bois du parc du musée d&#8217;histoire naturelle afin de passer le temps.</p>
<p>On se raconte qui et quoi. Comment va machin, est-ce que tu as vu le nouveau joujou truc ?</p>
<p>Et puis ça parle boulot, parce qu&#8217;on fait ce qu&#8217;on fait car on aime le faire, et la passion, c&#8217;est plus ou moins ce qui nous réunit.</p>
<p>Il m&#8217;explique que depuis quelques temps, il a un nouveau concept de travail : les start up éphémères.</p>
<p>On lui confie des missions, généralement des trucs assez coton, car cortex est un spécialiste. Il ne fait que les trucs qui sont trop durs pour les autres. Si vous pouvez le faire, ça ne l’intéresse pas. Une fois qu&#8217;il a accepté, il met sur place sa A-team en cherchant des profils de dev qui correspondent exactement au besoin, et il lance la prog en mode commando.</p>
<p>Il loue quelques milliers d&#8217;euros une grande maison, un truc sexy dans lequel on a envie de mettre des filles en bikini ou faire un bbq avec 50 membres de sa famille. Bonne connexion internet required. Il rassemble tout le monde, et ça devient le dortoir de l&#8217;équipe pour 2 jours ou 2 mois, le temps de finir la mission impossible.</p>
<p>Ensuite il livre, il se fait payer l&#8217;équivalent de votre salaire annuel, il le dépense, et il recommence.</p>
<p>Il crée sa start up pour quelques semaines, dans un joli cadre, sur un projet sympa. C&#8217;est cool. C&#8217;est fun. Et c&#8217;est en France. Comme quoi, Hollywood n&#8217;a pas le monopole des hackers branchés.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9739&amp;md5=30561746fe7a93481c0391ef556312c0" 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=9752
title: Un gros Troll de plus sur Javascript
uri: Un-gros-Troll-de-plus-sur-Javascript
url: http://sametmax.com/un-gros-troll-de-plus-sur-javacscript/
content:
<p><a href="http://sametmax.com/un-petit-gout-de-meteor-js-en-python/#comment-21099">Un commentaire très pertinent de Kontre</a> m&#8217;a interpellé dernièrement : si Javascript est si pourri, pourquoi tout le monde s&#8217;y intéresse ?</p>
<blockquote><p>TD;DR :</p>
<p>L&#8217;inertie technique.</p></blockquote>
<p>Il faut bien comprendre que PERSONNE ne s’intéresse à Javascript directement. Les gens s&#8217;intéressent passionnément à la programmation Web. Et il se trouve que, concernant la programmation côté client, il y a QUE Javascript de disponible.</p>
<p>Quand Ajax est arrivé, des mecs brillants ont rendu le Web plus interactif. Et ils ont utilisé ce qui était implémenté partout : Javascript. Pas parce qu&#8217;ils aimaient Javascript. Pas parce que Javascript était un bon langage.</p>
<p>Parce que c&#8217;était la seule solution dispo.</p>
<p>Avant, personne ne s&#8217;intéressait à ce truc. C&#8217;était un langage de script kiddies pour faire des flocons de neige sur les pages HTML. Et donc tout le monde se foutait royalement que ce soit de la merde. IE l&#8217;avait implémenté parce que Netscape l&#8217;avait fait. C&#8217;était alors un gros hybride qui tentait de rassurer les codeurs C et Java. Javascript était marketing, jusque dans le choix du nom. Puis IE6 a gardé le pouvoir pendant 10 ans, et du coup, tout le monde a suivi.</p>
<p>Personne n&#8217;a réfléchi. Personne n&#8217;a vu venir l&#8217;explosion du Web. Personne ne s&#8217;est dit &#8220;les gars faudrait peut être faire attention, le status quo pue la merde&#8221;. <strong>A cette époque, ça n&#8217;avait pas d&#8217;importance, on a mis les efforts de guerre ailleurs.</strong></p>
<p>L&#8217;heure du Web 2.0 a alors sonné, et là les business ont eu besoin de puissance de feu. Mais c&#8217;était trop tard, il n&#8217;y avait plus qu&#8217;un seul truc hideux de dispo pour la prog&#8230;</p>
<p> Google a utilisé massivement les pages dynamiques, et devant le constat des performances misérables de la seule techno qu&#8217;il y avait a dispo, il a pondu chrome, et sa VM Javascript ultra performante. Si on avait appliqué la même techno à n&#8217;importe quelle autre langage, on aurait obtenu 10 fois cette vitesse.</p>
<p> C&#8217;est quand Google a enfin pu donner des perfs décentes &#8211; c&#8217;est à dire celles qu&#8217;ont d&#8217;autres langage depuis une décennie &#8211; à Javascript que les gens ont envisagé de l&#8217;utiliser sur le serveur. Encore une fois, pas parce que Javascript était une techno dont ils étaient fondamentalement amoureux.</p>
<p>Parce qu&#8217;ils voulaient éviter d&#8217;écrire deux fois le même code côté client et côté serveur et que toute tentative de générer du Javascript n&#8217;a pas été satisfaisante. Et aussi parce que le besoin de faire de l&#8217;asynchrone se faisait sentir et que les Dev clients n&#8217;avaient pas envie d&#8217;apprendre un autre langage. Ben oui, l&#8217;asynchrone, vous croyez que pas que ça existe que sur JS quand même ? C&#8217;est aussi vieux que les premiers compilateurs. Les Devs clients connaissaient déjà le JS, et ça faisait du DRY, alors pouet.</p>
<p>Personne. J&#8217;ai bien dit, personne ! Ne s&#8217;est jamais extasié devant l&#8217;incroyable ergonomie de Javascript. Devant sa facilité de debuggage. Devant la qualité de sa doc.</p>
<div id="attachment_9753" class="wp-caption aligncenter" style="width: 373px"><a href="media/6c043fed.6wbwi22.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/03/6wbwi22.jpg"><img src="media/6c043fed.6wbwi22.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/03/6wbwi22.jpg" alt="Dessin humoristique sur la recherche de travail" title="Cherche Dev Javascript pour travailler sur projet innovant dans une start up à fort potentiel de croissance." width="363" height="500" class="size-full wp-image-9753" /></a><p class="wp-caption-text">Cherche Dev Javascript pour travailler sur projet innovant dans une start up à fort potentiel de croissance.</p></div>
<p>Ruby est un langage innovant and fun.</p>
<p>Python est un langage ergonomique and riche.</p>
<p>Php est un langage avec une super doc et une communauté noob friendly.</p>
<p>Lisp est un langage puissant avec un paradigme fonctionnel de référence.</p>
<p>Go est un langage propre avec une gestion de la concurrence très performante.</p>
<p>Javascript est juste là par hasard. Il ne dépasse aucun des langages ci-dessus en terme de ses qualités propres. Sa bibliothèque standard est risible. Il ne sert absolument à rien sans un framework côté serveur, et côté client il est parfaitement improductif sans une lib pour gommer les incompatibilités entre les implémentations.</p>
<p>Les docs sur JS sont éparpillées sur le Web. Les tutos sont déchirés entre tant de versions et de frameworks qu&#8217;on se croirait dans un script des frères wachowski.</p>
<p>Des notions de base comme les closures sont encore obscures pour la plupart des codeurs Javascript, alors qu&#8217;elles peuvent ruiner les perfs de votre programme ou créer des bugs énormes. Les projets innovants en Javascript sont tous faits par des gens hyper compétents parce qu&#8217;innover dans ce langage, ça demande une discipline de dingue tellement il offre d&#8217;opportunité de merder.</p>
<p>Javascript est un hack qu&#8217;on se traine.</p>
<p>C&#8217;est un bug legacy.</p>
<p><strong>C&#8217;est un virus préinstallé dans les navigateurs.</strong></p>
<div id="attachment_9754" class="wp-caption aligncenter" style="width: 410px"><a href="media/b24dd22f.24337352.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/03/24337352.jpg"><img src="media/b24dd22f.24337352.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/03/24337352.jpg" alt="Photo du film le dictateur" title="Ma Fureure, vous ne voulez pas utilisez le C# plutôt ? Naïne, toutes nos troupes sont déjà tatoués sur la fesse gauche, on va devoir y aller comme ça." width="400" height="286" class="size-full wp-image-9754" /></a><p class="wp-caption-text">Ma Fureure, vous ne voulez pas utilisez le C# plutôt ? Naïne, toutes nos troupes sont déjà tatoués sur la fesse gauche, on va devoir y aller comme ça.</p></div>
<p>Oui il y a des produits à base de Javascript fantastiques. Oui les innovations techno Web actuelles intéressantes tournent toutes autour de Javascript de près ou de loin. Et oui, vous devez définitivement mettre les mains dedans parce que le monde du dev avancera en dépit de vos goûts. En tout cas, en dépit des miens, j&#8217;en ai bien conscience.</p>
<p>Mais ceci ne se fait pas grâce à Javascript. Ceci se fait <strong>en dépit</strong> de Javascript. Malgré le fait que c&#8217;est un langage au typage pourri, malgré son scoping dégueulasse, malgré l&#8217;absence des facilités modernes les plus basiques comme le passage d&#8217;arguments avancés ou un slicing décent.</p>
<p>Parce qu&#8217;il y a des gens très (TRÈS) bons qui ont eu Javascript comme contrainte, et qui en ont tiré le meilleur. Et c&#8217;est pas faute d&#8217;avoir essayé autre chose (Flash, GWT, Haxe&#8230;). Ces mecs sont incroyables, ce sont des Dieux vivant, Amen to them, mais Javascript reste à chier.</p>
<p>Et on va se le coltiner encore très, très longtemps.</p>
<p>Au cas où vous ne l&#8217;aurez pas encore compris, je vomis sur Javascript. Mais je code avec, et j&#8217;offre même des formations dessus, car je suis pragmatique. Les besoins de l&#8217;industrie, l&#8217;inertie technologie et le contexte social / technique / économique dictent bien plus souvent les standards que nous utilisons que leurs qualités intrasèques. Sinon nous n&#8217;aurions pas utilisé le format .doc ou les VHS.</p>
<p>En fait, je ne détesterais pas autant Javascript si je n&#8217;en avais pas besoin quotidiennement. Je le hais du plus profond de mon âme justement parce que c&#8217;est non seulement une contrainte inamovible de mon métier, mais en plus une tumeur que les chercheurs annoncent voir grossir de jour en jour. Avec le sourire, les connards !</p>
<p>Le VB est peut être pire que le JS, mais je m&#8217;en branle, je n&#8217;ai pas à y toucher.</p>
<p>Après cet argumentaire, je précise que je ne mettrai pas de tampon sur les commentaires, parce que je comprends bien que je ne peux pas lâcher une caisse et demander à tout le monde de respirer à fond et ne pas se plaindre.</p>
<p>Néanmoins, puisque cet article à des vocations thérapeutique &#8211; vous êtes tous un peu mes psy au fond (la confidentialité bloggeur / lecteur, ça marche ?) &#8211; voici un listing de tout ce que j’abhorre dans le Javascript.</p>
<p><iframe width="560" height="315" src="//www.youtube.com/embed/mD-Jcg5UvUc" frameborder="0" allowfullscreen></iframe>)</p>
<h2>Les experts recommandent d&#8217;éviter la moitié du langage</h2>
<p>Il y a tellement de merdes dans JS que les plus grands experts s&#8217;accordent sur le fait que la première chose à faire est d&#8217;apprendre la liste des choses à ne PAS utiliser.</p>
<p>En fait, Douglas Crockford lui même a écrit <a href="http://shop.oreilly.com/product/9780596517748.do">un bouquin complet</a> rien que sur le sujet.</p>
<p>Je n&#8217;ai pas tout en tête, mais en vrac&#8230;</p>
<p>Ne pas utiliser l&#8217;opérateur <code>==</code>, parce que :</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #3366CC;">''</span>        <span style="color: #339933;">==</span>   <span style="color: #3366CC;">'0'</span>           <span style="color: #006600; font-style: italic;">// false</span>
<span style="color: #CC0000;">0</span>         <span style="color: #339933;">==</span>   <span style="color: #3366CC;">''</span>            <span style="color: #006600; font-style: italic;">// true</span>
<span style="color: #CC0000;">0</span>         <span style="color: #339933;">==</span>   <span style="color: #3366CC;">'0'</span>           <span style="color: #006600; font-style: italic;">// true</span>
<span style="color: #003366; font-weight: bold;">false</span>     <span style="color: #339933;">==</span>   <span style="color: #3366CC;">'false'</span>       <span style="color: #006600; font-style: italic;">// false</span>
<span style="color: #003366; font-weight: bold;">false</span>     <span style="color: #339933;">==</span>   <span style="color: #3366CC;">'0'</span>           <span style="color: #006600; font-style: italic;">// true</span>
<span style="color: #003366; font-weight: bold;">false</span>     <span style="color: #339933;">==</span>   undefined     <span style="color: #006600; font-style: italic;">// false</span>
<span style="color: #003366; font-weight: bold;">false</span>     <span style="color: #339933;">==</span>   <span style="color: #003366; font-weight: bold;">null</span>          <span style="color: #006600; font-style: italic;">// false</span>
<span style="color: #003366; font-weight: bold;">null</span>      <span style="color: #339933;">==</span>   undefined     <span style="color: #006600; font-style: italic;">// true</span>
<span style="color: #3366CC;">&quot; <span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span> <span style="color: #339933;">==</span>   <span style="color: #CC0000;">0</span>             <span style="color: #006600; font-style: italic;">// true</span></pre></div></div>

<p>Notez que même <code>===</code> ne retire pas toutes les ambiguïtés :</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #339933;">&gt;</span> <span style="color: #003366; font-weight: bold;">var</span> a <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> <span style="color: #3366CC;">&quot;abc&quot;</span> <span style="color: #339933;">:</span> <span style="color: #CC0000;">1</span> <span style="color: #009900;">&#125;</span>
<span style="color: #339933;">&gt;</span> a<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;abc&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">===</span> a<span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;abc&quot;</span><span style="color: #009900;">&#93;</span>
<span style="color: #003366; font-weight: bold;">true</span></pre></div></div>

<p>Ne pas utiliser <code>parseInt</code> sans préciser la base sinon :</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #339933;">&gt;</span> parseInt<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'06'</span><span style="color: #009900;">&#41;</span>
<span style="color: #CC0000;">6</span>
<span style="color: #339933;">&gt;</span> parseInt<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'07'</span><span style="color: #009900;">&#41;</span>
<span style="color: #CC0000;">7</span>
<span style="color: #339933;">&gt;</span> parseInt<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'08'</span><span style="color: #009900;">&#41;</span>
<span style="color: #CC0000;">0</span>
<span style="color: #339933;">&gt;</span> parseInt<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'09'</span><span style="color: #009900;">&#41;</span>
<span style="color: #CC0000;">0</span>
<span style="color: #339933;">&gt;</span> parseInt<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'10'</span><span style="color: #009900;">&#41;</span>
<span style="color: #CC0000;">10</span></pre></div></div>

<p>Bien se souvenir d&#8217;utiliser <code>var</code> partout. En fait activer <code>use strict</code> dès que possible pour éviter l&#8217;insertion de <code>;</code> automatiques.</p>
<p>Et ne pas utiliser la syntaxe de déclaration de variable sans <code>var</code>. <del datetime="2014-03-21T09:26:19+00:00">Cependant, faites gaffe quand vous convertissez du code parce que :</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #339933;">&gt;</span> a <span style="color: #339933;">=</span> <span style="color: #CC0000;">1</span>
<span style="color: #CC0000;">1</span>
<span style="color: #339933;">&gt;</span> <span style="color: #003366; font-weight: bold;">var</span> a <span style="color: #339933;">=</span> <span style="color: #CC0000;">1</span>
undefined</pre></div></div>

<p></del> Encore une connerie. Mais vous avez l&#8217;habitude :)</p>
<p>Ah oui, et ne pas utiliser les mots clés <code>new</code> ou <code>with</code> pour vos propres libs. Si, si, on bannit carrément des mots clés, c&#8217;est écrit dans le livre.</p>
<div id="attachment_9755" class="wp-caption aligncenter" style="width: 343px"><a href="media/268a535d.6NJn2xy.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/03/6NJn2xy.jpg"><img src="media/268a535d.6NJn2xy.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/03/6NJn2xy.jpg" alt="Phot d&#039;un gant de vaisselle avec des pansements" title="Ce gant est fantastique, si vous ignorez tous les trous il vous permettra de faire la vaisselle aussi bien que tous les autres gants. Comme ça vous êtes jardinier ? Remarquez, j&#039;avais créé le produit pour faire des touchers rectaux à la base, donc il est adaptable ! " width="333" height="500" class="size-full wp-image-9755" /></a><p class="wp-caption-text">Ce gant est fantastique, si vous ignorez tous les trous il vous permettra de faire la vaisselle aussi bien que tous les autres gants. Comme ça vous êtes jardinier ? Remarquez, j&#039;avais créé le produit pour faire des touchers rectaux à la base, donc il est adaptable ! </p></div>
<h2>Faire du JS propre présuppose l&#8217;utilisation de design patterns</h2>
<p>En l&#8217;état, on ne peut pas écrire du JS propre. Écrire la plus simple instruction Javascript est déjà écrire du code sale car toute variable devient globale. Il faut tout foutre dans un conteneur quelconque, souvent dans une fonction anonyme immédiatement appelée, mais il y a d&#8217;autres techniques (services avec injection de dépendance dans angularjs par exemple). </p>
<p>Pour être honnête, on commence à peine à savoir écrire des grosses applis Javascript propres côté client depuis quelques années. Ca a pris un temps fou de trial / error pour gommer petit à petit tous les aspects guedin de la techno et obtenir un socle utilisable. </p>
<p>Un autre truc : personne ne s&#8217;est mis d&#8217;accord sur l&#8217;utilisation des objets : prototypage, simulation d&#8217;héritage, instanciation ou pas, composition uniquement ? En tout cas vous devez en choisir un, et ne pas le merder.</p>
<p>Au fait, vous avez déjà essayé d&#8217;expliquer le prototypage à quelqu&#8217;un ? Bonne chance !</p>
<h2>Non seulement c&#8217;est du typage faible, mais en plus c&#8217;est du typage con</h2>
<p>J&#8217;ouvre Firefox, je tape:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;</span> <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span> + <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span> // Ceci n<span style="color: #483d8b;">'est effectivement PAS un nombre
NaN
&gt; {} + [] // logique IMPARABLE
0
&gt; [] + {} // fuck la commutativité
&quot;[object Object]&quot;</span></pre></div></div>

<p>Et après on va me dire que c&#8217;est juste l&#8217;API DOM qui est incohérente selon les implémentations. Mais non, tenez, même ça c&#8217;est cohérent. Je fais la même chose sous Node 0.8 (sur lequel j&#8217;ai par ailleurs <a href="http://sametmax.com/non-nodejs-nest-pas-mature/">déjà râlé</a>):</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;</span> <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span> + <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
<span style="color: #483d8b;">'[object Object]'</span></pre></div></div>

<p>On pourrait continuer longtemps avec ces saloperies, mais je finis sur un exemple qui résume bien tout le merdier :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;</span> <span style="color: #483d8b;">'5'</span> + <span style="color: #ff4500;">3</span>
<span style="color: #483d8b;">'53'</span>
<span style="color: #66cc66;">&gt;</span> <span style="color: #483d8b;">'5'</span> - <span style="color: #ff4500;">3</span>
<span style="color: #ff4500;">2</span>
<span style="color: #66cc66;">&gt;</span> <span style="color: #483d8b;">&quot;Vous en étiez à... peau de couilles je crois ?&quot;</span> + <span style="color: #ff4500;">1</span>
<span style="color: #483d8b;">'Vous en étiez à... peau de couilles je crois ?1'</span>
<span style="color: #66cc66;">&gt;</span> <span style="color: #483d8b;">&quot;Vous en étiez à... peau de couilles je crois ?&quot;</span> - <span style="color: #ff4500;">1</span>
NaN</pre></div></div>

<p>Et vous pouvez toujours vous dire que si vous faites attention, vous n&#8217;aurez pas de problème, mais ça a des répercussions sur TOUT le langage, dans les recoins les plus vicieux :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;</span> Math.<span style="color: #008000;">min</span><span style="color: black;">&#40;</span>null, <span style="color: #ff4500;">1234</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">0</span>
<span style="color: #66cc66;">&gt;</span> Math.<span style="color: #008000;">min</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'null'</span>, <span style="color: #ff4500;">1234</span><span style="color: black;">&#41;</span>
NaN
<span style="color: #66cc66;">&gt;</span> Math.<span style="color: #008000;">min</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'1'</span>, <span style="color: #ff4500;">1234</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">1</span></pre></div></div>

<h2>L&#8217;élégance d&#8217;un chameau bourré à la villageoise</h2>
<h3>On se déchaîne</h3>
<p>Ruby :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">coucou = <span style="color:#996600;">&quot;&quot;</span><span style="color:#996600;">&quot;Ceci est une looooooooooooooooooooooooooooooooooooooooongue chaine !
Sur plusieurs lignes !
Et une autre !
Et une autre !
J'adore les sauts de ligne, c'est tellement lisible !!!
&quot;</span><span style="color:#996600;">&quot;&quot;</span>
<span style="color:#CC0066; font-weight:bold;">puts</span> coucou</pre></div></div>

<p>Python :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">coucou = <span style="color: #483d8b;">&quot;&quot;&quot;Ceci est une looooooooooooooooooooooooooooooooooooooooongue chaine !
Sur plusieurs lignes !
Et une autre !
Et une autre !
J'adore les sauts de ligne, c'est tellement lisible !!!
&quot;&quot;&quot;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> coucou</pre></div></div>

<p>Javascript :</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> coucou <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;Ceci est une looooooooooooooooooooooooooooooooooooooooongue chaine !&quot;</span> <span style="color: #339933;">+</span>
<span style="color: #3366CC;">&quot;Sur plusieurs lignes !<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span> <span style="color: #339933;">+</span>
<span style="color: #3366CC;">&quot;Et une autre !<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span> <span style="color: #339933;">+</span>
<span style="color: #3366CC;">&quot;Et une autre !<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span> <span style="color: #339933;">+</span>
<span style="color: #3366CC;">&quot;J'adore les sauts de ligne, c'est tellement lisible !!!<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>
console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span>coucou<span style="color: #009900;">&#41;</span></pre></div></div>

<p>C&#8217;est vrai que manipuler des chaînes, c&#8217;est pas la PUTAIN D&#8217;OPERATION INFORMATIQUE LA PLUS COURANTE DANS LE PUTAIN DE MONDE. PUTAIN.</p>
<h3>Séquence émotion</h3>
<p>Une autre opération qu&#8217;on fait 100 fois par jour : créer des séquences (fichiers, settings, données en base, etc), en récupérer une partie, itérer dessus, les transformer, etc.*</p>
<p>Soit la liste :</p>
<pre>l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]</pre>
<p>Récupérer les carrés des nombres paires de la moité supérieure de la liste ?</p>
<p>Python :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">l = <span style="color: black;">&#91;</span>x<span style="color: #66cc66;">*</span>x <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> l<span style="color: black;">&#91;</span><span style="color: #ff4500;">5</span>:<span style="color: black;">&#93;</span> <span style="color: #ff7700;font-weight:bold;">if</span> x <span style="color: #66cc66;">%</span>2 == <span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span></pre></div></div>

<p>Ruby :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">l = l<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">5</span>..<span style="color:#006666;">10</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#CC0066; font-weight:bold;">select</span><span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>x<span style="color:#006600; font-weight:bold;">|</span> x <span style="color:#006600; font-weight:bold;">%</span> <span style="color:#006666;">2</span> == <span style="color:#006666;">0</span> <span style="color:#006600; font-weight:bold;">&#125;</span>.<span style="color:#9900CC;">collect</span><span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>x<span style="color:#006600; font-weight:bold;">|</span> x <span style="color:#006600; font-weight:bold;">*</span> x<span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>

<p>Javascript (Ma que, gracieux comme oune popotamé):</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> new_list <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span>
l.<span style="color: #660066;">splice</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">5</span><span style="color: #009900;">&#41;</span>
<span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> l.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>l<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span> <span style="color: #339933;">%</span> <span style="color: #CC0000;">2</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        new_list.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>l<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span> <span style="color: #339933;">*</span> l<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
l <span style="color: #339933;">=</span> new_list<span style="color: #339933;">;</span></pre></div></div>

<p>Et encore, je suis cool, je mets un code JS qui utilise <code>l.length</code> directement dans la boucle et pas de variable pour <code>l[i]</code>.</p>
<p><code>Array.map</code> arrive avec JS 1.6 et les arrays comprehensions avec la 1.7, que vous pourrez utiliser sur tous les navigateurs d&#8217;<a href="http://stackoverflow.com/questions/2714694/which-javascript-versions-does-ie8-supports">ici 2056</a>. Ou alors juste sur le serveur, mais si c&#8217;est pour pas avoir le même code sur le client ou le serveur, pourquoi ne pas utiliser un langage qui possède tout ça et bien plus depuis 5 ans ?</p>
<h3>DéLire</h3>
<p>Lire un fichier ligne à ligne ? Une opération vraiment rare et compliquée&#8230;</p>
<p>Python :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">for</span> line <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'</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> line</pre></div></div>

<p>Ruby :</p>

<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">foreach</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'/etc/fstab'</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span><span style="color:#006600; font-weight:bold;">|</span>x<span style="color:#006600; font-weight:bold;">|</span> <span style="color:#CC0066; font-weight:bold;">print</span> x <span style="color:#006600; font-weight:bold;">&#125;</span></pre></div></div>

<p>En JS&#8230; Heu, enfin avec NodeJS:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> fs  <span style="color: #339933;">=</span> require<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;fs&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
fs.<span style="color: #660066;">readFileSync</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'./input.txt'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">split</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'<span style="color: #000099; font-weight: bold;">\n</span>'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">forEach</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span>line<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span>line<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Ah oui, il faut installer un <a href="http://stackoverflow.com/questions/14551608/cant-find-encodings-for-node-js">MODULE SUPPLEMENTAIRE</a> pour gérer tout autre encoding que les variantes d&#8217;unicode.</p>
<h3>PASramètre</h3>
<p>Comment on fait ça en Javascript ?</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> fonction<span style="color: black;">&#40;</span>param, param2=<span style="color: #483d8b;">&quot;valeur&quot;</span>, <span style="color: #66cc66;">**</span>params<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> param, param2, params
&nbsp;
fonction<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, autre_valeur=<span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span></pre></div></div>

<p>On fait pas. Du coup on se retourne vers la bonne vieille technique de &#8220;j&#8217;attends un objet en paramètre et je le fusionne avec un autre objet qui a mes valeurs par défaut&#8221;.</p>
<div id="attachment_9756" class="wp-caption aligncenter" style="width: 410px"><a href="media/0217a80b.Dfy90EX.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/03/Dfy90EX.jpg"><img src="media/0217a80b.Dfy90EX.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/03/Dfy90EX.jpg" alt="Photo d&#039;un homme avec un chapeau giraffe" title="Dev JS qui essaye de comprendre pourquoi le callback anonyme de sa promise n&#039;a pas rebindé correctement son this dans une closure . Oui cette phrase a parfaitement du sens en Javascript." width="400" height="439" class="size-full wp-image-9756" /></a><p class="wp-caption-text">Dev JS qui essaye de comprendre pourquoi le callback anonyme de sa promise n&#039;a pas rebindé correctement son this dans une closure . Oui cette phrase a parfaitement du sens en Javascript.</p></div>
<h2>Javascript ça marche partout !</h2>
<p><del datetime="2014-03-13T22:22:12+00:00">Node ne tourne pas sous Windows, excluant de sa pool d&#8217;apprentissage les 3/4 des foyers de la planète. Parce que je sais pas pour vous, mais moi, quand j&#8217;ai appris la programmation, j&#8217;ai pris le premier ordinateur qui m&#8217;est  tombé sous la main et j&#8217;ai essayé. Parce que je n&#8217;y connaissais rien. Je ne me suis pas soucié de l&#8217;OS.</del></p>
<p><em>On me signale dans la comemntoreillette que j&#8217;ai dis une connerie.</em></p>
<p>Ah oui, et sans node, le Javascript on en fait quoi déjà ?</p>
<h2>Ah mais il faut utiliser coffeescript !</h2>
<p>Oui donc pas Javascript. Point made.</p>
<p>Le langage est tellement à chier qu&#8217;on a inventé un autre langage pour le générer et pas avoir à s&#8217;en soucier. Et ensuite, on a inventé des libs pour automatiquement faire cette compilation pour le dev, et les outils pour le déployer. Et on a inséré dans les navigateurs une nouvelle technologie : le source map, parce que sinon c&#8217;était trop chiant à débugger. Qu&#8217;il faut aussi déployer pendant le dev. Et former les gens dessus.</p>
<p>Vous trouvez ça normal ?</p>
<p>Vous trouvez que c&#8217;est le signe d&#8217;un BON langage ?</p>
<h2>Ouai mais ça fait un seul langage côté server et client</h2>
<p>Oui, c&#8217;est pour ça que les gens s&#8217;y mettent. Encore une fois, ça n&#8217;a rien à voir avec les qualités de Javascript. Ca reste de la merde en boîte, mais de la merde unifiée.</p>
<p>Et encore, car si on a bien le même langage, on est loin d&#8217;avoir le même code. Le code serveur et le code client est, sauf dans les frameworks avancés comme météorjs, très peu partagé au final. Surtout que vous n&#8217;avez PAS la même version du moteur Javascript côté serveur et côté client.</p>
<p>Les libs externes bien conçues marcherons de la même façon par contre, ce qui est un avantage.</p>
<p>Encore une fois, la question n&#8217;est pas &#8220;est-ce que les gens doivent utiliser Javascript ?&#8221; La réponse à cette question est oui. Pas le choix.</p>
<p>Mais on ne l&#8217;utilise pas parce que c&#8217;est un bon langage. On l&#8217;utilise parce que c&#8217;est le status quo. Qui est tout pérave.</p>
<h2>Arrête de baver et donne nous ta solution !</h2>
<p>J&#8217;ai pas de solution parce qu&#8217;il n&#8217;y en a pas. C&#8217;est trop tard. Le Javascript et là et on l&#8217;a dans le cul.  D&#8217;où ma frustration. La 1.7 va dans la bonne direction, mais le temps qu&#8217;elle soit adoptée partout.</p>
<p>Par contre si ce n&#8217;est pas trop demandé, arrêtez de mettre du Javascript partout. Limitez la contamination. Vous n&#8217;avez pas vu &#8220;28 jours plus tard&#8221; ? Il faut isoler le problème avant que la pandémie ne dévore l&#8217;humanité. Il y a des tas d&#8217;alternatives : Python, Ruby, Clojure, Go, Lua&#8230;</p>
<p>Si vous faites un langage de scripting embarqué, si vous faites un outils de déploiement, si vous faites un premier binding pour votre outil&#8230; Ne donnez pas la prio à cette bouse. Quand je vois Gnome ou QT adopter le JS pour leur scripting, ça me met dans une rage folle. C&#8217;est de la connerie pure. Bordel, il y a un site appelé <a href="http://www.99-bottles-of-beer.net/">99 bottles of beer</a> avec des milliers de langages. Vous avez le choix !</p>
<p>C&#8217;est bien beau d&#8217;avoir le même langage partout, mais si c&#8217;est pour se trainer un boulet&#8230; Vous ne travaillerez pas plus vite.</p>
<p>D&#8217;ailleurs, vous n&#8217;aurez jamais le même langage partout. Vous aurez toujours à apprendre et utiliser 2 ou 3 langages. C&#8217;est un fait de la vie. Les humains ne parlent pas tous anglais ou chinois. Et les codeurs ne coderont jamais dans un espéranto, fusse-t-il fantastique.</p>
<p>Je sais, je sais, quand on vient du C, Javascript parait si facile, on se dit que c&#8217;est une amélioration de l&#8217;ergonomie au prix de la performance. Mais non, c&#8217;est comme acheter une 2 chevaux pour aller en ville à la place de son tracteur, alors qu&#8217;on vous avait proposé une smart ou une mini pour le même prix.</p>
<p>Par ailleurs, il y a une vie en dehors de la prog Web vous savez.</p>
<h2>Si il n&#8217;y a pas de solution, ferme ta gueule alors</h2>
<p>C&#8217;est mon blog, je fais ce que je veux. Na.</p>
<div id="attachment_9757" class="wp-caption aligncenter" style="width: 510px"><a href="media/1324c520.aTyyA0D.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/03/aTyyA0D.jpg"><img src="media/1324c520.aTyyA0D.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/03/aTyyA0D.jpg" alt="Photo d&#039;un homme ayant son aspirateur coincé dans un ascenseur" title="Sam, passant directement du stade de la colère à la dépression dans son dueil de la programmation Web" width="500" height="610" class="size-full wp-image-9757" /></a><p class="wp-caption-text">Sam, passant directement du stade de la colère à la dépression dans son dueil de la programmation Web</p></div>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9752&amp;md5=c94de486c1ca5837e7e8ff08ce6bc1d1" 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=9771
title: 10 trucs que je déteste en Python
uri: 10-trucs-que-je-déteste-en-Python
url: http://sametmax.com/10-trucs-que-je-deteste-en-python/
content:
<p>Il faut savoir être honnête dans la vie, et puisque j&#8217;ai tapé sur le JS dans le dernier article, on va rappeler que rien n&#8217;est parfait et que chez les Pythoneux aussi y a du boulot.</p>
<h2>Le piège des paramètres par défaut mutables</h2>
<p>C&#8217;est le &#8220;ne pas faire&#8221; le plus connu en Python. Mais même en étant au courant on se fait TOUS baiser un jour.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> transfert<span style="color: black;">&#40;</span>source, res=<span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>:
	<span style="color: #808080; font-style: italic;"># faire un truc qui passe des élement de</span>
	<span style="color: #808080; font-style: italic;"># source à res</span></pre></div></div>

<p>Ce code va remplir <code>res</code> d&#8217;appels en appels, qui ne sera donc plus une liste vide dès le second appel.</p>
<p>It&#8217;s a feature, not a bug, mais c&#8217;est pourtant rarement ce qu&#8217;on veut.</p>
<h2>L&#8217;opérateur pour les tuples est la virgule, pas les parenthèses</h2>
<p>C&#8217;est pratique car ça permet de rendre l&#8217;unpacking propre et élégant. Mais c&#8217;est aussi un coup à se tirer une balle dans le pied :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> t = <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;a&quot;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># ceci n'est pas un tuple !</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>t<span style="color: black;">&#41;</span>
<span style="color: #008000;">str</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> t = <span style="color: #483d8b;">&quot;a&quot;</span>, <span style="color: #808080; font-style: italic;"># grrrr</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>t<span style="color: black;">&#41;</span> 
<span style="color: #008000;">tuple</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> t = <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>t<span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># WAIT WAT ?</span>
<span style="color: #008000;">tuple</span></pre></div></div>

<p>Et comme les string sont itérables, la boucle <code>for</code> marchera toujours, silencieusement, jusqu&#8217;à ce que bug s&#8217;en suive.</p>
<h2>Pas de set literal vide</h2>
<p>On peut faire <code>set()</code>, on peut faire <code>{1}</code>, on peut faire <code>()</code> mais on ne peut pas faire <code>{}</code> puisque c&#8217;est un dico, ni <code>{,}</code> puisque c&#8217;est une syntax error. Ces deux lettres à taper en plus pèsent sur ma conscience.</p>
<h2>Le packaging</h2>
<p>Packager un programme Python est une grosse galère. Créer un setup.py est facile, mais savoir comment le créer, c&#8217;est une autre histoire. En fait le seul tuto valable sur la question est <a href="http://sametmax.com/creer-un-setup-py-et-mettre-sa-bibliotheque-python-en-ligne-sur-pypi/">celui de ce blog</a>, et il commence à être vieux. Vous savez pourquoi ? J&#8217;ai pas la foi de le mettre à jour car ça veut dire de nouveau passer des heures à me renseigner sur ce qu&#8217;il faut faire maintenant.</p>
<p>En fait un exe ou un deb devrait se faire en une ligne de commande.</p>
<h2>Les modules inutiles de stdlib</h2>
<p>Vous saviez qu&#8217;il y a un module pour lire les fichiers WAV dans la stdlib ? Sérieusement, qu&#8217;est-ce que ça fout dans la lib standard ?</p>
<h2>La convention de langage, pas respectée dans la stdlib</h2>
<p>Même après le nettoyage de Python 3, des libs existent qui utilisent le camelcase pour les noms de méthodes comme par exemple <a href="http://docs.python.org/2/library/unittest.html?highlight=unittest#unittest">unittest</a>. Le code de ces libs lui-même n&#8217;est pas PEP8, ce qui craint dès qu&#8217;on veut voir comment c&#8217;est fait à l&#8217;intérieur.</p>
<h2>La concaténation automatique fonctionne à côté de l&#8217;opérateur virgules</h2>
<p>J&#8217;adore le fait que :</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;1&quot;</span>
<span style="color: #483d8b;">&quot;2&quot;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Se concatène automatiquement.</p>
<p>Mais ça devrait lever une syntax error quand c&#8217;est déclaré à côté de virgules pour éviter cette merde :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">var = <span style="color: black;">&#40;</span>
<span style="color: #483d8b;">&quot;1&quot;</span>,
<span style="color: #483d8b;">&quot;2&quot;</span>
<span style="color: #483d8b;">&quot;3&quot;</span>
<span style="color: black;">&#41;</span></pre></div></div>

<p>Combien de fois je me suis fait niquer avec ça dans <code>settings.py</code>&#8230;</p>
<h2>On n&#8217;a pas accès au bloc de code dans un with</h2>
<p>Il y a des tas de context managers géniaux qu&#8217;on pourrait faire si on avait accès au bloc de code exposée dans la close <code>with</code> comme on pourrait le faire avec lisp. Cette limitation m&#8217;a frustré plus d&#8217;une fois.</p>
<h2>Pas de plug de code à chaud</h2>
<p>Je rêve de cette feature.</p>
<h2>Ecrire du code parallèle, concurrent ou non bloquant est lourd</h2>
<p>Syntaxiquement c&#8217;est pas top, surtout qu&#8217;on doit contourner souvent le GIL. Une grosse amélioration pour l&#8217;io async arrive avec la 3.4 mais elle sera surtout bas niveau.</p>
<h2>Y a pas de point 10</h2>
<p>Ce langage est fantastique.</p>
<h2>Ce qui n&#8217;est PAS un problème à mes yeux</h2>
<h3>Le passage à Python 3</h3>
<p>A mon sens, brillament exécuté. Je sais que les gens pensent que ça prend un temps fou et que ça a foutu la merde, etc. Mais en vérité, c&#8217;est un des rares langages qui ait géré la transition aussi bien : largement documentée, outillée et suivie, bien soutenue par la communauté, avec tout le temps qu&#8217;il faut pour la transition mais une direction ferme de la part du BDFL. En plus il est POSSIBLE d&#8217;écrire du code qui fonctionne dans les deux versions alors qu&#8217;elles sont supposément incompatibles. C&#8217;est assez fou quand on y pense.</p>
<p>Il y a d&#8217;autres langages qui n&#8217;ont jamais réussi ce genre de changements, comme PERL (qui en est mort) ou PHP (qui a avorté).</p>
<h3>Les espaces significatifs</h3>
<p>Best. Feature. Ever.</p>
<h3>Les lambdas sur une ligne</h3>
<p>Ne pas toujours pouvoir faire des <a href="http://sametmax.com/fonctions-anonymes-en-python-ou-lambda/">fonctions anonymes</a> pour les callback, c&#8217;est un peu moins élégants, mais sinon, ça ne me manque pas.</p>
<h3>L&#8217;encoding</h3>
<p>Les gens râlent sur la gestion de l&#8217;encoding Python parce qu&#8217;ils ne comprennent pas ce qu&#8217;ils font. Mais personnellement je trouve excellent que le langage te force à gérer CORRECTEMENT tes encodings ou te lève une erreur. J&#8217;ai vu tellement de bases de données corrompues, de scripts qui affichent des hiéroglyphes, des &#8220;?&#8221; plein les pages Web, que je me dis que trop de personnes ignorent juste complètement la question. Et le jour où ça merde, ils passent un mois à réparer.</p>
<p>En 2.7, cette gestion était assez verbeuse par contre, et je suis bien content que ça change en 3.4.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9771&amp;md5=f220f364671e29cd491944ece0925b88" 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=9783
title: Un coup de langue sur l’Oculus Rift
uri: Un-coup-de-langue-sur-l-Oculus-Rift
url: http://sametmax.com/un-coup-de-langue-sur-loculus-rift/
content:
<p>Complètement par hasard, j&#8217;ai pu passer quelques minutes avec un <a href="https://en.wikipedia.org/wiki/Oculus_Rift">Oculus Rift</a>.</p>
<p>Le casque est léger et pas inconfortable, et isole très bien du reste du monde, allant dans le sens de l&#8217;objectif d&#8217;immersion du produit. L&#8217;image n&#8217;est pas en haute résolution, et comme l&#8217;écran est très proche des yeux, on voit les pixels assez grossièrement, surtout en comparaison des écrans HD des dispositifs mobiles actuels. L&#8217;image est également un peu saccadée.</p>
<p>Il faut dire que j&#8217;étais sur un prototype destiné aux dev.</p>
<p>Mais si on met de côté ces problèmes qui sont naturels sur un dispositif en cours d&#8217;élaboration, le résultat est très prometteur. Malgré une vision loin des 180° (on est plus proche du casque de paintball), l&#8217;angle est asez confortable et on ne se sent pas trop bridé. Tourner la tête fait changer l&#8217;angle de vision de manière naturelle et fluide, et l&#8217;expérience est particulièrement bluffante quand on se retourne pour regarder derrière soit.</p>
<p>Le plus fun, c&#8217;est la sensation de vitesse. Une accélération avec pour seul repère les lunettes donne vraiment ce sentiment grisant qu&#8217;on a IRL.</p>
<p>Qui dit nouvelle techo dit nouvel apprentissage. Le corps perd en effet complètement ses repères. D&#8217;une part, on ne voit pas ses propres membres bouger. D&#8217;autre part, on voit un mouvement que l&#8217;oreille interne ne subit pas, et je paries sur des bonnes nausées pour les gens sensibles au mal des transports.</p>
<p>Désolé, je n&#8217;ai pas d&#8217;image de la scène. Comme je le disais, ça s&#8217;est fait vraiment à l&#8217;arrache, donc j&#8217;avais rien sur moi pour immortaliser le moment.</p>
<p>Dans tous les cas, mes fantasmes d&#8217;utilisation du dispositif comme station de travail portable ont été tués dans l&#8217;oeuf. On ne peut clairement pas dev avec ça pour le moment.</p>
<p>Par contre, pour un FPS ou un survival horror, ça peut donner un truc fantastique.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9783&amp;md5=65926db2c4ba2cef303c3ed4e5c35ee8" 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=9790
title: Ca y est, on peut coder en Python 3
uri: Ca-y-est-on-peut-coder-en-Python-3
url: http://sametmax.com/ca-y-est-on-peut-coder-en-python-3/
content:
<p><a href="https://www.python.org/download/releases/3.4.0/">Python 3.4 vient de sortir</a>, et avec cette release, je peux enfin recommander aux gens de se mettre à Python 3 plutôt que Python 2. Tout simplement parce que maintenant, en plus d&#8217;avoir énormément de <a href="http://python3wos.appspot.com/">libs qui ont migré</a>, on a l&#8217;expérience de la bestiole. C&#8217;est stable, les perfs sont bonnes, la conversion de code d&#8217;une version à l&#8217;autre est bien documentée et maitrisée.</p>
<p><strong>Et surtout, la 3.3 et la 3.4 viennent avec tout un tas des goodies super green.</strong></p>
<p>Voici tout ce dont vous pouvez profiter avec Python 3 que vous ne pouvez pas faire avec Python 2.</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="420" height="315" src="//www.youtube.com/embed/ILObfEzX92k" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<h2>Des classes classes</h2>
<p>Les classes sont des new type classes en Python 3. Pas besoin d&#8217;hériter d&#8217;<code>object</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># Au revoir !</span>
<span style="color: #ff7700;font-weight:bold;">class</span> TouteMoche<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>
&nbsp;
<span style="color: #808080; font-style: italic;"># Bonjour !</span>
<span style="color: #ff7700;font-weight:bold;">class</span> PropreEtNette:
    <span style="color: #ff7700;font-weight:bold;">pass</span></pre></div></div>

<p>Les metaclasses ne se définissent plus comme un attribut spécial :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># Au revoir !</span>
<span style="color: #ff7700;font-weight:bold;">class</span> TouteMoche<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    <span style="color: #0000cd;">__metaclass__</span> = UnTruc
&nbsp;
<span style="color: #808080; font-style: italic;"># Bonjour !</span>
<span style="color: #ff7700;font-weight:bold;">class</span> PropreEtNette<span style="color: black;">&#40;</span>metaclass=Untruc<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">pass</span></pre></div></div>

<h2>Super Super()</h2>
<p>Franchement, qui se souvient de la syntaxe pour appeler proprement la méthode parente d&#8217;une classe ?</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># Au revoir !</span>
<span style="color: #ff7700;font-weight:bold;">class</span> FranchementHein<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><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">super</span><span style="color: black;">&#40;</span>FranchementHein, <span style="color: #008000;">self</span><span style="color: black;">&#41;</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Bonjour !</span>
<span style="color: #ff7700;font-weight:bold;">class</span> FranchementHein:
&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: black;">&#41;</span>:
        <span style="color: #008000;">super</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<h2>Meta meta programmation</h2>
<p>Le module <a href="http://docs.python.org/3/library/inspect.html?highlight=signature#inspect.signature">inspect</a> permet maintenant de récupérer des infos très très précises sur la signature des fonctions :</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;">inspect</span> <span style="color: #ff7700;font-weight:bold;">import</span> signature
    <span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">def</span> foo<span style="color: black;">&#40;</span>a, <span style="color: #66cc66;">*</span>, b:<span style="color: #008000;">int</span>, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>:
    ...     <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
    <span style="color: #66cc66;">&gt;&gt;&gt;</span> sig = signature<span style="color: black;">&#40;</span>foo<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>sig<span style="color: black;">&#41;</span>
    <span style="color: #483d8b;">'(a, *, b:int, **kwargs)'</span>
&nbsp;
    <span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>sig.<span style="color: black;">parameters</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'b'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    <span style="color: #483d8b;">'b:int'</span>
&nbsp;
    <span style="color: #66cc66;">&gt;&gt;&gt;</span> sig.<span style="color: black;">parameters</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'b'</span><span style="color: black;">&#93;</span>.<span style="color: black;">annotation</span>
    <span style="color: #66cc66;">&lt;</span>class <span style="color: #483d8b;">'int'</span><span style="color: #66cc66;">&gt;</span></pre></div></div>

<p>Et comme vous pouvez le voir, les <a href="http://sametmax.com/les-annotations-en-python-3/">annotations</a> sont de la partie.</p>
<p>Les classes ont également un nouvel attribut <a href="http://www.python.org/dev/peps/pep-3155/#proposal">__qualname__</a>, qui, comme on peut s&#8217;y attendre, est le qualified name de la classe :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">class</span> C:
...   <span style="color: #ff7700;font-weight:bold;">def</span> f<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>: <span style="color: #ff7700;font-weight:bold;">pass</span>
...   <span style="color: #ff7700;font-weight:bold;">class</span> D:
...     <span style="color: #ff7700;font-weight:bold;">def</span> g<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>: <span style="color: #ff7700;font-weight:bold;">pass</span>
...
<span style="color: #66cc66;">&gt;&gt;&gt;</span> C.__qualname__
<span style="color: #483d8b;">'C'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> C.<span style="color: black;">f</span>.__qualname__
<span style="color: #483d8b;">'C.f'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> C.<span style="color: black;">D</span>.__qualname__
<span style="color: #483d8b;">'C.D'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> C.<span style="color: black;">D</span>.<span style="color: black;">g</span>.__qualname__
<span style="color: #483d8b;">'C.D.g'</span></pre></div></div>

<p>Ca marche aussi pour les fonctions.</p>
<p>Enfin pour les gars qui sont vraiment tordus, on a une nouvelle méthode pour les metaclasses, <a href="http://www.python.org/dev/peps/pep-0447/">__locallookup__</a>, qui permet d&#8217;influencer le <a href="http://python-history.blogspot.fr/2010/06/method-resolution-order.html">MRO</a> à la volée.</p>
<h2>Un yield qui yield</h2>
<p>Bon, mon titre ne veut rien dire, c&#8217;était pour la continuité.</p>
<p><code>yield</code> a maintenant un petit frère, <code>yield from</code>, qui permet de déléguer l&#8217;itération à un itérable sous jacent :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> generateur<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #483d8b;">&quot;123&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span>, <span style="color: #ff4500;">7</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;7&quot;</span>, <span style="color: #483d8b;">&quot;8&quot;</span>, <span style="color: #483d8b;">&quot;9&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> generateur<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">## 1</span>
<span style="color: #808080; font-style: italic;">## 2</span>
<span style="color: #808080; font-style: italic;">## 3</span>
<span style="color: #808080; font-style: italic;">## 4</span>
<span style="color: #808080; font-style: italic;">## 5</span>
<span style="color: #808080; font-style: italic;">## 6</span>
<span style="color: #808080; font-style: italic;">## 7</span>
<span style="color: #808080; font-style: italic;">## 8</span>
<span style="color: #808080; font-style: italic;">## 9</span></pre></div></div>

<p>Là ce n&#8217;est pas très utile, mais sur des générateurs complexes, c&#8217;est sympa. Surtout que <code>yield from</code> passe aussi les valeur avec <code>send()</code>, fait remonter les exceptions proprement et est détecté par les events loops du module asyncio, dont on parlera plus tard.</p>
<h2>Batteries included, with charger</h2>
<p><a href="http://sametmax.com/votre-python-aime-les-pip/">Pip</a> et <a href="http://sametmax.com/les-environnement-virtuels-python-virtualenv-et-virtualenvwrapper/">virtualenv</a> sont livrés avec la 3.4 ! Rien de plus à faire, rien à installer ! Enfin !</p>
<p>Malheureusement pas virtualenv wrapper, mais c&#8217;est déjà pas mal.</p>
<p>Un nouveau format, le <a href="http://pythonwheels.com/">wheel</a>, permet de faire des paquets binaires qui n&#8217;auront pas besoin d&#8217;être compilés sur la machine cible. Ca veut dire bientôt du numpy / scipy sans avoir à compiler quoi que ce soit. C&#8217;est un remplacement du <em>egg</em> plus simple et sans les problèmes de compatibilités. Il ne vise pas la distribution de projets Python standalones, comme le <em>egg</em> qui a notamment eu le problème de vouloir tout faire en même temps.</p>
<p>Pour ce dernier, le <a href="http://www.python.org/dev/peps/pep-0441/">pyz</a> est en discussion.</p>
<p>Enfin les scripts Python supportent maintenant <a href="http://www.python.org/dev/peps/pep-0397/">l&#8217;équivalent du shebang, mais sous Windows</a>. Ceci vient avec l&#8217;introduction de la commande <code>py</code> qui permet de lancer toutes les commandes Python (<code>pip</code>, <code>venv</code>, etc.) pour une version de Python installée spécifique.</p>
<p>Ah, non, pas &#8220;enfin&#8221;, j&#8217;ai oublié un truc :</p>
<p><code>python -X faulthandler votre_script.py</code> vous permet maintenant d&#8217;obtenir une stacktrace sur les scripts utilisant <code>ctypes</code> \o/. Et le module <a href="http://docs.python.org/3.4/library/tracemalloc.html">tracemalloc</a> permet d&#8217;enquêter sur l&#8217;allocation mémoire.</p>
<h2>Tout un tas de trucs que les codeurs Java vont adorer</h2>
<p>Il y a des <a href="http://docs.python.org/3.4/library/enum.html">Enums</a>, et ça vient sous toutes les formes :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> enum <span style="color: #ff7700;font-weight:bold;">import</span> Enum, IntEnum
&nbsp;
<span style="color: #808080; font-style: italic;"># La version de feignasse :</span>
Animal = Enum<span style="color: black;">&#40;</span><span style="color: #483d8b;">'ant bee cat dog'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># La version 'anal retentive'</span>
<span style="color: #ff7700;font-weight:bold;">class</span> Animal<span style="color: black;">&#40;</span>IntEnum<span style="color: black;">&#41;</span>:
     ant = <span style="color: #ff4500;">1</span>
     bee = <span style="color: #ff4500;">2</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># et tout ce qu'il faut entre les deux pour les centristes</span></pre></div></div>

<p>Pour les nostalgiques de l&#8217;overloading, on peut maintenant spécifier que le code d&#8217;une fonction est différent selon le type des arguments qui lui sont passés :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> functools <span style="color: #ff7700;font-weight:bold;">import</span> singledispatch
&nbsp;
@singledispatch
<span style="color: #ff7700;font-weight:bold;">def</span> fun<span style="color: black;">&#40;</span>arg<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Comportement par défaut, teddy'</span><span style="color: black;">&#41;</span>
&nbsp;
@fun.<span style="color: black;">register</span><span style="color: black;">&#40;</span><span style="color: #008000;">int</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> _<span style="color: black;">&#40;</span>arg<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Tu m'as passé un int, jonhy !&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Cacatoes:
    <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
@fun.<span style="color: black;">register</span><span style="color: black;">&#40;</span>Cacatoes<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> _<span style="color: black;">&#40;</span>arg<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Tu m'as passé un Cacatoes, billy !&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
fun<span style="color: black;">&#40;</span><span style="color: #483d8b;">'Do'</span><span style="color: black;">&#41;</span>
fun<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
fun<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
fun<span style="color: black;">&#40;</span>Cacatoes<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">## Comportement par défaut, teddy</span>
<span style="color: #808080; font-style: italic;">## Comportement par défaut, teddy</span>
<span style="color: #808080; font-style: italic;">## Tu m'as passé un int, jonhy !</span>
<span style="color: #808080; font-style: italic;">## Tu m'as passé un Cacatoes, billy !</span></pre></div></div>

<p>Et puis le module <a href="http://docs.python.org/2/library/abc.html?highlight=abc#abc">abc</a> pour faire des classes abstraites, même si ça a été backporté en Python 2.7, donc un peu hors sujet.</p>
<h2>Les built-in ont un peu changé</h2>
<p>Pour le texte, c&#8217;est de l&#8217;unicode partout, avec utf8 par défaut pour les conversions. Ca veut dire plus de <code>u</code> devant les chaînes de caractère, plus de déclaration de l&#8217;encoding en haut des fichiers de code. Moins de <code>decode</code> / <code>encode</code>.</p>
<p>Mais ça veut dire aussi que <code>open</code> a besoin obligatoirement d&#8217;un paramètre <code>encoding</code>, dont la valeur par défaut est bien entendu <code>utf8</code>.</p>
<p>Attention cependant, le built-in <code>bytes</code> n&#8217;est pas l&#8217;exacte équivalent du type <code>str</code> en Python 2 puisqu&#8217;il ne possède plus certaines méthodes de manipulation de texte comme <code>replace</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: #483d8b;">&quot;Trololo&quot;</span>.<span style="color: black;">replace</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'o'</span>, <span style="color: #483d8b;">'a'</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'Tralala'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> b<span style="color: #483d8b;">&quot;Trololo&quot;</span>.<span style="color: black;">replace</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'o'</span>, <span style="color: #483d8b;">'a'</span><span style="color: black;">&#41;</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&lt;ipython-input-5-f7e93d6f629e&gt;&quot;</span>, line <span style="color: #ff4500;">1</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #66cc66;">&lt;</span>module<span style="color: #66cc66;">&gt;</span>
    b<span style="color: #483d8b;">&quot;Trololo&quot;</span>.<span style="color: black;">replace</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'o'</span>, <span style="color: #483d8b;">'a'</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">TypeError</span>: expected an <span style="color: #008000;">object</span> <span style="color: #ff7700;font-weight:bold;">with</span> the buffer interface</pre></div></div>

<p>C&#8217;est un peu chiant quand on manipule des protocoles binaires, et les mecs de mercurial ont un peu gueulé. Donc il est possible que ça change. J&#8217;ai mis beaucoup de fois le mot &#8220;peu&#8221; dans cet article, ce qui est stylistiquement très laid. Mais je suis trop paresseux pour éditer cet article qui fait maintenant 3 km.</p>
<p>Pour les nombres, on n&#8217;a plus à se soucier du type <code>long</code>, qui n&#8217;existe plus. <code>/</code> est maintenant la division ordinaire et <code>//</code> la division entière.</p>
<p>Pour les fonctions built-in, pas mal de changements avec bien entendu, <code>print()</code> qui devient une fonction, mais aussi toute ce qui est <code>zip</code>, <code>map</code>, etc, qui retournent des générateurs au lieu de listes, tout comme <code>dict.items</code> et consorts. Ah oui, et <code>import</code> est maintenant absolu par défaut.</p>
<h2>Quelques libs en plus</h2>
<p>Marre du module <code>os</code> ? <a href="http://docs.python.org/3.4/library/pathlib.html?highlight=pathlib#module-pathlib">pathlib</code> permet de donner un petit goût d'objet à vos manipulations de FS, comme <a href="https://github.com/jaraco/path.py">path.py</a>. Ca reste moins bien, mais c'est mieux que rien.</p>
<p>Raz-le bol de recoder la fonction moyenne, médiane, etc ? Le module <a href="http://docs.python.org/3.4/library/statistics.html?highlight=statistics#module-statistics">statistics</a> a été ajouté pour ça.</p>
<p>Enfin, le fameux module <a href="http://docs.python.org/3/library/unittest.mock.html#module-unittest.mock">mock</a>, qui permet de simuler tout un tas de trucs sans tout casser :</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> mock <span style="color: #ff7700;font-weight:bold;">import</span> patch
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">with</span> patch.<span style="color: #008000;">object</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>, <span style="color: #483d8b;">'listdir'</span>, return_value=<span style="color: black;">&#91;</span><span style="color: #483d8b;">'file2.txt'</span>, <span style="color: #483d8b;">'file2.text'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">listdir</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/etc/'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
...
<span style="color: black;">&#91;</span>u<span style="color: #483d8b;">'file2.txt'</span>, u<span style="color: #483d8b;">'file2.text'</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">listdir</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/etc/'</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span>:<span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span>
<span style="color: black;">&#91;</span>u<span style="color: #483d8b;">'environment'</span>, u<span style="color: #483d8b;">'hosts.allow'</span><span style="color: black;">&#93;</span></pre></div></div>

<h2>Tout est bien rangé</h2>
<p>Les fichiers bytecode Python sont maintenant tous groupés dans un dossier appelé <em>__pycache__</em>. Finis les <em>.pyc</em> qui trainent partout. Et en plus prefixés de l'architecture avec laquelle ils ont été générés. Toujours utile.</p>
<p>En prime pas mal de noms ont été normalisés : tous les modules sont maintenant en minuscule, tous les modules liés à IO sont groupés dans le module <code>io</code>, <code>urllib</code> 1 et 2 ont été mergés, et l'arborescence des exceptions pour les erreurs d'IO a maintenant beaucoup plus de sens :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># Au revoir !</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">errno</span> <span style="color: #ff7700;font-weight:bold;">import</span> ENOENT, EACCES, EPERM
&nbsp;
<span style="color: #ff7700;font-weight:bold;">try</span>:
    <span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;document.txt&quot;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> f:
        content = f.<span style="color: black;">read</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: #008000;">IOError</span> <span style="color: #ff7700;font-weight:bold;">as</span> err:
    <span style="color: #ff7700;font-weight:bold;">if</span> err.<span style="color: #dc143c;">errno</span> == ENOENT:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;document.txt file is missing&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">elif</span> err.<span style="color: #dc143c;">errno</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#40;</span>EACCES, EPERM<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;You are not allowed to read document.txt&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #ff7700;font-weight:bold;">raise</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Bonjour !</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">try</span>:
    <span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;document.txt&quot;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> f:
        content = f.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">except</span> FileNotFoundError:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;document.txt file is missing&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">except</span> PermissionError:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;You are not allowed to read document.txt&quot;</span><span style="color: black;">&#41;</span></pre></div></div>

<h2>Asyncio, la prog asynchrone rebootée</h2>
<p>Une des raisons pour laquelle je tape sur javascript aussi fort, c'est aussi la jalousie. Ils ont tous les derniers joujoux asynchrones hi-tech, meh !</p>
<p>Avec Python on était obligé d'installer tornado ou twisted pour ça, et c'était un peu dommage :)</p>
<p>Avec la 3.4, la prog asynchrone fait peau neauve (adieu l'horrible module <a href="http://docs.python.org/2/library/asyncore.html">asyncore</a>) et propose de la prog asynchrone plus simple, plus légère, plus facilement intégrable : <a href="http://legacy.python.org/dev/peps/pep-3156/">asyncio</a>.</p>
<p>Si vous lisez ce PEP, ça ne va pas vous parler, alors je vais potasser tout ça et faire un petit article.</p>
<p>Mon seul regret avec asyncio, c'est que c'est un module uniquement bas niveau, alors que tulip, le prototype de la lib, contenait des mobiles haut niveau comme par exemple <a href="https://code.google.com/p/tulip/source/browse/tests/http_client_test.py?r=593a96f529b800fb0a67098c0f3bd7ce197c2205">un client http bien foutu</a>. Du coup ça a donné <a href="http://sametmax.com/en-attendant-asyncio/#comment-19108">ce genre de discussion</a> sur le blog, avec des gens qui ne comprenaient pas que je m'attendais à un peu de haut niveau et eux qui ne voyaient que le bas, et donc s'attardaient sur de la sémentique d'implémentation de la prog non blocante.</p>
<h2>En conclusion</h2>
<p>Le code Python 3 est plus court, plus cohérent, avec moins de surprises, moins de dépendances externes et plus de flexibilité. Des comportements par défaut sains un peu partout, des outils en plus, et comme d'habitude vous n'en utiliserez pas la moitié tellement il y a à faire.</p>
<p>Python 3.4 est vraiment un très bon cru, honnêtement, avec toutes ces améliorations, le langage parvient à se maintenir au niveau des petits jeunes et de leur hype, sans sacrifier sa solidité et sa cohérence.</p>
<p>C'est pour ça qu'on a attendu 5 ans. C'est pour ça que la migration a été lente et prudente.</p>
<p>Parce que la communauté Python fait vraiment les choses bien.</p>
<p>Les exemples du blogs seront donc à partir de maintenant en Python 3.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9790&amp;md5=0e9fafbab3ed2dc4ef8fb49f7f2bf4c6" 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>


