# articles

feed_id: http://sametmax.com/?p=5909
title: Mettre Ubuntu en veille en appuyant sur le bouton ‘power’
uri: Mettre-Ubuntu-en-veille-en-appuyant-sur-le-bouton-power
url: http://sametmax.com/mettre-ubuntu-en-veille-en-appuyant-sur-le-bouton-power/
content:
<p>J&#8217;ai horreur que mon ordi se mette en veille quand je rabat le capot. C&#8217;est un ultra portable, donc je le balade partout. Du coup, je régle dans les options que la fermeture déclenche juste le verrouillage de l&#8217;écran : un geste et mon laptop est à l&#8217;abrit des blagues des petits malins dans les hackerspaces pendant la pose pipi.</p>
<p>Mais j&#8217;aime pouvoir le mettre en veille rapidement, en appuyant juste sur le bouton power, et il n&#8217;y a plus de paramètres pour le régler dans les settings d&#8217;Ubuntu.</p>
<p>La solution et cette petite ligne de commande :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">gsettings <span style="color: #008000;">set</span> org.<span style="color: black;">gnome</span>.<span style="color: black;">settings</span>-daemon.<span style="color: black;">plugins</span>.<span style="color: black;">power</span> button-power <span style="color: #483d8b;">'suspend'</span></pre></div></div>

<p>Les valeurs possibles sont :</p>
<ul>
<li><strong>&#8216;blank&#8217;</strong> : aucune valeur.</li>
<li><strong>&#8216;suspend&#8217;</strong> : mettre en veille.</li>
<li><strong>&#8216;shutdown&#8217;</strong> : éteindre.</li>
<li><strong>&#8216;hibernate&#8217;</strong> : hiberner.</li>
<li><strong>&#8216;interactive&#8217;</strong> : afficher une fenêtre qui demande quoi faire.</li>
<li><strong>&#8216;nothing&#8217;</strong> : ne rien faire.</li>
</ul>
<p>On peut aussi <a href=" http://askubuntu.com/questions/66723/how-do-i-modify-the-power-options">le faire en graphique</a> pour ceux qui n&#8217;aiment pas le terminal.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5909&amp;md5=790888b26cbe44bd429ed8a938f220ba" 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=5927
title: Liste des plugins sublime text que j’utilise
uri: Liste-des-plugins-sublime-text-que-j-utilise
url: http://sametmax.com/liste-des-plugins-sublime-text-que-jutilise/
content:
<p>Ils sont tous installable via <a href="http://wbond.net/sublime_packages/package_control">Package Control</a>.</p>
<h2>Les paquets de syntaxe supplémentaires</h2>
<p>D&#8217;abord, j&#8217;ai ajouté le support de syntaxe et de snippets pour des fichiers / langages qui ne sont pas pris en compte par défaut.</p>
<ul>
<li><strong>ApacheConf</strong>: coloration des fichiers de config apache.</li>
<li><strong>CoffeeScript</strong>: coloration pour le langage coffeescript.</li>
<li><strong>jQuery</strong>: coloration pour la lib jQuery.</li>
<li><strong>jQuery Snippets pack</strong>: snippets pour jQuery.</li>
<li><strong>HTML5</strong>: coloration et snippets pour HTML5.</li>
<li><strong>LESS</strong>: coloration pour lesscss.</li>
<li><strong>Djaneiro</strong>: coloration et snippet pour django, y compris les templates.</li>
<li><strong>nginx</strong>: coloration pour les fichiers de confi nginx.</li>
<li><strong>INI</strong>: coloration pour les fichiers INI.</li>
</ul>
<p>Et en prime le pack de langue &#8216;Language &#8211; French&#8217;, pour corriger mon orthographe française.</p>
<p>En plus de ça, il y a&#8230;</p>
<h2><a href="http://wbond.net/sublime_packages/alignment">Alignment</a></h2>
<p>Permet de réaligner des lignes avec <kbd>Ctrl</kbd> + <kbd>Alt</kbd> + <kbd>A</kbd>.</p>
<p><a href="media/ccd4c4fb.align.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/align.gif"><img src="media/ccd4c4fb.align.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/align.gif" alt="" title="" width="700" height="400" class="aligncenter size-full wp-image-5929" /></a></p>
<h2><a href="https://github.com/Monnoroch/ColorHighlighter">Color Highlighter</a></h2>
<p>Pour éviter de se demander à quelle couleur correspond ce code hexa dans le css.</p>
<p><a href="media/b453c03f.hilight-color.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/hilight-color.gif"><img src="media/b453c03f.hilight-color.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/hilight-color.gif" alt=""  width="700" height="400" class="aligncenter size-full wp-image-5931" /></a></p>
<h2><a href="http://weslly.github.io/ColorPicker/">ColorPicker</a></h2>
<p>Changez les valeurs des couleurs en CSS depuis un picker graphique.</p>
<p><a href="media/0ba6e9b0.color-picker.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/color-picker.gif"><img src="media/0ba6e9b0.color-picker.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/color-picker.gif" alt="" title="" width="700" height="400" class="aligncenter size-full wp-image-5932" /></a></p>
<p>Le gif rend mal, en vrai la roue de couleurs est parfaite.</p>
<h2><a href="https://github.com/colinta/SublimeDuplicateSelections">DuplicateSelections</a></h2>
<p>S&#8217;interface directement sur le copier / coller. Si vous copiez plusieurs sélections et que vous collez vers plusieurs curseurs de même nombre, cela insère chaque sélection respectivement dans chaque curseur, au lieu d&#8217;insérer un vrac de toutes les sélections en même temps dans chacun des curseurs.</p>
<p><a href="media/27064e5a.duplicate-selection.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/duplicate-selection.gif"><img src="media/27064e5a.duplicate-selection.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/duplicate-selection.gif" alt="" title="" width="700" height="400" class="aligncenter size-full wp-image-5933" /></a></p>
<h2><a href="https://github.com/Stuk/sublime-edit-history">Edit History</a></h2>
<p>Tellement utile que c&#8217;est intégré dans ST3 d&#8217;origine : cela permet de faire back et forward comme sur un navigateur Web. Chaque fois qu&#8217;on édite une ligne, ça rajoute une entrée dans l&#8217;historique, et on peut y revenir plus tard. Fantastique pour naviguer dans les gros fichiers</p>
<p><a href="media/4c7e1d14.history.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/history.gif"><img src="media/4c7e1d14.history.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/history.gif" alt="" title="" width="700" height="410" class="aligncenter size-full wp-image-5934" /></a></p>
<h2><a href="https://github.com/kek/sublime-expand-selection-to-quotes">Expand Selection to Quotes</a></h2>
<p>Je sais pas pour vous mais moi, sélectionner une chaîne à la main, ça me fait chieerrrrrrrrrrr. Cette sélection permet, avec une seconde combinaison de touches, de sélectionner les quotes.</p>
<p><a href="media/8bdc7d24.expend-selection.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/expend-selection.gif"><img src="media/8bdc7d24.expend-selection.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/expend-selection.gif" alt="" title="" width="700" height="410" class="aligncenter size-full wp-image-5935" /></a></p>
<h2><a href="https://github.com/freewizard/SublimeFormatSQL">Format SQL</a></h2>
<p>Je l&#8217;utilise pas souvent, mais je suis feinéant.<br />
<a href="media/30fdca16.format-sql.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/format-sql.gif"><img src="media/30fdca16.format-sql.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/format-sql.gif" alt="" title="" width="700" height="410" class="aligncenter size-full wp-image-5936" /></a></p>
<h2><a href="https://github.com/jisaacks/GitGutter">GitGutter</a></h2>
<p>Une nouvelle addition, un truc qui rassure. Ça affiche le diff des modifications faites au fichier par rapport à la dernière copie dans Git.<br />
<a href="media/0b2aaab3.gitgutter.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/gitgutter.gif"><img src="media/0b2aaab3.gitgutter.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/gitgutter.gif" alt="" title="" width="700" height="410" class="aligncenter size-full wp-image-5937" /></a></p>
<h2><a href="https://github.com/rmaksim/Sublime-Text-2-Inc-Dec-Value">IncDecValue</a></h2>
<p>Ajouter quelques points à une valeur ? Pas besoin de sélectionner la bonne partie et tout réécrire.</p>
<p><a href="media/28136357.inc.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/inc.gif"><img src="media/28136357.inc.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/inc.gif" alt="" title="" width="700" height="410" class="aligncenter size-full wp-image-5938" /></a></p>
<h2><a href="https://github.com/viyano/sublime-oddly">Oddly</a></h2>
<p>Sélectionner une ligne sur deux ou sur 3.</p>
<p><a href="media/32674a41.odly.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/odly.gif"><img src="media/32674a41.odly.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/odly.gif" alt="" title="" width="700" height="410" class="aligncenter size-full wp-image-5939" /></a></p>
<h2><a href="">SublimeLinter</a></h2>
<p>Entour d&#8217;une bordure blanche les erreurs en Python (et JS) telles que imports inutilisés, variables non déclarées et syntaxe errors.</p>
<p><a href="media/53a80150.linter.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/linter.gif"><img src="media/53a80150.linter.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/linter.gif" alt="" title="" width="700" height="410" class="aligncenter size-full wp-image-5940" /></a></p>
<h2><a href="https://github.com/allixsenos/SublimeMRU">SublimeMRU</a></h2>
<p>Annuler la fermeture d&#8217;un fichier fermé, comme un tab sur le navigateur Web.</p>
<h2><a href="https://github.com/alexnj/SublimeOnSaveBuild">SublimeOnSaveBuild</a></h2>
<p>Lance la commande build configurée pour ce fichier au moment où on save.</p>
<h2><a href="https://github.com/spadgos/sublime-ToggleQuotes">ToggleQuotes</a></h2>
<p>Transformer &#8216;&#8221;&#8216; en &#8220;&#8216;&#8221; et inversement.</p>
<p><a href="media/6230f6b3.toggle-quote.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/toggle-quote.gif"><img src="media/6230f6b3.toggle-quote.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/toggle-quote.gif" alt="" title="" width="700" height="410" class="aligncenter size-full wp-image-5941" /></a></p>
<h2><a href="https://github.com/ehuss/Sublime-Wrap-Plus">Wrap Plus</a></h2>
<p>Je ne sais pas comment j&#8217;ai vécu avant ce plugin. Wrap les comments, les string (incluant les docstrings) pour se limiter à n caractères. Automatiquement. C&#8217;est beau.</p>
<p><a href="media/5852e938.wraps_plus.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/wraps_plus.gif"><img src="media/5852e938.wraps_plus.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/wraps_plus.gif" alt="" title="" width="700" height="410" class="aligncenter size-full wp-image-5943" /></a></p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5927&amp;md5=3ae95a3981508852ae1a52a6d9580188" 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=5945
title: Savoir si une page est en cache avec Varnish
uri: Savoir-si-une-page-est-en-cache-avec-Varnish
url: http://sametmax.com/savoir-si-une-page-est-en-cache-avec-varnish/
content:
<p>Pour savoir si cette feignasse de Varnish a bien fait son boulot voici une petite astuce pour afficher dans les HEADERS de son navigateur la provenance de la page, le cache ou le backend.<br />
Varnish propose dans son <a href="https://www.varnish-cache.org/trac/wiki/VCLExampleHitMissHeader">wiki</a> cette méthode.</p>
<p><strong><br />
dans le fichier de conf de Varnish:</strong></p>

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

<p><b>et rajoutez ces quelques lignes:</b></p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">sub vcl_deliver <span style="color: #7a0874; font-weight: bold;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>obj.hits <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000;">0</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
                <span style="color: #000000; font-weight: bold;">set</span> resp.http.X-Cache = <span style="color: #ff0000;">&quot;HIT&quot;</span>;
        <span style="color: #7a0874; font-weight: bold;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
                <span style="color: #000000; font-weight: bold;">set</span> resp.http.X-Cache = <span style="color: #ff0000;">&quot;MISS&quot;</span>;
        <span style="color: #7a0874; font-weight: bold;">&#125;</span>
<span style="color: #7a0874; font-weight: bold;">&#125;</span></pre></div></div>

<p><b>On redemarre le service pour prendre en compte les changements:</b></p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">service varnishd restart</pre></div></div>

<p><b>Dans le navigateur:</b></p>
<p><img src="media/64a2cd9e.varnish.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/04/varnish.png" alt="" title="ça devrait cristalliser..." width="300" height="329" class="aligncenter size-full wp-image-5949" /></p>
<p>Comme on le voit ici, la page a été servie par le backend, si ce n&#8217;était pas prévu il va falloir revoir vos règles.</p>
<p>ATTENTION: Pensez à bien rafraichir votre navigateur pour être sur que ce ne soit pas la page mise en cache par ce dernier qui soit affichée, personnellement j&#8217;utilise la version navigation privé de chrome.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5945&amp;md5=be6785e27a7adbf7068ee14abcc3ccb5" 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=5960
title: J’avais dis que je répondrais à tous les mails…
uri: J-avais-dis-que-je-répondrais-à-tous-les-mails
url: http://sametmax.com/javais-dis-que-je-repondrais-a-tous-les-mails/
content:
<p>Bon, vous connaissez le principe, un mec me pose une question dans un mail, je répond et je m’aperçois que j&#8217;ai un DELIVERY FAILURE.</p>
<p>En l’occurrence, si j&#8217;avais lu le mail avant de cliquer, j&#8217;aurais eu l&#8217;air moins con : pouete@&#8230;. </p>
<blockquote><p>
un tuto sur &#8220;Parser du HTML/XML&#8221;</p>
<p>Ca m&#8217;amuse d&#8217;écrire des petits scripts qui récupèrent les vidéos des<br />
replays télés, pour plein de raisons (7 ou 15 jours c&#8217;est court, j&#8217;aime<br />
bien ne pas dépendre de la qualité du site distant, ni de ma connexion<br />
pour regarder ensuite&#8230;). Chacun ses perversions </p>
<p>Le système est le toujours le même. Sur la page de replay, il y a un<br />
identifiant de vidéo, que l&#8217;on passe à un site (WAT pour<br />
TF1/TMC/NT1/HD1, Brightcove pour BFMTV,<br />
http://prod-kernnrj12v5.integra.fr/videoinfo pour cherie25 et nrj12,<br />
Akamai pour France TV/Pluzz/TV5 Monde&#8230;), qui nous renvoie la vraie<br />
adresse de la vidéo. Il y a souvent un peu de XML à parser, avec<br />
plusieurs lignes parmi lesquelles on choisira la meilleure qualité vidéo<br />
(HD, SD, BD, Ipad, Iphone), le bitrate le plus élevé.</p>
<p>Donc on parse du HTML et du XML pour un petit script de rien.
</p></blockquote>
<p>Hello bilou,</p>
<p>Il y a des choses que je n&#8217;ai pas compris dans le mail, et j&#8217;aurais voulu te poser moult questions : &#8220;est-ce que tu propose un tuto suite à cette expérience ou tu en demande un ?&#8221;  mais l&#8217;adresse de réponse est &#8220;pouete&#8221;.</p>
<p>Met un addresse Yopmail ou spamgourmet la prochaine fois, ça permettra de te répondre.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5960&amp;md5=7efe63ac1c80b65a642ffb9523383666" 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=5969
title: Paramètres par défaut pour la commande py.test
uri: Paramètres-par-défaut-pour-la-commande-py-test
url: http://sametmax.com/parametres-par-defaut-pour-la-commande-py-test/
content:
<p>Je ne fais plus de tests unittaires sans <a href="http://sametmax.com/se-simplifier-les-tests-python-avec-pytest/">pytest</a>, et je me retrouve souvent à rentrer les mêmes paramètres de la commande encore et encore. Parfois, quand j&#8217;utilise des wrappers tels que django-pytest et pytest-django (ça s&#8217;invente pas), je ne peux même pas passer d&#8217;arguments directement à <code>py.test</code>.</p>
<p>On peut y remédier en créant un fichier de config à la racine du projet. Nommez le fichier <em>tox.ini</em>, car c&#8217;est aussi le nom du fichier de configuration de l&#8217;outil de tests <a href="http://testrun.org/tox/latest//">tox</a>, et il est compatible, donc autant avoir un seul format. Dedans, créez une section pytest, et vous pouvez configurer la lib la dedans.</p>
<p>En l’occurrence, le settings &#8220;addopts&#8221;, pour &#8220;add options&#8221; (ajouter options), permet de spécifier les options de la ligne de commande à toujours ajouter à <code>py.test</code>.</p>
<p>Mon fichier contient toujours au moins ceci :</p>

<div class="wp_syntax"><div class="code"><pre class="json" style="font-family:monospace;">[pytest]
addopts = --ignore=&quot;virtualenv&quot; --capture=no</pre></div></div>

<p>Ainsi <code>py.test</code> ignore toujours le dossier <em>virtualenv</em> (qui est un lien vers l&#8217;env virtuel de mon projet) car je ne veux pas qu&#8217;il lance les tests de ce dossier. Et il ne capture pas stdout, ce qui me permet d&#8217;utiliser <a href="http://sametmax.com/debugger-en-python-les-bases-de-pdb/">ipdb</a> pendant les tests unittaires. Parfois j&#8217;utilise aussi <code>--maxfail=1</code> quand je veux qu&#8217;il s&#8217;arrête dès la première erreur rencontrée.</p>
<p>Pour ne pas aller dans ce dossier et ne pas capturer stdout.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5969&amp;md5=a6fe4d17d33ee89c21be724c6325f4d8" 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=5955
title: Alors, on passe à Ubuntu 13.04 ?
uri: Alors-on-passe-à-Ubuntu-13-04
url: http://sametmax.com/alors-on-passe-a-ubuntu-13-04/
content:
<p>J&#8217;ai utilisé Ubuntu 13.04 depuis quelques jours. C&#8217;est un bon cru : l&#8217;interface est fluide (n&#8217;oubliez pas d&#8217;installer <a href="http://sebsauvage.net/logiciels/ubuntu_power.html">preload</a>) et quelques ajouts ergonomiques sympas ont fait leur apparition.</p>
<p>Mais globalement, je reste en 12.04 car :</p>
<ul>
<li>Il n&#8217;y a rien de si fantastique dans raring qui justifie une migration.</li>
<li>Il y a des programmes qui ne marchent plus (Qwit ou les plugins nautilus par exemple).</li>
<li>La 12.04 est très stable, c&#8217;est une LTS et elle sera supportée bien plus longtemps.</li>
</ul>
<p>Si vous devez installer une nouvelle version, installez la 13.04. Sinon, ne faites pas l&#8217;update, ça ne vaut pas le coup.</p>
<p>P.S: Ubuntu 13.04 vient avec Python 2.7 par défaut, et pas Python 3. C&#8217;est la 2eme fois qu&#8217;ils reportent. <a href="http://sametmax.com/dois-je-apprendre-python-2-ou-python-3/">Qu&#8217;est-ce que je vous disais, déjà ?</a></p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5955&amp;md5=80a3db29927b1b405d03192d532cc6e8" 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=5811
title: Appeler du code C depuis Python avec ctypes
uri: Appeler-du-code-C-depuis-Python-avec-ctypes
url: http://sametmax.com/appeler-du-code-c-depuis-python-avec-ctypes/
content:
<p>On vous a dit et répété que Python c&#8217;était un super langage de glu et que ça pouvait très facilement s&#8217;interfacer avec les binaires produits par du C. Mais jusqu&#8217;à quel point ?</p>
<p>En vérité c&#8217;est extrêmement simple : Python permet de se mapper directement sur un .dll ou un .so, et d&#8217;appeler n&#8217;importe quelle fonction qu&#8217;il contient depuis le code Python comme si c&#8217;était une fonction normale. Il n&#8217;y a rien à installer, c&#8217;est fourni d&#8217;office.</p>
<p>On peut tester ça facilement. Je ponds une lib d&#8217;une folle puissance grâce à mes talents de codeurs C internationalement connus dans le quartier :</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#include&lt;stdio.h&gt;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/*
Attend un pointeur sur un array de caractères (une chaîne en C) 
et l'affiche.
*/</span>
dit_papa<span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">*</span> p<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> p<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;">/*
Attend deux entiers et les multiple
*/</span>
multiplier<span style="color: #009900;">&#40;</span><span style="color: #993333;">long</span> a<span style="color: #339933;">,</span> <span style="color: #993333;">long</span> b<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> a <span style="color: #339933;">*</span> b<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/*
Attend un pointeur de pointeur sur un array de char
parce qu'on aime les risques.
*/</span>
jakadi<span style="color: #009900;">&#40;</span><span style="color: #993333;">char</span> <span style="color: #339933;">**</span> p<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span> <span style="color: #339933;">*</span>p<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>On compile tout ça. Comme je suis sous Nunux, j&#8217;utilise GCC et j&#8217;obtiens un .so, mais sous Windows c&#8217;est pareil avec VisualStudio et les .dll.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">gcc</span> <span style="color: #660033;">-shared</span> -Wl,-soname,ZeLib <span style="color: #660033;">-o</span> ZeLib.so <span style="color: #660033;">-fPIC</span> ZeLib.c</pre></div></div>

<p>ZeLib.so est prête et frétille d&#8217;impatience à l&#8217;idée de vous servir. Il ne reste plus qu&#8217;à lancer le shell Python&#8230;</p>
<p>D&#8217;abord on fait ses imports, c&#8217;est dans la lib standard tout ç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: #ff7700;font-weight:bold;">import</span> ctypes</pre></div></div>

<p>Ensuite on se bind sur le binaire, il faut préciser un chemin absolu sinon ça ne marche pas :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> zelib = ctypes.<span style="color: black;">CDLL</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;/home/sam/Work/projet/ZeLib.so&quot;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Et derrière on peut appeler une fonction (Python fait la <a href="http://docs.python.org/2/library/ctypes.html?highlight=ctypes#fundamental-data-types">conversion entre tous les types</a> de bases Python et C) :</p>

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

<p>Si on veut faire des chaînes, on ne peut pas passer de l&#8217;unicode. Comme mon shell a toutes les chaînes en unicode par défaut, je dois <a href="http://sametmax.com/lencoding-en-python-une-bonne-fois-pour-toute/">encoder</a> dans le charset de sortie (sur mon système, c&#8217;est UTF8):</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> zelib.<span style="color: black;">dit_papa</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;papa&quot;</span>.<span style="color: black;">encode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'utf8'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
papa
<span style="color: #ff4500;">5</span></pre></div></div>

<p>Notez au passage que la fonction retourne quelque chose même si je n&#8217;ai pas précisé de valeur de retour. Du coup j&#8217;aurais mieux fait de mettre un bon <code>return 0 </code>à la fin.</p>
<p>Si on veut appeler une fonction qui attend un pointeur, il faut d&#8217;abord caster son type en un type C, puis appeler <code>by_ref</code> dessus, qui va passer l&#8217;argument par référence, plutôt que par valeur :</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> ctypes <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> s = ctypes.<span style="color: black;">c_char_p</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'kiwi'</span>.<span style="color: black;">encode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'utf8'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> zelib.<span style="color: black;">jakadi</span><span style="color: black;">&#40;</span>byref<span style="color: black;">&#40;</span>s<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
kiwi
<span style="color: #ff4500;">5</span></pre></div></div>

<p>Voilà.</p>
<p>Voilà, voilà.</p>
<p>Bon attention quand même, le C n&#8217;est pas aussi conciliant que le Python : le debug est plus dur (pas de stacktrace, mais un bon vieux core dump), pas de completion dans ipython, et on peut même planter la VM si on se débrouille bien :-) </p>
<p>P.S: je ne vais pas mettre le code C à télécharger et le code Python, franchement, il est pas énorme. Donc petite exception dans cet article : y a rien à DL et la syntaxe est pas à base de comments.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5811&amp;md5=bf1653034ac1855f6140bbaef27708c1" 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=557
title: Redshift / F.lux pour éviter de s’exploser le yeux devant l’ordi
uri: Redshift-F-lux-pour-éviter-de-s-exploser-le-yeux-devant-l-ordi
url: http://sametmax.com/redshift-f-lux-pour-eviter-de-sexploser-le-yeux-devant-lordi/
content:
<p>Si vous passez comme moi 34 heures par jour devant votre ordi au bout d&#8217;un moment vos yeux vont piquer un peu. Et là soit on arrête et on se repose soit on continue et on chiale.</p>
<p>Sur Ubuntu j&#8217;avais <a href="http://www.omgubuntu.co.uk/2010/05/alleviate-tired-eyes-in-ubuntu-with-redshift">redshift</a> et depuis que je suis sous Mac j&#8217;utilise f.lux que vous pouvez <a href="http://stereopsis.com/flux/">télécharger ici</a>.</p>
<p>Ce petit logiciel va épargner vos yeux en ajustant la luminosité et la couleur de votre écran en fonction de l&#8217;heure de la journée.</p>
<p>Au début c&#8217;est asser désagrable je dois avouer car on a l&#8217;impression que l&#8217;écran vire sur un sale jaune orangé mais on s&#8217;y habitue au bout de quelques semaines. </p>
<p>Personnelement je le désactive de temps en temps la journéelorsque je bosse du design mais le réactive quand le soir arrive car c&#8217;est là où non seulement nos yeux ont passés des heures devant l&#8217;ordi mais ou l&#8217;ambiance de l&#8217;appartement diminue en luminosité laissant l&#8217;écran flashé 2.2 GigoWatts de lumière dans les yeux.</p>
<p><img src="media/5757d846.flux-shot.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/05/flux-shot.png" alt="" title="flux et ses réglages minimalistes" width="395" height="200" class="aligncenter size-full wp-image-6015" /></p>
<p>F.lux se lancera avec votre ordi, une icone dans la barre des tâches permettra de le désactiver au besoin.</p>
<p>Vos yeux vous diront merci.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=557&amp;md5=87c1c67e9cfd0ad30ef2e511efcfe0f3" 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=6025
title: Le génie des titres des films pornos
uri: Le-génie-des-titres-de-films-pornos
url: http://sametmax.com/le-genie-des-titres-de-films-pornos/
content:
<p>Je trouve qu&#8217;on ne rend pas assez hommage <a href="http://sametmax.com/le-travail-decriture-dans-le-domaine-du-cul/">au travail énorme</a> fait par les mecs qui ont 10000 euros de budgets et une caméra pour tourner un boulard. Prenez le marketting par exemple : vous imaginez le challenge pour vendre un nanard cheap sur un marché saturé par des produits similaires ?</p>
<p>Mais ils y arrivent. Ils trouvent des astuces. À l&#8217;époque des héros du porno, tout commençait par un titre bien choisi.</p>
<p>D&#8217;abord, il y a les titres dits &#8220;expressifs&#8221;. Ils véhiculent une idée forte au travers d&#8217;une tag line inégalée ou d&#8217;un jeu de mot à faire rebiquer un carambar. Le poids des mots, le choc des&#8230; heu&#8230; Le choc en tout cas.</p>
<ul>
<li>Change de trou, ça fume</li>
<li>Des pétasses au pays des tapas</li>
<li>Enlève ta langue que je pête</li>
<li>Je vous reçois 5 sur 5 mais uniquement chez moi.</li>
<li>L&#8217;Allemagne fait des râles</li>
<li>Le nain l&#8217;avait grosse</li>
<li>Le plus dur est derrière toi</li>
<li>Ma banane au Canada</li>
<li>Ma kososovare sur le trottoir</li>
<li>Ma queue, Donald</li>
<li>Mature et Découverte</li>
<li>Mi-putes, mi-soumises</li>
<li>Oh oui, prends moi pendant la ligue des champions</li>
<li>Par où t&#8217;es rentré je t&#8217;ai pas vu sortir ?</li>
<li>Prise mâle cherche fiche femelle</li>
<li>Qui est l&#8217;as à seins ?</li>
<li>Retourne la chaise, on sera mieux assis.</li>
<li>Rien ne sert de courir, il faut partir à poil.</li>
<li>Écarte tes cuisses, je trouve plus ma montre !</li>
<li>Écarte tes roseaux que je pêche au large !</li>
</ul>
<p>Et puis il y a les traditionnelles parodies de films. Il faudrait faire un quizz pour voir qui est capable de retrouver tous les originaux.</p>
<ul>
<li>20 000 vieux sous mémère</li>
<li>Alice au pays des merguez !</li>
<li>Aline Baba et les 40 gauleurs</li>
<li>Analgeddon</li>
<li>Anus Beauté &#8211; Sodom Institut</li>
<li>AsterX &#038; ObelX se font Cléopâtre</li>
<li>Attache-moi si tu peux !</li>
<li>Autant en emporte le gland</li>
<li>Banane mécanique</li>
<li>Bienvenue Chez Les Chtites Coquines</li>
<li>Blanche fesse et les 7 mains</li>
<li>Chérie, j&#8217;ai agrandi les godes</li>
<li>Clithanger</li>
<li>Coup de foutre à Notting Hill</li>
<li>Da Vinci Gode</li>
<li>Défloration finale</li>
<li>Encule Poirot</li>
<li>Elle boit pas, elle fume pas, mais qu&#8217;est-ce qu&#8217;elle suce !</li>
<li>Fuck Club</li>
<li>Full Metal Quéquette</li>
<li>Germianal</li>
<li>Glandiator</li>
<li>Glands of New-York</li>
<li>Harry Ploteur et la braguette magique</li>
<li>Harry Ploteur à la croupe en feu</li>
<li>Il faut sauter la sœur de Ryan</li>
<li>In Diana Jones</li>
<li>Ingrid bite en cours</li>
<li>Iznogod</li>
<li>Jamais sans ma bite</li>
<li>Juranal Park</li>
<li>Kiki roux et la léchante sorcière</li>
<li>Kill Bite</li>
<li>L&#8217;aine ou la cuisse ?</li>
<li>L&#8217;appel de la fourrée</li>
<li>L&#8217;arrière-train sifflera trois fois</li>
<li>L&#8217;étroit mousquetaire</li>
<li>La communauté de l&#8217;anus</li>
<li>La dernière pine droite</li>
<li>La dernière tante à fion du Christ</li>
<li>La famille bite en feu</li>
<li>La flûte emmanchée</li>
<li>La grande dérouille</li>
<li>La grande touffe</li>
<li>La quéquette du Graal</li>
<li>La ruée vers Laure</li>
<li>Le ciel, les oiseaux et ta femme</li>
<li>Le fabuleux vagin d&#8217;Amélie Bourrin</li>
<li>Le gland bleu</li>
<li>Le petit capuchon rouge</li>
<li>Le père Noël est super dur !</li>
<li>Le seigneur de l&#8217;anus</li>
<li>Les 4 fentes astiquent</li>
<li>Les aventuriers du derche poilus</li>
<li>Les douze couilles de mes nuits</li>
<li>Les Fables de la femme fontaine</li>
<li>Pinez-les, haut et court</li>
<li>Position: Impossible</li>
<li>Princesse Monokini</li>
<li>Pulp Friction</li>
<li>Quai des burnes</li>
<li>Qui veut la bite de Roger Rapeau ?</li>
<li>Rasta kékette</li>
<li>Rencontre du troisième fist</li>
<li>Robin des doigts</li>
<li>Robinson suce Zoé</li>
<li>Robocock</li>
<li>Rocco l&#8217;empereur mégalo</li>
<li>Rodéo sur Juliette</li>
<li>Scarefesse</li>
<li>Total rectal</li>
<li>Tous sur ma mère</li>
<li>Un morpion nommé Wanda</li>
<li>Viol au dessus d’un nid de cocus</li>
<li>Viscères au poing</li>
<li>Ça glisse au pays de merveille</li>
</ul>
<p>Ils sont mêmes capables de pondre des suites &#8220;cohérentes&#8221;.</p>
<ul>
<li>2001, l&#8217;odyssée des seins</li>
<li>2002, l&#8217;odyssée de la queue</li>
<li>2004, l&#8217;odyssée à 4 pattes</li>
<li>2006, l&#8217;odyssée de la saucisse</li>
<li>2007, l&#8217;odyssée de la levrette</li>
<li>2008, l&#8217;odyssée du coït</li>
<li>2009, l&#8217;odyssée de la meuf</li>
<li>2010, l&#8217;odyssée du pénis</li>
<li>2012, l&#8217;odyssée de la partouze</li>
<li>2013, l&#8217;odyssée de la baise</li>
<li>2020, l&#8217;odyssée du vagin</li>
</ul>
<p>Clairement, mon calendrier n&#8217;est pas assez rock&#8217;n roll. Je vais tout de suite le changer. Surtout qu&#8217;on est en 2013.</p>
<p>Enfin, il y a les séries. J&#8217;adorerais regarder cette version de la croisière s&#8217;amuse. Ou encore mieux, la montrer à mamie, qui était fan de la version originale (avant d&#8217;être dévorée par le virus de la plusbellelavite).</p>
<ul>
<li>Alerte à Malaucul</li>
<li>Code Rectum</li>
<li>Docteur Gouine, femme putain</li>
<li>Hélène et les cochons</li>
<li>Insphincter Gadjet</li>
<li>Josépine, ange catin</li>
<li>La croisière s&#8217;enfile</li>
<li>Ma sorcière bien baisée</li>
<li>Premiers baisés</li>
<li>Rustine Powers</li>
<li>Sailor foune</li>
</ul>
<p>Et après on va dire que ces mecs sont pas créatifs.</p>
<p>Les tubes ont tué tout ça ma p&#8217;tite dame. C&#8217;est la faute au capitalisme, à Internet et François Hollande. Avant, y avait une vrai démarche artistique, des poils, des papiers peints aussi laids que la musique d&#8217;ambiance&#8230; Du vrai, de la bonne.</p>
<p>P.S: une simple recherche sur Google peut vous en donner beaucoup plus, mais j&#8217;ai préféré afficher les plus percutants uniquement. On fait de la recherche de fond nous monsieurs, on extrait le diamant de son écrin de carbone avant de le livrer au client. On a l&#8217;amour du travail bien fait.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6025&amp;md5=b8127ef17be64dbc101ab3e0d1441ef6" 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=5965
title: Ajouter une route au urls.py de Django durant les tests
uri: Ajouter-une-route-au-urls-py-de-Django-durant-les-tests
url: http://sametmax.com/ajouter-une-route-au-urls-py-de-django-durant-les-tests/
content:
<p>Créer des routes dans l&#8217;urlconf juste pour les tests unitaires n&#8217;est pas très propre, heureusement on peut utiliser des urls de test complètement séparées.</p>
<p>D&#8217;abord, il faut mettre un fichier <em>urls.py</em> dans votre dossier <em>tests</em> qui contient vos routes de tests. Ensuite&#8230;</p>
<p>Si vous utilisez le mécanisme de Django pour les tests, il suffit de déclarer le chemin de ce module comme attribut <code>urls</code> de votre classe de test, et Django se charge du reste :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> VotreTestCase<span style="color: black;">&#40;</span>TestCase<span style="color: black;">&#41;</span>:
    urls = <span style="color: #483d8b;">'votreapp.tests.urls'</span></pre></div></div>

<p>Dans le cas où, comme moi, vous préférez utiliser <a href="http://sametmax.com/se-simplifier-les-tests-python-avec-pytest/">une autre lib</a> pour écrire vos tests, vous pouvez quand choisir votre module d&#8217;urls en faisant :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">conf</span> <span style="color: #ff7700;font-weight:bold;">import</span> settings
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">core</span>.<span style="color: black;">urlresolvers</span> <span style="color: #ff7700;font-weight:bold;">import</span> clear_url_caches
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> urls
&nbsp;
settings.<span style="color: black;">ROOT_URLCONF</span> = urls
<span style="color: #808080; font-style: italic;"># n'oubliez pas cette ligne, sinon vous autre des comportements aberrant</span>
<span style="color: #808080; font-style: italic;"># car django met les urls en cache</span>
clear_url_caches<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5965&amp;md5=a99445b6954686cc63707726dba48ea9" 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=6028
title: Comment le Revenu de Base Inconditionnel pourrait maximiser le bonheur.
uri: Comment-le-Revenu-de-Base-Inconditionnel-pourrait-maximiser-le-bonheur
url: http://sametmax.com/comment-le-revenu-de-base-inconditionnel-pourrait-maximiser-le-bonheur/
content:
<blockquote><p>
Ceci est un post invité de <a href="http://sametmax.com/author/recher/">Recher</a> posté sous licence <a href="http://creativecommons.org/licenses/by/3.0/">creative common 3.0 unported</a>.</p>
<p>Recher est un des premiers lecteurs (et soutient) du blog, donc nous avons choisi de le laisser exprimer des idées qui lui sont chères. Notez que ce n&#8217;est PAS la marque d&#8217;un changement de ligne éditoriale du blog et que ce n&#8217;est PAS l&#8217;annonce de plus d&#8217;articles sur des thèmes politiques sur Sam et Max.</p>
<p>Ceci dit, un de temps en temps ne fait pas de mal. Ne vous battez pas trop en comments :-)
</p></blockquote>
<h2>Quelques faits amusants concernant les humains</h2>
<h3>La viande, c&#8217;est la force</h3>
<p>Lorsque les hommes préhistoriques tuaient une grosse bestiole, ils ne pouvaient ni manger toute la viande d&#8217;un coup, ni la conserver. La meilleure solution qu&#8217;ils ont trouvé a été de donner cette viande à d&#8217;autres hommes préhistoriques, qui se sentaient alors redevable, et qui partageraient la viande de leurs chasses futures.</p>
<p>Le placement bancaire de l&#8217;homme préhistorique, c&#8217;était l&#8217;estomac des autres. </p>
<p>D&#8217;ailleurs, selon de nombreux scientifiques, ce qui a fait que l&#8217;homo sapiens soit devenu ce que nous sommes aujourd’hui, c’est que pour survivre, ils s’échangeaient leur savoir. Sans cela, on aurait certainement très vite disparu. Comparé aux autres espèces, l&#8217;homo sapiens est une pauvre lopette qui n&#8217;a rien pour lui.</p>
<p><a href="http://web.archive.org/web/20060627055742/http://culturelibre.net/article.php3?id_article=247">Source approximative (webarchivée, et qui elle-même ne cite pas ses sources)</a></p>
<p><a href="media/cd999904.geico_caveman.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/05/geico_caveman.jpg"><img src="media/cd999904.geico_caveman.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/05/geico_caveman.jpg" alt="Le cours du tigre à dents de sabre a chuté de 3 points. Groumf !" title="Le cours du tigre à dents de sabre a chuté de 3 points. Groumf !" width="250" height="125" class="alignnone size-full wp-image-6038" /></a></p>
<h3>Une expérience un peu glauque du 13ème siècle</h3>
<p>Frédéric 2, Suprême Tôlier du Saint-Empire romain germanique, voulait savoir quelle serait la langue que parlerait naturellement un homme n&#8217;ayant pas reçu d&#8217;influences extérieures. Il prit plusieurs bébés, et demanda à des nourrices de s&#8217;en occuper avec beaucoup de soin, mais sans jamais leur parler. Il s&#8217;attendait à ce qu&#8217;ils finissent par parler grec ou latin. </p>
<p>Ça a méchamment échoué. Les bébés ont dépéris et ils sont tous morts.</p>
<h3>Géant vert, nain jaune, etc.</h3>
<p>Il y a une expression à la mode, qui dit : &#8220;Nous sommes des nains sur des épaules de géants&#8221;. Les géants représentent nos ancêtres, qui ont accumulé des connaissances et construit des trucs pour que les générations suivantes vivent mieux. Les nains représentent les humains actuels, qui contribuent eux aussi à améliorer la condition humaine, pas autant que les géants, mais un peu quand même. L&#8217;ensemble géant + nain étant plus haut que le géant tout seul.</p>
<h3>Les pensées d&#8217;un philosophe-généticien-mathématicien-humaniste</h3>
<p>Albert Jacquard dit : &#8220;je suis les liens que je tisse avec d&#8217;autres&#8221;.</p>
<p>C&#8217;est une phrase bizarre. Ce n&#8217;est pas : &#8220;les liens que je tisse avec d&#8217;autres révèlent ma nature profonde&#8221;. C&#8217;est : &#8220;ma nature profonde, ce sont les liens&#8221;.</p>
<p>Ça veut dire qu&#8217;on construit sa personnalité par les relations qu&#8217;on a avec les autres. Ça ressemble à une idée hippie-new-age-cucul-la-praline, mais en fait non. Si on a des relations de merde et qu&#8217;on insulte tous le monde, on se construit une personnalité de merde. On fait ce qu&#8217;on veut de soi-même.</p>
<p><a href="media/55cc1d43.albert_jacquard-03.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/05/albert_jacquard-03.jpg"><img src="media/55cc1d43.albert_jacquard-03.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/05/albert_jacquard-03.jpg" alt="C&#039;est lui Albert Jacquard. Il peut créer un seau rempli de chromosomes par la seule force de sa volonté." title="C&#039;est lui Albert Jacquard. Il peut créer un seau rempli de chromosomes par la seule force de sa volonté." width="373" height="501" class="alignnone size-full wp-image-6039" /></a></p>
<h2>Le fonctionnement de l&#8217;humanité.</h2>
<p>À partir de ces quelques faits amusants, il me semble être possible de déduire deux principes globaux :</p>
<p><b>Les humains sont interdépendants avec leurs contemporains, ainsi qu&#8217;avec les générations passées et futures.</b></p>
<p>Cette interdépendance est inévitable. Vous n&#8217;avez pas le choix, à moins d&#8217;être un ermite habitant une grotte et chassant pour se nourrir. Et si vous décidez de vivre comme ça, surtout, ne partagez pas votre viande de mammouth, vous reprendriez votre interdépendance.</p>
<p>Même quelqu&#8217;un de très riche est interdépendant, car il a besoin d&#8217;un pool d&#8217;humain &#8220;de bonne qualité&#8221;, à qui il pourra acheter des biens et services de bonnes qualités : un bon comptable, un bon cuisinier, un bon chauffeur, un bon constructeur de piscine, un bon médecin, un bon chirurgien esthétique&#8230; Ce riche quelqu&#8217;un ne pourra pas former son pool d&#8217;humain par lui-même. Ça nécessite beaucoup de temps, plus que le temps d&#8217;une seule vie, fût-elle de riche.</p>
<p><a href="media/905c9e44.interdependance.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/05/interdependance.jpg"><img src="media/905c9e44.interdependance.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/05/interdependance.jpg" alt="Interdépendance des gens riches entre eux-même. Source : http://www.cairn.info/revue-societes-contemporaines-2007-4-page-105.htm (tl;dnr)" title="Interdépendance des gens riches entre eux-même. Source : http://www.cairn.info/revue-societes-contemporaines-2007-4-page-105.htm (tl;dnr)" width="500" height="331" class="alignnone size-full wp-image-6040" /></a></p>
<p><b>Plus on développe des liens de bonne qualité avec les autres, plus on est heureux.</b></p>
<p>Voici un graphique exprimant le bonheur d&#8217;une personne en fonction de son argent</p>
<p><a href="media/d58c3912.fonction_argent_bonheur.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/05/fonction_argent_bonheur.png"><img src="media/d58c3912.fonction_argent_bonheur.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/05/fonction_argent_bonheur.png" alt="Des courbes comme ça mériteraient clairement un petit coup de xkcdify." title="Des courbes comme ça mériteraient clairement un petit coup de xkcdify." width="467" height="333" class="alignnone size-full wp-image-6041" /></a></p>
<p>Et un autre exprimant le bonheur d&#8217;une personne en fonction de la qualité et de la quantité de liens qu&#8217;elle a tissé avec d&#8217;autres.</p>
<p><a href="media/b502dc4f.fonction_argent_liens.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/05/fonction_argent_liens.png"><img src="media/b502dc4f.fonction_argent_liens.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/05/fonction_argent_liens.png" alt="Mais j&#039;avais la flemme et je sais pas me servir de xkcdify, désolé !" title="Mais j&#039;avais la flemme et je sais pas me servir de xkcdify, désolé !" width="544" height="388" class="alignnone size-full wp-image-6042" /></a></p>
<p>Le bonheur total d&#8217;une personne étant, à peu de choses près, la somme de ces deux bonheurs.</p>
<p>Cette théorie rejoint plus ou moins celle de la pyramide de Maslow. Sauf que le grand Wikipedia dit que des tas de gens ont invalidé la pyramide de Maslow. Je vais donc pas trop m&#8217;attarder dessus, et faire comme si on n&#8217;était pas au courant. (Un peu de mauvaise foi, ça aide toujours les argumentations).</p>
<p>À partir de ces 2 graphiques, mon conseil en tant que coach du sens de la vie, est le suivant :</p>
<p>Si vous êtes vraiment pauvres, essayez d&#8217;abord de récupérez de l&#8217;argent, plutôt que de vous faire des amis. Ça vous rendra heureux plus vite. Une fois que vous avez atteint un seuil de revenu suffisamment satisfaisant et régulier, ce sera devenu moins rentable, en terme de bonheur, de chercher à gagner encore plus. À partir de là, essayez de vous faire des amis et de créer des liens. </p>
<p>Au passage, cela me permet de rappeler <a href="http://sametmax.com/deux-conneries-a-la-seconde/">qu&#8217;il faut conserver la neutralité d&#8217;internet</a>, car c&#8217;est une formidable machine à fabriquer des liens.</p>
<p>Et au passage bis, je ne pense pas que l&#8217;être humain soit &#8220;naturellement bon&#8221;. Les concepts &#8220;bon&#8221; et &#8220;mauvais&#8221; me semblent trop compliqués pour qu&#8217;ils puissent être implémentés dans la nature.</p>
<p><a href="media/c3896a4d.le-bien-et-le-mal.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/05/le-bien-et-le-mal.jpg"><img src="media/c3896a4d.le-bien-et-le-mal.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/05/le-bien-et-le-mal.jpg" alt="J&#039;ai hésité entre ça et une image de South Park épisode 10 saison 1. Et je me suis dit que South Park, c&#039;était tellement conventionnel." title="J&#039;ai hésité entre ça et une image de South Park épisode 10 saison 1. Et je me suis dit que South Park, c&#039;était tellement conventionnel." width="550" height="330" class="alignnone size-full wp-image-6044" /></a></p>
<p>En fait, l&#8217;humain cherche à maximiser son bonheur personnel, sans forcément se soucier des autres. Mais en plus de ça, une bonne partie des humains a pris conscience du graphique &#8220;liens tissés -> bonheur&#8221;, ce qui va les amener à vouloir développer des liens de bonne qualité avec les autres : rendre service, discuter, échanger des idées, &#8230; Ça donne l&#8217;impression qu&#8217;ils sont naturellement bon, alors qu&#8217;en fait, ils cherchent juste à être heureux eux-même, le plus efficacement possible.</p>
<p>Toute la question est de savoir comment faire prendre conscience aux humains de la relation entre le bonheur et les liens tissés. Je n&#8217;ai pas de réponse précise (éducation ? liens initiaux ?)</p>
<h2>Où veux-je donc en venir ?</h2>
<p>Il vaut mieux pour vous-même que les humains proches de vous soient pas trop cons, pas trop pauvres et un minimum heureux. Ceci pour 2 raisons :</p>
<ul>
<li>
Afin de maximiser votre bonheur personnel, vous devez développer des liens de bonne qualité. Or c&#8217;est plus facile à faire avec des gens &#8220;de bonne qualité&#8221;.
</li>
<p><br/></p>
<li>
Dans &#8220;interdépendance inévitable&#8221; il y a &#8220;dépendance inévitable&#8221;. C&#8217;est moins inquiétant d&#8217;être dépendant de gens de bonne qualité, plutôt que d&#8217;un ramassis de crève-la-faim dépressifs qui ne savent rien faire.
</li>
<p><br/></ul>
<p>Il existe un moyen simple pour s&#8217;assurer que tous les humains autour de vous soient un minimum heureux, et aient la possibilité matérielle d&#8217;être d&#8217;une qualité minimale : le graphique &#8220;argent -> bonheur&#8221;.</p>
<p>Si on s&#8217;assure que tout le monde a la possibilité de s&#8217;avancer un peu dans ce graphique, afin d&#8217;arriver à peu près au point &#8220;Appartement&#8221;, on augmentera énormément le bonheur de beaucoup de gens, à peu de frais.</p>
<p>Si on s&#8217;assure que tout le mode peut s&#8217;avancer encore plus dans le graphique (par exemple, jusqu&#8217;au point &#8220;Rolex&#8221;), ce sera moins rentable. Il faudrait beaucoup plus d&#8217;argent, pour une augmentation de bonheur plutôt faible. Autant donc rester dans des sommes raisonnables.</p>
<p>L&#8217;idée qui en résulte s&#8217;appelle le Revenu de Base Inconditionnel.</p>
<p><a href="media/864131c2.ban_bart.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/05/ban_bart.jpg"><img src="media/864131c2.ban_bart.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/05/ban_bart.jpg" alt="J&#039;ai jamais compris comment Kurt Cobain pouvait chanter sous l&#039;eau." title="J&#039;ai jamais compris comment Kurt Cobain pouvait chanter sous l&#039;eau." width="450" height="225" class="alignnone size-full wp-image-6045" /></a></p>
<h3>Explication du Revenu de Base Inconditionnel en un paragraphe </h3>
<p>Cela consiste à donner la même somme d&#8217;argent, tous les mois, à toutes les personnes d&#8217;un pays ou d&#8217;une région. Ce Revenu continue d&#8217;être perçu même lorsqu&#8217;on commence à travailler, et quel que soit le type de contrat de travail. La somme donnée est calculée de façon à ce que chaque personne puisse vivre &#8220;dignement&#8221;, c&#8217;est à dire : bouffer, se loger et éventuellement acquérir certains biens culturels de base.</p>
<p>Cette idée (pas si nouvelle que ça) est actuellement en train de susciter des réflexions ici et là. C&#8217;est alors que des gens se sont dit que ce serait bien de lancer une Initiative Citoyenne Européenne, pour également faire réflexionner les gens qui nous gouvernent.</p>
<h3>Explication de l&#8217;Initiative Citoyenne Européenne (ICE) en un paragraphe, avec mes propres termes, donc simplifiée à outrance</h3>
<p>Une ICE est créée par un petit groupe de gens, qui demandent que soit mis en place un &#8220;truc dans la loi&#8221; (Ça peut être un peu tout, mais pas complètement n&#8217;importe quoi). Les citoyens de l&#8217;Union Européenne qui sont d&#8217;accord avec le truc en question signent une pétition. Si au bout d&#8217;un an, un million de signature est récupéré, la Commission Européenne est obligée de venir écouter le groupe initiateur de l&#8217;ICE, de réfléchir au truc et de donner un avis. La Commission Européenne peut répondre &#8220;on ne fera pas votre truc, GTFO LOL&#8221;, mais cela doit être accompagné d&#8217;arguments détaillés.</p>
<p>C&#8217;est là où je voulais en venir. Je vous invite à signer l&#8217;ICE pour le Revenu de Base Inconditionnel, afin de réfléchir à cette technique d&#8217;optimisation du bonheur humain. Pour en savoir plus, pour des infos pratiques et concrètes, et pour finalement signer en ligne, ça se passe par ici : <a href="http://revenudebase.info/initiative-citoyenne-europeenne/">http://revenudebase.info/initiative-citoyenne-europeenne/</a></p>
<h3>Si vous pensez que c&#8217;est une idée de merde parce que &lt;pleins de raisons&gt;.</h3>
<p>Le Revenu de Base Inconditionnel modifierait en profondeur notre façon de nous comporter en société, en modifiant notre rapport à l&#8217;argent, au travail et aux autres. C&#8217;est pourquoi, il suscite beaucoup de réactions, parfois assez fortes, de refus ou d&#8217;acceptation.</p>
<p>Les raisons de refuser cette idée sont assez diverses, mais on retombe souvent sur les mêmes. Des gens les ont alors rassemblées, et y ont opposés des arguments pour refuser ce refus. Je vous laisse quelques liens à ce sujet. Rassurez-vous, le propos y est bien plus concret que la réflexion nuagesque que j&#8217;ai faite en début d&#8217;article.</p>
<p>&#8220;Les chômeurs vont jouer à la Playstation&#8221;<br />
<a href="http://revenudebase.info/2013/04/revenu-base-pas-outil-lutte-contre-chomage/">http://revenudebase.info/2013/04/revenu-base-pas-outil-lutte-contre-chomage/</a></p>
<p>&#8220;C&#8217;est une idée libérale / de communiste&#8221;<br />
&#8220;Cela poussera les gens à l’oisiveté&#8221;<br />
&#8220;Plus personne ne voudra effectuer les tâches ingrates&#8221;<br />
&#8220;Le revenu de base va provoquer de l’inflation&#8221;<br />
&#8220;C’est une idée utopiste&#8221;<br />
&#8220;C’est impossible à financer&#8221;<br />
&#8220;L’état est déjà très généreux en France, ça ne va rien changer&#8221;<br />
&#8220;L’immigration va encore plus augmenter&#8221;<br />
&#8220;La société n’est pas prête, il faut d’abord réformer le système&#8221;<br />
<a href="http://www.tetedequenelle.fr/2011/04/mauvaises-raisons-revenu-de-vie/">http://www.tetedequenelle.fr/2011/04/mauvaises-raisons-revenu-de-vie/</a></p>
<p><a href="media/4db3bb93.rinter-hotsale-magic-paper-make-real-money-toy-free-shipping.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/05/Trialsale-10pcs-magic-tricks-money-printer-hotsale-magic-paper-make-real-money-toy-free-shipping.jpg"><img src="media/4db3bb93.rinter-hotsale-magic-paper-make-real-money-toy-free-shipping.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/05/Trialsale-10pcs-magic-tricks-money-printer-hotsale-magic-paper-make-real-money-toy-free-shipping.jpg" alt="It prints money !" title="It prints money !" width="310" height="310" class="alignnone size-full wp-image-6046" /></a></p>
<h3>Si vous pensez toujours que c&#8217;est une idée de merde.</h3>
<p>C&#8217;est votre droit. Et si ça se trouve, c&#8217;est vous qui avez raison.</p>
<p>Mais même dans ce cas, je vous invite à signer l&#8217;ICE. Celle-ci n&#8217;oblige pas l&#8217;Europe à instaurer le Revenu de Base. Elle oblige <strong>à réfléchir</strong> à l&#8217;idée du Revenu de Base. </p>
<p>Si c&#8217;est une idée de merde, les gens de la Commission Européenne auront tôt fait de s&#8217;en apercevoir, car ils sont certainement plus calés que moi en économie, géopolitique, psychohistoire et autres. Ils pourront alors expliquer à tout le monde, et avec des arguments valables, en quoi c&#8217;est de la merde. Si c&#8217;est le cas, je promets de ne plus embêter personne avec cette idée. Une toute petite signature en échange de votre tranquilité future, ça vaut le coup non ?</p>
<p>Le bonheur vaincra !</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6028&amp;md5=2053126202f75ac856da2a8129ac41a1" 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=5809
title: Socket en Python
uri: Socket-en-Python
url: http://sametmax.com/socket-en-python/
content:
<p>Python est un langage de haut niveau, ce qui fait qu&#8217;on a rarement besoin de taper directement dans les interface de couches basses comme les sockets : on utilise des abstractions comme urllib et consort. </p>
<p>Même quand on doit communiquer directement des paquets de données, on préférera utiliser des solutions comme <a href="http://www.zeromq.org/bindings:python">ZeroMQ</a>, bien plus fiables et faciles à mettre en œuvre. </p>
<p>Cela étant dit, pour la culture G, ça ne fait pas de mal d&#8217;avoir un petit hello world des sockets en Python.</p>
<p>Client :</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;">socket</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># cette fonction n'est pas très performante puisqu'elle</span>
<span style="color: #808080; font-style: italic;"># ouvre et ferme la socket pour chaque message,</span>
<span style="color: #808080; font-style: italic;"># mais vous voyez le principe.</span>
<span style="color: #ff7700;font-weight:bold;">def</span> envoyer_message<span style="color: black;">&#40;</span>ip, port, message<span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;"># on ouvre une socket TCP / IP, en IP V4</span>
    <span style="color: #808080; font-style: italic;"># la doc contient une liste de constantes avec</span>
    <span style="color: #808080; font-style: italic;"># les protocoles de base supportés</span>
    <span style="color: #808080; font-style: italic;"># (http://docs.python.org/2/library/socket.html)</span>
    <span style="color: #808080; font-style: italic;"># on peut aussi ouvrir des sockets unix, des datagrames...</span>
    sock = <span style="color: #dc143c;">socket</span>.<span style="color: #dc143c;">socket</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">socket</span>.<span style="color: black;">AF_INET</span>, <span style="color: #dc143c;">socket</span>.<span style="color: black;">SOCK_STREAM</span><span style="color: black;">&#41;</span>
    sock.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>ip, port<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        <span style="color: #808080; font-style: italic;"># on broadcast le message</span>
        sock.<span style="color: black;">sendall</span><span style="color: black;">&#40;</span>message<span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># et on lit la réponse cash pistache</span>
        <span style="color: #808080; font-style: italic;"># Tout ça est synchrone, car si on veut</span>
        <span style="color: #808080; font-style: italic;"># faire de l'asynchrone, l'exemple serait</span>
        <span style="color: #808080; font-style: italic;"># vachement moins simple</span>
        response = sock.<span style="color: black;">recv</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1024</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Received: {}&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>response<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> e:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Impossible de se connecter au serveur: {}&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>e<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">finally</span>:
        <span style="color: #808080; font-style: italic;"># toujours fermer sa socket, même si dans notre cas</span>
        <span style="color: #808080; font-style: italic;"># on a pas besoin de la fermer pour chaque message</span>
        <span style="color: #808080; font-style: italic;"># On pourrait aussi utiliser le context manager closing()</span>
        <span style="color: #808080; font-style: italic;"># pour cette tâche</span>
        sock.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># petit test qui envoit trois messages</span>
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
&nbsp;
    ip, port = <span style="color: #483d8b;">&quot;127.0.0.1&quot;</span>, <span style="color: #ff4500;">7777</span>
&nbsp;
    envoyer_message<span style="color: black;">&#40;</span>ip, port, <span style="color: #483d8b;">&quot;Hello World 1&quot;</span><span style="color: black;">&#41;</span>
    envoyer_message<span style="color: black;">&#40;</span>ip, port, <span style="color: #483d8b;">&quot;Hello World 2&quot;</span><span style="color: black;">&#41;</span>
    envoyer_message<span style="color: black;">&#40;</span>ip, port, <span style="color: #483d8b;">&quot;Hello World 3&quot;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Serveur:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">threading</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">SocketServer</span>
&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;
&nbsp;
<span style="color: #808080; font-style: italic;"># Python vient avec ses serveurs socket tout prêts.</span>
<span style="color: #808080; font-style: italic;"># Tout ce qu'il y a faire c'est créer une classe </span>
<span style="color: #808080; font-style: italic;"># de handler, c'est à dire l'objet qui va s'occuper</span>
<span style="color: #808080; font-style: italic;"># des messages quand ils arrivent. On hérite du </span>
<span style="color: #808080; font-style: italic;"># handler de la lib standard, et on redéfinit juste</span>
<span style="color: #808080; font-style: italic;"># handle() qui est la méthode qui va être appelée</span>
<span style="color: #808080; font-style: italic;"># à chaque message.</span>
<span style="color: #ff7700;font-weight:bold;">class</span> RequestHandler<span style="color: black;">&#40;</span><span style="color: #dc143c;">SocketServer</span>.<span style="color: black;">BaseRequestHandler</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> handle<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 récupère des requêtes, et on répond avec</span>
        <span style="color: #808080; font-style: italic;"># exactement le même message + un timestamp</span>
        data = <span style="color: #008000;">self</span>.<span style="color: black;">request</span>.<span style="color: black;">recv</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1024</span><span style="color: black;">&#41;</span>
        now = <span style="color: #dc143c;">datetime</span>.<span style="color: black;">now</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<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>
        response = <span style="color: #483d8b;">&quot;{}: {}&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>now, data<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">request</span>.<span style="color: black;">sendall</span><span style="color: black;">&#40;</span>response<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Pour le serveur, pas grand chose à faire à part le définir</span>
<span style="color: #808080; font-style: italic;"># Ici je fais un serveur threadé pour le Lulz car ça</span>
<span style="color: #808080; font-style: italic;"># ne sert pas à grand chose pour un client avec 3 messages</span>
<span style="color: #808080; font-style: italic;"># synchrones</span>
<span style="color: #ff7700;font-weight:bold;">class</span> ThreadedTCPServer<span style="color: black;">&#40;</span><span style="color: #dc143c;">SocketServer</span>.<span style="color: black;">ThreadingMixIn</span>, <span style="color: #dc143c;">SocketServer</span>.<span style="color: black;">TCPServer</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;"># on instancie notre server et on lui passe le gestionnaire de</span>
    <span style="color: #808080; font-style: italic;"># requêtes</span>
    server = ThreadedTCPServer<span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'127.0.0.1'</span>, <span style="color: #ff4500;">7777</span><span style="color: black;">&#41;</span>, RequestHandler<span style="color: black;">&#41;</span>
    ip, port = server.<span style="color: black;">server_address</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># on start le thread pour le serveur et on le daemonise</span>
    server_thread = <span style="color: #dc143c;">threading</span>.<span style="color: black;">Thread</span><span style="color: black;">&#40;</span>target=server.<span style="color: black;">serve_forever</span><span style="color: black;">&#41;</span>
&nbsp;
    server_thread.<span style="color: black;">daemon</span> = <span style="color: #008000;">True</span>
    server_thread.<span style="color: black;">start</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># si on appuie sur &quot;enter&quot;, raw_input() s'arrête et le serveur</span>
    <span style="color: #808080; font-style: italic;"># est stoppé</span>
    <span style="color: #008000;">raw_input</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Hit enter to stop the server&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
    server.<span style="color: black;">shutdown</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Je suis d&#8217;un niveau pathétique en réseau, alors je vous pond ça vraiment pour le plaisir de partager mes moments bac à sable. Il y a peu de chance que ça vous serve, mais qui sait ?</p>
<p>P.S: je ne suis pas sur mon OS, donc je mettrai les outputs et le code en ligne plus tard.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5809&amp;md5=201cb2eeaf74d3a76224442a445f7f0f" 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=3946
title: Faire cohabiter plusieurs versions de jQuery
uri: Faire-cohabiter-plusieurs-versions-de-jQuery
url: http://sametmax.com/faire-cohabiter-plusieurs-versions-de-jquery/
content:
<p>jQuery est très bien foutu, non content de permettre d&#8217;utiliser des libs concurrentes utilisant la même API avec <code>noConflict()</code> (c&#8217;est beau l&#8217;open source quand même), elle permet également d&#8217;utiliser en même temps une version plus récente ou plus ancienne de son code, facilitant les migrations.</p>
<p>Pour utiliser noConflict à bon escient, il faut simplement faire très attention à l&#8217;ordre d&#8217;inclusion de ses scripts&#8230;</p>
<p>D&#8217;abord, loader les deux versions de jQuery :</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;script type=&quot;text/javascript&quot; src=&quot;version1-de-jquery.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;plugin-qui-utilise-cette-version.js&quot;&gt;&lt;/script&gt;</pre></div></div>

<p>Ensuite utilise <code>noConflict()</code> pour sauvegarder une référence à cette version :</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;script type=&quot;text/javascript&quot;&gt;
var version1dejQuery = $.noConflict(true);
&lt;/script&gt;</pre></div></div>

<p>Et on charge la deuxième fournée :</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;script type=&quot;text/javascript&quot; src=&quot;autre-version-de-jquery.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;plugin-qui-utilise-cette-autre-version.js&quot;&gt;&lt;/script&gt;</pre></div></div>

<p>On sauvegarde aussi cette version dans une variable :</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;script type=&quot;text/javascript&quot;&gt;
var autreVersionDejQuery = $.noConflict(true);
&lt;/script&gt;</pre></div></div>

<p>Et du coup on peut utiliser les deux en parallèle. Au lieu d&#8217;appeler <code>$</code>, les appelle par leur p&#8217;tit nom :</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">autreVersionDejQuery<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'a'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">click</span><span style="color: #009900;">&#40;</span>truc<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Et comme d&#8217;hab, vous pouvez utiliser la technique de la <a href="http://sametmax.com/la-fonction-anonyme-appelee-immediatement-en-javascript-function/">fonction anonyme immédiatement appelée</a> pour créer un alias local et réutiliser <code>$</code>.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>$<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'img'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">hover</span><span style="color: #009900;">&#40;</span>bidule<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: #009900;">&#40;</span>version1dejQuery<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>D&#8217;ailleurs, je pense que ça ne marche que si les plugins inclus utilisent cette technique, ce qui est normalement une convention dans le monde de jQuery.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=3946&amp;md5=05ba624c6a709b40d2146b4427b1ce6c" 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=6085
title: C’est l’ascenseur émotionnel, tu baises à tous les coups
uri: C-est-l-ascenseur-émotionnel-tu-baises-à-tous-les-coups
url: http://sametmax.com/cest-lascenseur-emotionnel-tu-baises-a-tous-les-coups/
content:
<p>Vous connaissez ce genre de plan. Les amis des amis des amis vous invitent à un apéro d&#8217;amis d&#8217;amis. Vous vous pointez, et vous constatez que que :</p>
<ol>
<li> y a encore des gens qui louent des palaces pour 600 euros par mois.</li>
<li> y a quand même des invités que vous connaissez d&#8217;un autre groupe qui n&#8217;a rien à voir.</li>
<li> finalement vous allez bien rester pour le bar-beuk.</li>
</ol>
<p>Vous discutez avec &#8220;la meuf trop bonne qui a un copain&#8221;, &#8220;le gay de service qui travaille dans la com&#8221;, &#8220;le gamin de 12 ans trop intelligent pour son age&#8221;, &#8220;la grosse qui parle très fort pour se faire plus remarquer que sa bonnasse de copine&#8221;&#8230; Vous vous connectez à internet en screud, parce que merde, on est bourré mais quand même.</p>
<p>Pétanque, eau de vie, tarot, les musicos se mettent en place, ça roule dans les coins, et finalement on va bien rester jusqu&#8217;au dîner.</p>
<p>Deux potes font la compet&#8217; pour la métisse qui a un nom exotique et pas de conversation, le premier se barre avec pendant 1h et revient brocouille, le second tente le rencart en semaine, se prend un demi vent mais chope le numéro.</p>
<p>Et puis finalement on va bien se faire un after.</p>
<p>On termine chez les champions de la soirée, des Sam et Max du commerce. L&#8217;un est un rond et jovial commercial importé du moyen orient, le second est un petit et souriant négociant en immobilier en provenance du soleil levant. Le duo de choc, pas assortis, super sociables, Batman et Robin depuis pas mal de temps.</p>
<p>Whisky-coca. Marie-Juana.</p>
<p>Et on parle business, puis nana. Parce que le pognon et le cul, c&#8217;est assez fédérateur.</p>
<p>Et je suis surpris d&#8217;apprendre que les mecs sont blindés des deux. Ils ne paient pas de mine pourtant. Pas les prototypes du beau gosse, sympas et discrets, pas prétentieux, facilement approchables, habillés simplement.</p>
<p>Sauf que quand on les rejoint ils récupèrent la porsche, et on les suit dans un très bel appart&#8217; avec terrasse et vue.</p>
<p>Ils sont amateurs de FKK, on est allé dans les mêmes endroits, et font du chiffre sur adopte un mec :</p>
<p>&#8220;Le ratio, c&#8217;est un rendez-vous avec baise pour 70 approches.&#8221;, qu&#8217;il me dit. &#8220;Je suis spécialiste en marketting sur ce site. Je fais ça avec une photo floue, et de loin.&#8221;</p>
<p>&#8220;Ouai enfin avec la décapotable, ça aide déjà pas mal non ?&#8221;</p>
<p>&#8220;Nan, jamais au premier rendez-vous. Hier on était à un bar, tu vois, et on leur a dit qu&#8217;on était postier, et plombier. Là, soit les meufs se barrent, soit on passe une bonne soirée. Après, le deuxième soir, on arrive avec la caisse. C&#8217;est la surprise, c&#8217;est l&#8217;ascenseur émotionnel, elles écartent les cuisses cash, tu baises à tous les coups.&#8221;</p>
<p>Je me suis dis que je ferai circuler l&#8217;info. Au cas où vous sachiez pas comment utiliser votre porsche.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6085&amp;md5=81899ad19d7270db135278b83fc8ec77" 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=6095
title: Le choix d’un langage influence le fun de votre carrière
uri: Le-choix-d-un-langage-influence-le-fun-de-votre-carrière
url: http://sametmax.com/le-choix-dun-langage-influence-le-fun-de-votre-carriere/
content:
<p>Les langages de programmation sont censés être des technologies neutres, mais comme toute chose utilisée dans le monde réel pour des usages concrets et nombreux, l&#8217;humain finit par leur donner une orientation, une préférence.</p>
<p>De fait, chaque langage finit par être plus utilisé dans certains types de métiers ou d&#8217;activités, pour certains types de projets, dans certains environnements. Plus important encore, un langage appelle d&#8217;autres outils, et un certain type de collègue, et même si, comme d&#8217;habitude, la généralisation est un piège à con, il y a bien des stéréotypes visibles qui se dégagent.</p>
<p>Ainsi, Java et PHP sont des langages pour lesquels il est très facile de trouver du travail. Il y a une telle base de code là dehors qu&#8217;il y a des annonces partout, et tout le temps. En revanche, les environnements Java sont généralement très très lourds à manipuler. Pas en terme de performance (Java est aujourd&#8217;hui très rapide), mais en terme de charge de travail : énormément de configuration, beaucoup d&#8217;abstractions et de design pattern imbriqués, des APIs et des formats très verbeux&#8230;</p>
<p>Travailler dans un monde Java, c&#8217;est généralement travailler à un rythme lent, plus souvent dans des grosses boîtes, pour des systèmes assez larges avec un grosse inertie. Ne vous attendez pas à des Java-party avec vos collègues après le boulot.</p>
<p>PHP, c&#8217;est la même chose, avec des projets et composants plus simples (dans des entreprises de toutes tailles), et souvent bien plus dégueulasses. Non pas qu&#8217;on ne puisse pas écrire du PHP propre, mais 15 ans de PHP codé à l&#8217;arrache ne s&#8217;effacent pas avec quelques années de Symfony, et autre cakePHP. Du coup on hérite souvent d&#8217;un projet moche comme ta mère. </p>
<p>Bref, Java et PHP vous garantissent un job, mais les projets sont rarement marrants, et l&#8217;ambiance au taff sera pas pumped up. Par contre il y a de la doc et des tutos, même si généralement ceux pour PHP sont de meilleure qualité que pour Java (qui peuvent être assez indigestes).</p>
<p>Il y a une alternative intermédiaire : le C#. Beau langage, beaux outils, c&#8217;est propre sans être trop lourd, et la base de code est pas à vomir. Mais on reste dans le corporate, et la plupart du temps, sur du 98% Microsoft ou affiliés. </p>
<p>Après vous avez des langages spécialisés comme Erlang, Scala, Lisp. Là, trouver du taff sera généralement un challenge. Ce n&#8217;est pas le genre de truc qu&#8217;on voit partout. Et le niveau sera difficile : un débutant peut arriver avec la bite et le couteau dans un projet PHP, mais si vous vous pointez avec 3 mois d&#8217;expérience sur une gateway jabber haute tolérance, le bidouillage ça va pas le faire. </p>
<p>Ce sont des langages qu&#8217;il faut choisir si on aime le taff de haut niveau, la débrouillardise et les solutions intelligentes. En général les missions sont super intéressantes, mais la reconversion est dure. Par contre, vous rencontrerez des collègues qui valent le détour.</p>
<p>Puis il y a les langages de bas niveau, type C/C++. Aujourd&#8217;hui, c&#8217;est massivement des missions scientifiques ou de l&#8217;embarqué : analyse d&#8217;image, cartes électroniques, petites machines, etc. Il y a encore des trucs pas cool genre Windev (j&#8217;ai un pote coincé là dedans, c&#8217;est triste, fuyez ces annonces), mais ce n&#8217;est plus la majorité. Ces langages, c&#8217;est une question de tempérament. Est-ce que vous aimez la minutie ? L&#8217;efficacité des algos ? Le travail sous contrainte technique ? Si oui, alors ce genre de taff peut être très sympa. Sinon, choisissez un langage plus dynamique.</p>
<p>Ensuite il y a les langages de niches : Cobol, Power Builder, etc. Là c&#8217;est généralement des projets de merde très bien payés. Plus personne ne veut coder avec ces trucs, mais ça coûte trop cher à changer. Les jeunes sont acceptés, les formations offertes, le salaire de début de carrière est bon, mais par contre, le code est un truc de mémé. C&#8217;est pas mal pour commencer une carrière et se faire un peu de thune, mais faut savoir en sortir, et ça ne donne pas de bonnes habitudes en prog.</p>
<p>Et pour finir il y des langages dit &#8220;modernes&#8221; (ce qui est un abus&#8230; de langage, car ils ne datent pas d&#8217;hier) comme Python, Ruby ou Javascript. Le côté &#8220;moderne&#8221; vient surtout du fait qu&#8217;ils sont maintenant très adaptés à des projets modernes, où la souplesse de développement a priorité sur le reste des caractéristiques. Choisissez ces langages si vous visez des missions, principalement Web, sur des produits récents. Ce sont les communautés les plus sympas et dynamiques, ça brasse pas mal dans le milieu et c&#8217;est assez jeune. Mais un grand nombre de start up, donc il faut pas chercher la sécurité de l&#8217;emploi.</p>
<p>Une petite parenthèse pour Python tout de même : il n&#8217;est pas autant limité au Web et on le voit aussi beaucoup dans le secteur scientifique et bancaire. C&#8217;est sa versatilité et la facilité de reconversion qu&#8217;il offre qui me fait dire que c&#8217;est un très bon choix comme premier langage. Mais. Car il y a un &#8220;mais&#8221;. Trouver une offre Python sera plus difficile qu&#8217;une offre Ruby, et BEAUCOUP plus difficile qu&#8217;une offre PHP ou Java. Après perso je n&#8217;ai jamais connu le chômage.</p>
<p>Warning ! Il faut faire gaffe à se lancer dans le dev Web. C&#8217;est très tentant, mais contrairement aux autres carrières, ça veut dire <a href="http://sametmax.com/evolution-de-la-courbe-dapprentissage-dun-dev-front-end/">une courbe d&#8217;apprentissage beaucoup plus longue</a>. Vous ne pouvez pas juste apprendre votre langage, ses libs et son env et vous vendre comme &#8220;expert&#8221;.</p>
<p>J&#8217;ai laissé pas mal de truc de côté, comme l&#8217;objective C, Haskell, Smalltalk, le Bash, Perl et <a href="http://99-bottles-of-beer.net">quelques milliers d&#8217;autres langages</a>. On ne peut pas tout faire, et je voudrais surtout peindre un tableau global du marché. En me relisant, je me dis que c&#8217;est bourré d&#8217;idées reçues, qu&#8217;il y a plein d&#8217;exceptions, etc. Mais je pense que les infos données peuvent permettre à des gens qui se posent la question de l&#8217;orientation de prendre une décision moins mauvaise que &#8220;je lance un D20 et on verra bien&#8221;.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6095&amp;md5=8bd7c3e77140bd94c7422f6ef1194601" 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=1086
title: Synchroniser son serveur avec ntp sous Linux
uri: Synchroniser-son-serveur-avec-ntp-sous-Linux
url: http://sametmax.com/synchroniser-son-serveur-avec-ntp-sous-linux/
content:
<p>NTP (Network Time Protocol) est un protocole utilisé pour synchroniser l&#8217;heure de votre système en utilisant un serveur en ligne. Cet article explique comment l&#8217;installer et le configurer sur un système d&#8217;exploitation Linux.</p>
<p><strong>1. Installation</strong></p>
<p>Pour installer le service ntp, ouvrez un terminal en root.</p>
<p><b>Sous Ubuntu:</b></p>

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

<p><b><br />
2. Utilisation<br />
</b></p>
<p>La configuration de ntp se trouve généralement dans le fichier /etc/ntp.conf. On peut y ajouter de nouveaux serveurs de temps, en ajoutant une ligne similaire à celle-ci par exemple :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">server <span style="color: #000000;">0</span>.fedora.pool.ntp.org dynamic</pre></div></div>

<p>Démarrez ensuite le service avec cette commande afin de synchroniser la date et l&#8217;heure (Attention, il faut plusieurs minutes avant que l&#8217;heure soit synchronisée) :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>init.d<span style="color: #000000; font-weight: bold;">/</span>ntpd start</pre></div></div>

<p>On pourra ensuite vérifier que l&#8217;heure est correcte avec la commande &#8220;date&#8221;:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#91;</span>sm<span style="color: #000000; font-weight: bold;">@</span>web1 ~<span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #666666; font-style: italic;"># date</span>
Wed May <span style="color: #000000;">15</span> 07:<span style="color: #000000;">21</span>:<span style="color: #000000;">15</span> UTC <span style="color: #000000;">2013</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span>sm<span style="color: #000000; font-weight: bold;">@</span>web1 ~<span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #666666; font-style: italic;">#</span></pre></div></div>

<p>Note : en cas de problème, on pourra vérifier le bon fonctionnement avec la commande ntpstat qui donnera des informations sur le statut du service ntp :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#91;</span>sm<span style="color: #000000; font-weight: bold;">@</span>web1 ~<span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #666666; font-style: italic;"># ntpstat</span>
synchronised to NTP server <span style="color: #7a0874; font-weight: bold;">&#40;</span>213.161.194.93<span style="color: #7a0874; font-weight: bold;">&#41;</span> at stratum <span style="color: #000000;">4</span>
<span style="color: #000000; font-weight: bold;">time</span> correct to within <span style="color: #000000;">562</span> ms
polling server every <span style="color: #000000;">64</span> s</pre></div></div>

<p><b>A quoi ça sert ?</b></p>
<p>Dans notre cas nous avons des sites qui hébergent du contenu avec des urls qui expirent au bout d&#8217;un certainstemps.<br />
La création de ces urls à durée de vie comptée est faite depuis le serveur web, le contenu se trouvant sur d&#8217;autres serveurs.<br />
ntp dans ce cas nous assure que tous les serveurs seront calés sur la même heure, ce qui évite de générer des urls déjà expirées si un des serveurs de contenu n&#8217;était pas à l&#8217;heure.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=1086&amp;md5=5aabf1ac5ed68a01e3a317c1460fb923" 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=6127
title: Les imports en Python
uri: Les-imports-en-Python
url: http://sametmax.com/les-imports-en-python/
content:
<p>Je suis fan de carmina burrana depuis l&#8217;age de 12 ans, alors pourquoi pas O Fortuna comme musique d&#8217;ambiance :</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="420" height="315" src="http://www.youtube.com/embed/nIwrgAnx6Q8" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<p>Les imports, c&#8217;était fastoche. Vous étiez dans votre petit programme, et pour importer un module de la lib standard, vous faisiez:</p>

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

<p>Par exemple :</p>

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

<p>Et pour importer une classe ou une fonction de cette lib, vous faisiez :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> module <span style="color: #ff7700;font-weight:bold;">import</span> fonction
<span style="color: #ff7700;font-weight:bold;">from</span> module <span style="color: #ff7700;font-weight:bold;">import</span> Classe</pre></div></div>

<p>Par exemple :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> hashlib <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">md5</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">xml</span>.<span style="color: black;">etree</span> <span style="color: #ff7700;font-weight:bold;">import</span> Element</pre></div></div>

<p>Parfois, c&#8217;était un peu plus compliqué, mais ça allait encore. Des fois il fallait importer un sous-module :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> package.<span style="color: black;">sous_package</span> <span style="color: #ff7700;font-weight:bold;">import</span> module</pre></div></div>

<p>Par exemple :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">xml</span>.<span style="color: black;">sax</span> <span style="color: #ff7700;font-weight:bold;">import</span> saxutils</pre></div></div>

<p>Mais ça allait encore.</p>
<p>Et puis un jour vous avez du écrire votre propre module. Vous n&#8217;aviez pas vraiment réfléchi à la question. C&#8217;était juste une petite lib pour regrouper des fonctions. Ou juste une app Django. Un truc tout simple. Mais les imports ont soudainement cessé de devenir clairs. Ça ne marchait pas. Rien ne marchait. Vous aviez des <code>sys.path.append</code> partout juste au cas où et c&#8217;était encore pire.</p>
<p>Vous avez donc décidé de vous remettre à PHP, au moins le <code>include</code> utilise les chemins de fichiers, et ça, c&#8217;est facile.</p>
<h2>Sous le capot</h2>
<p>Quand vous utilisez <code>import</code>, sous le capot Python utilise le fonction <code>__import__</code>. Malgré ses <code>__</code> dans le nom, c&#8217;est une fonction ordinaire, et vous pouvez d&#8217;ailleurs l&#8217;utiliser vous-même :</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;">os</span> = <span style="color: #008000;">__import__</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'os'</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'s'</span>, <span style="color: #483d8b;">'ton'</span>, <span style="color: #483d8b;">'mon'</span>, <span style="color: #483d8b;">'g'</span><span style="color: black;">&#41;</span>
u<span style="color: #483d8b;">'s/ton/mon/g'</span></pre></div></div>

<p>En fait, importer un module, c&#8217;est créer un objet module qui est assigné à une variable tout à fait normale :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>type <span style="color: #483d8b;">'module'</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">os</span> = <span style="color: #483d8b;">&quot;on peut ecraser un module&quot;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</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-12-e34748f24345&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: #dc143c;">os</span>.<span style="color: black;">path</span>
<span style="color: #008000;">AttributeError</span>: <span style="color: #483d8b;">'unicode'</span> <span style="color: #008000;">object</span> has no attribute <span style="color: #483d8b;">'path'</span>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>type <span style="color: #483d8b;">'module'</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">sys</span> = <span style="color: #483d8b;">&quot;je t'ecrase la tronche&quot;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>type <span style="color: #483d8b;">'unicode'</span><span style="color: #66cc66;">&gt;</span></pre></div></div>

<p>Le mécanisme de module Python n&#8217;est donc pas un truc à part, c&#8217;est un objet comme le reste, qui contient des attributs. Les attributs sont les variables et les fonctions du module.</p>
<p>Pour charger un module, la fonction <code>__import__</code> passe par les étapes suivantes :</p>
<ol>
<li>Chercher si le module <code>os</code> existe.</li>
<li>Chercher si le module a déjà été importé. Si oui, s&#8217;arrêter ici et renvoyer le module existant.</li>
<li>Si non, chercher si il a été déjà compilé en .pyc.</li>
<li>Si ce n&#8217;est pas le cas, compiler le fichier .py en .pyc.</li>
<li>Charger le bytecode du fichier pyc.</li>
<li>Créer un objet module vide.</li>
<li>Éxecuter le bytecode dans le contexte de l&#8217;objet module et remplir ce dernier avec le résultat.</li>
<li>Ajouter l&#8217;objet module dans <code>sys.modules</code>, un dictionnaire qui contient tous les modules déjà chargés.</li>
<li>Retourner le module pour pouvoir l&#8217;assigner à une variable, par défaut la variable porte son nom.</li>
</ol>
<p>La fonction <code>__import__</code> est donc très complexe, et d&#8217;ailleurs si vous voulez l&#8217;utiliser pour des trucs plus compliqués qu&#8217;un simple import de module, vous allez galérer car sa signature est vraiment zarb.</p>
<p>Mais pour vous, seule l&#8217;étape 1 est importante à comprendre. C&#8217;est l&#8217;étape à laquelle tout se joue.</p>
<h2>Comment Python définit quel module importer ?</h2>
<p>C&#8217;est la partie vraiment difficile, en effet si un import ne marche pas, c&#8217;est très souvent parce que Python ne trouve pas le module que vous voulez. Et la raison pour laquelle il ne le trouve pas, c&#8217;est que vous ne comprenez pas comment il cherche.</p>
<p>Python utilise ce qu&#8217;on appelle le PYTHON PATH pour chercher les modules importables. C&#8217;est une variable système qui contient une liste de dossiers. Par exemple, sur ma machine, elle contient ceci :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: black;">&#91;</span><span style="color: #483d8b;">''</span>,
 <span style="color: #483d8b;">'/usr/bin'</span>,
 <span style="color: #483d8b;">'/usr/local/lib/python2.7/dist-packages/grin-1.2.1-py2.7.egg'</span>,
 <span style="color: #483d8b;">'/usr/lib/python2.7'</span>,
 <span style="color: #483d8b;">'/usr/lib/python2.7/plat-linux2'</span>,
 <span style="color: #483d8b;">'/usr/lib/python2.7/lib-tk'</span>,
 <span style="color: #483d8b;">'/usr/lib/python2.7/lib-old'</span>,
 <span style="color: #483d8b;">'/usr/lib/python2.7/lib-dynload'</span>,
 <span style="color: #483d8b;">'/home/sam/.local/lib/python2.7/site-packages'</span>,
 <span style="color: #483d8b;">'/usr/local/lib/python2.7/dist-packages'</span>,
 <span style="color: #483d8b;">'/usr/local/lib/python2.7/dist-packages/setuptools-0.6c11-py2.7.egg-info'</span>,
 <span style="color: #483d8b;">'/usr/lib/python2.7/dist-packages'</span>,
 <span style="color: #483d8b;">'/usr/lib/python2.7/dist-packages/PIL'</span>,
 <span style="color: #483d8b;">'/usr/lib/python2.7/dist-packages/gst-0.10'</span>,
 <span style="color: #483d8b;">'/usr/lib/python2.7/dist-packages/gtk-2.0'</span>,
 <span style="color: #483d8b;">'/usr/lib/pymodules/python2.7'</span>,
 <span style="color: #483d8b;">'/usr/lib/python2.7/dist-packages/ubuntu-sso-client'</span>,
 <span style="color: #483d8b;">'/usr/lib/python2.7/dist-packages/ubuntuone-client'</span>,
 <span style="color: #483d8b;">'/usr/lib/python2.7/dist-packages/ubuntuone-control-panel'</span>,
 <span style="color: #483d8b;">'/usr/lib/python2.7/dist-packages/ubuntuone-couch'</span>,
 <span style="color: #483d8b;">'/usr/lib/python2.7/dist-packages/ubuntuone-installer'</span>,
 <span style="color: #483d8b;">'/usr/lib/python2.7/dist-packages/ubuntuone-storage-protocol'</span>,
 <span style="color: #483d8b;">'/usr/lib/python2.7/dist-packages/wx-2.6-gtk2-unicode'</span>,
 <span style="color: #483d8b;">'/usr/lib/python2.7/dist-packages/IPython/extensions'</span><span style="color: black;">&#93;</span></pre></div></div>

<p> Donc, quand vous faites <code>import os</code>, Python va faire une boucle <code>for</code> là dessus et chercher dans chaque dossier si un package (un dossier avec un fichier <code>__init__.py</code>) ou un module (un fichier avec l&#8217;extension <em>.py</em>) nommé <code>os</code> existe.</p>
<p> Dès qu&#8217;il en trouve un, il s&#8217;arrête de chercher et l&#8217;importe. Si il n&#8217;en trouve pas, il va lever une <code>ImportError</code>.</p>
<p> Ce qui signifie que si votre module n&#8217;est PAS dans le PYTHON PATH, vous ne pouvez PAS l&#8217;importer. C&#8217;est impossible.</p>
<p> La grande majorité des problèmes d&#8217;import vient du fait que le module que vous essayez d&#8217;importer n&#8217;est pas dans le PYTHON PATH.</p>
<p> Maintenant, la grande question, c&#8217;est :</p>
<h2>Qu&#8217;est-ce qui est dans le PYTHON PATH ?</h2>
<p>Par défault, les dossiers <em>sites-packages</em> et <em>dist-packages</em> dans le dossier d&#8217;installation Python sont dans le PYTHON PATH. Quelques autres sont ajoutés selon les systèmes, mais vous pouvez toujours compter sur <em>sites-packages</em> et <em>dist-packages</em> pour être dans le PYTHON PATH. Quand vous installez une lib, par exemple avec <a href="http://sametmax.com/votre-python-aime-les-pip/">pip</a>, c&#8217;est là dedans que la lib va s&#8217;installer, pour être sûre de pouvoir être importée.</p>
<p>Quand vous êtes dans un <a href="http://sametmax.com/les-environnement-virtuels-python-virtualenv-et-virtualenvwrapper/">virtualenv</a>, les dossiers <em>sites-packages</em> et <em>dist-packages</em> de l&#8217;environnement virtuel sont ajoutés au PYTHON PATH.</p>
<p>Mais tout ça ne change pas grand chose pour vous. En effet, vous n&#8217;allez pas mettre VOTRE code dans les dossiers <em>sites-packages</em> et <em>dist-packages</em>.</p>
<p>C&#8217;est pour cela que Python possède un mécanisme supplémentaire : le dossier qui contient le module sur lequel vous lancez la commande <code>python</code> est automatiquement ajouté au PYTHON PATH.</p>
<h2>Le PYTHON PATH, en pratique</h2>
<p>Supposons que je sois dans le dossier <em>/home/sam/Bureau</em> et que j&#8217;aie dedans ce package. Voici à quoi ressemble mon arbo (<a href="https://github.com/sametmax/codes-des-articles/blob/master/2013/mai/test_imports.zip">téléchargez l&#8217;arbo vierge</a> pour vos tests):</p>
<pre><strong>/home/sam/Bureau # <-- je suis ici</strong>
.
`-- test_imports
    |-- __init__.py
    |-- package_tout_en_haut
    |   |-- __init__.py
    |   |-- autre_sous_package
    |   |   |-- __init__.py
    |   |   `-- autre_module_en_bas.py
    |   |-- sous_module.py
    |   `-- sous_package
    |       |-- __init__.py
    |       |-- autre_module_en_bas.py
    |       |-- autre_sous_package
    |       |   |-- __init__.py
    |       |   `-- autre_module_en_bas.py
    |       `-- module_tout_en_bas.py
    `-- top_module.py</pre>
<p>Si je lance un shell Python depuis ce dossier ou un script Python contenu dans ce dossier, je peux faire <code>import test_imports</code>, car <em>/home/sam/Bureau</em> est automatiquement ajouté au PYTHON PATH.</p>
<p>Je peux donc faire :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">import</span> test_imports
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">from</span> test_imports <span style="color: #ff7700;font-weight:bold;">import</span> package_tout_en_haut
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">from</span> test_imports <span style="color: #ff7700;font-weight:bold;">import</span> top_module
test_imports.<span style="color: black;">top_module</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">from</span> test_imports.<span style="color: black;">package_tout_en_haut</span> <span style="color: #ff7700;font-weight:bold;">import</span> sous_module
test_imports.<span style="color: black;">package_tout_en_haut</span>.<span style="color: black;">sous_module</span></pre></div></div>

<p>Mais si je me mets ici dans <em>./package_tout_en_haut/sous_package</em> :</p>
<pre>/home/sam/Bureau
.
`-- test_imports
    |-- __init__.py
    |-- package_tout_en_haut
    |   |-- __init__.py
    |   |-- autre_sous_package
    |   |   |-- __init__.py
    |   |   `-- autre_module_en_bas.py
    |   |-- sous_module.py
    |   `-- <strong>sous_package     # <-- je suis ici</strong>
    |       |-- __init__.py
    |       |-- autre_module_en_bas.py
    |       |-- autre_sous_package
    |       |   |-- __init__.py
    |       |   `-- autre_module_en_bas.py
    |       |-- module_tout_en_bas.py
    `-- top_module.py</pre>
<p>Je ne peux PAS importer <code>test_imports</code>, ni dans un shell, ni depuis un module de ce dossier :</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> test_imports
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;">ImportError</span>: No module named test_imports</pre></div></div>

<p>En effet, comme je lance la commande Python depuis</p>
<p> <em>./package_tout_en_haut/sous_package</em></p>
<p> alors</p>
<p> <em>./package_tout_en_haut/sous_package</em> </p>
<p> <strong>EST</strong> ajouté au PYTHON PATH, mais </p>
<p> <em>/home/sam/Bureau/</em> </p>
<p> n&#8217;est <strong>PAS</strong> ajouté au PYTHON PATH.</p>
<p>Je ne peux donc PAS faire</p>

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

<p>depuis un fichier comme </p>
<p><em>.test_imports/package_tout_en_haut/sous_package/autre_module_en_bas.py</em> </p>
<p>et exécuter directement</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">python autre_module_en_bas.<span style="color: black;">py</span></pre></div></div>

<p>ni même</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">python ./test_imports/package_tout_en_haut/sous_package/autre_module_en_bas.<span style="color: black;">py</span></pre></div></div>

<p>Je peux faire</p>

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

<p>depuis </p>
<p><em>autre_module_en_bas.py</em> </p>
<p>uniquement si je lance un script Python tout en haut de mon arbo qui importe </p>
<p><em>autre_module_en_bas.py</em>.</p>
<h2>Mais alors, comment on fait ?<br />
</h2>
<p>Il faut s&#8217;assurer que le dossier qui contient <code>test_imports</code>, notre module racine, soit TOUJOURS dans le PYTHON PATH.</p>
<p>Il y a plusieurs possibilités pour cela.</p>
<p>La première, c&#8217;est que notre lib va être utilisée une fois installée avec pip. Dans ce cas, on s&#8217;en branle, <code>test_imports</code> sera dans sites-packages automatiquement, et on pourra faire <code>from test_imports import top_module </code> de partout joyeusement.</p>
<p>Mais souvent, ce n&#8217;est pas le cas, votre code n&#8217;est pas fait pour être installé.</p>
<p>La seconde technique consiste à s&#8217;assurer que l&#8217;on appelle TOUJOURS la commande Python depuis le dossier qui est tout au dessus. C&#8217;est ce que fait django avec sa commande <code>./manage.py</code> par exemple.</p>
<p>Vous avez votre projet :</p>
<pre>./manage.py
projet</pre>
<p>Et tout passe par <code>python manage.py</code>, qui est au dessus de projet, donc le dossier est bien ajouté au PYTHON PATH, et tout va bien.</p>
<p>Dans votre cas ça veut dire vous assurer qu&#8217;on lance toujours votre programme depuis un script d&#8217;entrée qui est tout en haut de votre arborescence.</p>
<p>Ca veut dire que vous devez avoir un point d&#8217;entrée UNIQUE pour votre package.</p>
<p>Mais parfois ça ne convient pas. Dans le cas des tests unitaires par exemple, il vous faut un point d&#8217;entrée spécialement pour les tests.</p>
<p>Pour ce genre de scénario, il faut donc avoir le dossier qui les contient <strong>à côté</strong> de votre package.  Ainsi, si j&#8217;avais des tests unitaires, je devrais faire un dossier <em>tests</em> à côté du dossier <em>test_imports</em>. Par exemple, transformer mon arbo en un truc comme ça :</p>
<pre>src
   |_ test_imports
   |_ tests
</pre>
<p>Afin que je lance les tests en faisant <code>python tests</code> depuis <em>src</em>. Et dans mes fichiers de tests, je pourrai faire des <code>from test_imports import truc</code>.</p>
<p>La manière dont vous organisez votre projet est donc très importante en Python, et si vous avez des problèmes d&#8217;import, la première chose à faire est de changer sa structure. Il n&#8217;y a pas de magie.</p>
<p>La dernière possibilité, quand tout a échoué, c&#8217;est de rajouter à la main le dossier dans le PYTHON PATH. <code>sys.path</code> est une simple liste, on peut donc faire un <code>append()</code> dessus.</p>
<p>Par exemple, si je veux absolument (mais je ne devrais pas :-)) pouvoir faire :</p>
<p><code>python .test_imports/package_tout_en_haut/sous_package/autre_module_en_bas.py</code> et importer <code>test_imports</code> dans <em>autre_module_en_bas.py</em>, je peux faire un truc du genre :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
&nbsp;
dossier = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">abspath</span><span style="color: black;">&#40;</span>__file__<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff7700;font-weight:bold;">not</span> dossier.<span style="color: black;">endswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'test_imports'</span><span style="color: black;">&#41;</span>:
    dossier = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span>dossier<span style="color: black;">&#41;</span>
&nbsp;
dossier = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span>dossier<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> dossier <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">sys</span>.<span style="color: black;">path</span>:
    <span style="color: #dc143c;">sys</span>.<span style="color: black;">path</span>.<span style="color: black;">append</span><span style="color: black;">&#40;</span>dossier<span style="color: black;">&#41;</span></pre></div></div>

<p>Ce code va remonter dans l&#8217;arbo jusqu&#8217;à tomber sur le chemin du dossier <em>test_imports</em> et ajouter son dossier parent au PYTHON PATH.</p>
<p>Ce n&#8217;est pas le truc le plus propre du monde, mais ça peut dépanner.</p>
<h2>Imports absolus et relatifs</h2>
<p>Si vous êtes dans <em>./package_tout_en_haut/sous_package</em> :</p>
<pre>/home/sam/Bureau
.
`-- test_imports
    |-- __init__.py
    |-- package_tout_en_haut
    |   |-- __init__.py
    |   |-- autre_sous_package
    |   |   |-- __init__.py
    |   |   `-- autre_module_en_bas.py
    |   |-- sous_module.py
    |   `-- <strong>sous_package     # <-- je suis ici</strong>
    |       |-- __init__.py
    |       |-- autre_module_en_bas.py
    |       |-- autre_sous_package
    |       |   |-- __init__.py
    |       |   `-- autre_module_en_bas.py
    |       |-- module_tout_en_bas.py
    |       `-- test_imports  # <-- autre package nommé test_imports
    |           `-- sous_module.py
    `-- top_module.py</pre>
<p>Vous voyez que vous avez deux packages nommés <em>test_imports</em>.</p>
<p>Si vous écrivez <code>import test_imports</code> dans <em>autre_module_en_bas.py</em>, que va-t-il se passer ?</p>
<p>C'est le module tout en bas qui va être importé.</p>
<p>Ce n'est pas forcément ce que vous voulez. Python 3 corrige cela en permettant des imports relatifs, et Python 2.7 peut en bénéficier en important tout en haut du module :</p>

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

<p>En faisant cela, vous obtenez le comportement de Python 3 dans Python 2.7, et vous pourrez alors choisir entre 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> test_imports <span style="color: #808080; font-style: italic;"># importe le module tout en haut</span>
<span style="color: #ff7700;font-weight:bold;">import</span> .<span style="color: black;">test_imports</span> <span style="color: #808080; font-style: italic;"># import le module dans le même dossier</span>
<span style="color: #ff7700;font-weight:bold;">from</span> .<span style="color: black;">test_imports</span> <span style="color: #ff7700;font-weight:bold;">import</span> sous_module
<span style="color: #ff7700;font-weight:bold;">from</span> test_imports <span style="color: #ff7700;font-weight:bold;">import</span> top_module</pre></div></div>

<p>Je vous recommande de toujours utiliser <em>from __future__ import absolute_import</em>. Ca ne coûte rien, et c'est plus cohérent. Par contre, vous ne pourrez pas tester <em>from __future__ import absolute_import</em> dans le shell, donc cet exemple ne marche pas dans ipython, mais il fonctionne parfaitement dans vos modules.</p>
<p>On peut aussi faire des imports relatifs du package contenant avec :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> .. <span style="color: #ff7700;font-weight:bold;">import</span> truc
<span style="color: #ff7700;font-weight:bold;">from</span> ..<span style="color: black;">package</span> <span style="color: #ff7700;font-weight:bold;">import</span> machin</pre></div></div>

<p>N'oubliez pas que ceci ne marche que :</p>
<ul>
<li>Si <code>from __future__ import absolute_import</code> est activé.</li>
<li>Le package tout en haut (celui qui contient tous les autres) est dans le PYTHON PATH</li>
</ul>
<p>Sinon, ça ne sert A RIEN. Ce n'est pas comme un <em>../</em> dans un bash. Ça ne remonte pas d'un dossier. C'est juste une notation pour dire j'utilise celui la plutôt que l'autre, quand il y a ambiguité.</p>
<h2>Pièges des imports</h2>
<h3>Package sans init</h3>
<p>Si vous avez :</p>
<pre>.
`-- test_imports
    |-- __init__.py
    |-- package_sans_init
    |   `-- nada.py</pre>
<p><em>nada.py</em> n'est pas importable, car <em>package_sans_init</em> ne contient pas de fichier <em>__init__.py</em>, même si <em>test_imports</em> est dans le PYTHON PATH. Ce comportement est corrigé en Python 3, et tout sous-dossier d'un package importable est automatiquement importable, qu'il contienne un <em>__init__.py</em> ou non.</p>
<h3>Imports circulaires</h3>
<p>J'en ai déjà parlé <a href="http://sametmax.com/quelques-erreurs-tordues-et-leurs-solutions-en-python/">ici</a>.</p>
<p>Vous avez :</p>
<pre>.
`-- test_imports
    |-- __init__.py
    |-- package_tout_en_haut
    |   |-- __init__.py
    |   `-- sous_package
    |       |-- __init__.py
    |       |-- autre_module_en_bas.py
    |       `-- module_tout_en_bas.py</pre>
<p>Et vous importez <code>autre_module_en_bas</code> dans <code>module_tout_en_bas</code> et inversement. Non seulement ça ne marchera pas, mais en plus l'erreur est déroutante :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #008000;">ImportError</span>: No module named module_tout_en_bas</pre></div></div>

<p>Oui vous avez bien lu, il va vous dire que le module n'existe pas !</p>
<p>Il n'y a pas non plus de solution propre à ce problème : soit vous fusionnez vos deux fichiers, soit vous faites un 3eme module qui utilise ces deux modules (et ces deux modules n'importent pas ce 3eme module).</p>
<p>Sinon il y a la solution crade : mettre un des imports dans un appel de fonction ou de méthode comme ça:</p>

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

<p>Parfois, ça dépanne :-) On ne tue pas des chatons non plus, donc si ça ne devient pas une habitude, ça peut passer.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6127&amp;md5=6dfcefd6dd5011b94280860d37ab983d" 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=1605
title: Qu’est-ce qu’un callable en Python ?
uri: Qu-est-ce-qu-un-callable-en-Python
url: http://sametmax.com/quest-ce-quun-callable-en-python/
content:
<p>Petit définition du jour.</p>
<p>Un callable, qu&#8217;on peut traduire maladroitement par &#8220;appelable&#8221;, est un objet qui peut être appelé. Et ça ne vous arrange pas beaucoup de savoir ça.</p>
<p>On parle de callable dans les tutos, les docs, etc, en supposant que vous savez ce que ça veut dire.</p>
<p>En fait c&#8217;est très simple, si vous pouvez mettre deux parenthèses après le nom d&#8217;un objet (en fait de la variable qui contient l&#8217;objet, mais ne chipotons pas) pour obtenir un effet, alors l&#8217;objet est un callable.</p>
<p>Une fonction est un callable:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">def</span> fonction<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;Vous m'avez appelé&quot;</span><span style="color: black;">&#41;</span>
...
<span style="color: #66cc66;">&gt;&gt;&gt;</span> fonction<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># appel de la fonction</span>
Vous m<span style="color: #483d8b;">'avez appelé</span></pre></div></div>

<p>Une classe est un callable:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> Class<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># appel de la classe</span>
<span style="color: #66cc66;">&lt;</span>__main__.<span style="color: black;">Class</span> <span style="color: #008000;">object</span> at 0x26d8310<span style="color: #66cc66;">&gt;</span></pre></div></div>

<p>Une méthode est un callable :</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> Class<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> 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;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Veuillez patientez, nous allons répondre à votre appel&quot;</span><span style="color: black;">&#41;</span>
...
<span style="color: #66cc66;">&gt;&gt;&gt;</span> obj = Class<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> obj.<span style="color: black;">methode</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># appel de la méthode</span>
Veuillez patientez, nous allons répondre à votre appel</pre></div></div>

<p>Il sont callables car on peut faire <code>()</code> dessus, et il se passe quelque chose. On peut les appeler.</p>
<p>Et par voie de conséquence, un callable peut <strong>retourner</strong> une valeur quand il est appelé. En fait, un callable est même garanti de retourner une valeur quand il est appelé, puisque toute fonction ou méthode retourne <code>None</code> par défaut en Python, et toute classe retourne au moins un objet vide.</p>
<p>Les string, les int, les listes, les fichiers ou les dicos ne sont pas des callables :</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: #ff4500;">1</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
File <span style="color: #483d8b;">&quot;&lt;ipython-input-11-769e123a5ede&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: #ff4500;">1</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">TypeError</span>: <span style="color: #483d8b;">'int'</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>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;&quot;</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
File <span style="color: #483d8b;">&quot;&lt;ipython-input-12-de235e3e26d7&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: #483d8b;">&quot;&quot;</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">TypeError</span>: <span style="color: #483d8b;">'unicode'</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>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
File <span style="color: #483d8b;">&quot;&lt;ipython-input-13-bda5b10b5bf7&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: black;">&#91;</span><span style="color: black;">&#93;</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">TypeError</span>: <span style="color: #483d8b;">'list'</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>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
File <span style="color: #483d8b;">&quot;&lt;ipython-input-14-67901a4bc3e8&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: black;">&#123;</span><span style="color: black;">&#125;</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">TypeError</span>: <span style="color: #483d8b;">'dict'</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>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> f = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/etc/fstab'</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> f<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
File <span style="color: #483d8b;">&quot;&lt;ipython-input-16-0ec059b9bfe1&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>
f<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">TypeError</span>: <span style="color: #483d8b;">'file'</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></pre></div></div>

<p>Mais les classes (et oui, ce sont des classes, pas des fonctions malgré leurs noms en minuscule) <code>str</code>, <code>int</code>, <code>list</code>, <code>dict</code> et <code>file</code> sont des callables :</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;">int</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">0</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">''</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">dict</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">file</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/etc/fstab'</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>open <span style="color: #008000;">file</span> u<span style="color: #483d8b;">'/etc/fstab'</span>, mode <span style="color: #483d8b;">'r'</span> at 0x2689930<span style="color: #66cc66;">&gt;</span></pre></div></div>

<p>En fait, la plupart des objets ne sont tout simplement pas des callables. Aucun nouvel objet n&#8217;est un callable par nature.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> obj = Class<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> obj<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
File <span style="color: #483d8b;">&quot;&lt;ipython-input-18-da8742d08647&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>
obj<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">TypeError</span>: <span style="color: #483d8b;">'Class'</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></pre></div></div>

<p>Donc, quand on vous dit de passer un &#8220;callable&#8221; en paramètre, généralement on vous dit de passer une fonction (sans les parenthèses), une classe (sans les parenthèses) ou une méthode (sans les parenthèses), afin de s&#8217;en servir comme <a href="http://sametmax.com/quest-ce-quun-callback/"><strong>call</strong>back</a>.</p>
<p>Par exemple, les champs des modèles Django acceptent un callable comme paramètre par défaut. Comme les callables sont garantis de retourner une valeur, Django utilise cela pour créer dynamiquement une valeur par défaut. La fonction <a href="http://sametmax.com/ordonner-en-python/">sort()</a> des listes accepte un callable en callback pour le paramètre key.</p>
<p>Demander un callable, c&#8217;est donc demander un truc qu&#8217;on peut appeler en utilisant des parenthèses, et qui va retourner un autre truc.</p>
<p>Au passage, pour votre culture, on peut créer ses propres callables. Ça sert rarement, dans quelques cas tordus. Il suffit de créer une classe avec la méthode magique <code>__call__</code>, et l&#8217;objet retourné sera automatiquement un callable :</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> CreerUnCallable<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;">__call__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
...                 <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;Vous m'avez appelé, maître ?&quot;</span>
...
<span style="color: #66cc66;">&gt;&gt;&gt;</span> un_callable = CreerUnCallable<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>un_callable<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
Vous m<span style="color: #483d8b;">'avez appelé, maître ?</span></pre></div></div>

<p>On a donc ici DEUX callables : la classe, qui est callable par nature, et l&#8217;instance de la classe, qui est callable grâce à la méthode <code>__call__</code>.</p>
<p>Et moi j&#8217;ai commencé à taper cet article parce que je me suis dit que c&#8217;était une notion simple et que ça allait être vite fait, juste avant le petit dèj. Ca fait une heure que je suis dessus. Qu&#8217;est-ce que je suis con des fois.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=1605&amp;md5=0625590521663172fdd6453d170b7236" 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=6146
title: Mise à jour
uri: Mise-à-jour
url: http://sametmax.com/mise-a-jour/
content:
<p>J&#8217;ai mis à jour la liste des cours en <a href="http://sametmax.com/cours-et-tutos/les-articles-pour-apprendre-python-dans-le-bon-ordre/">Python</a> et <a href="http://sametmax.com/cours-et-tutos/les-articles-pour-apprendre-django-dans-le-bon-ordre/">Django</a>.</p>
<p>J&#8217;ai aussi updaté <a href="https://github.com/sametmax/miroir-du-blog/archive/master.zip">la copie offline du site</a> pour que vous puissiez en profiter dans le train, au camping, chez mamie, etc.</p>
<p>Enjoy.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6146&amp;md5=68cd49405cb06f97ccd9b4dbac9b1ec9" 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=6158
title: Nouvelle config iPython
uri: Nouvelle-config-iPython
url: http://sametmax.com/nouvelle-config-ipython/
content:
<p>J&#8217;ai bricolé une config pour iPython dernièrement. Rappelez-vous, on peut complètement <a href="http://sametmax.com/personnalisez-le-demarrage-dipython/">customiser ce shell</a>.</p>
<p>Voici ce que j&#8217;ai dans mon <em>./.config/ipython/profile_default/ipython_config.py</em>:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">c.<span style="color: black;">TerminalIPythonApp</span>.<span style="color: black;">exec_lines</span> = <span style="color: black;">&#91;</span>
<span style="color: #483d8b;">'doctest_mode on'</span>,
<span style="color: #483d8b;">'from __future__ import unicode_literals, absolute_import, division'</span>,
<span style="color: #483d8b;">'import sys'</span>,
<span style="color: #483d8b;">'import os'</span>,
<span style="color: #483d8b;">'import re'</span>,
<span style="color: #483d8b;">'import json'</span>,
<span style="color: #483d8b;">'import base64'</span>,
<span style="color: #483d8b;">'import calendar'</span>,
<span style="color: #483d8b;">'import csv'</span>,
<span style="color: #483d8b;">'import datetime'</span>,
<span style="color: #483d8b;">'import itertools'</span>,
<span style="color: #483d8b;">'import random'</span>,
<span style="color: #483d8b;">'import hashlib'</span>,
<span style="color: #483d8b;">'import tempfile'</span>,
<span style="color: #483d8b;">'import argparse'</span>,
<span style="color: #483d8b;">'import math'</span>,
<span style="color: #483d8b;">'import random'</span>,
<span style="color: #483d8b;">'import subprocess'</span>,
<span style="color: #483d8b;">'from glob import glob'</span>,
<span style="color: #483d8b;">'from uuid import uuid4'</span>,
<span style="color: #483d8b;">'from datetime import datetime, timedelta'</span>,
<span style="color: #483d8b;">'from collections import Counter, OrderedDict'</span>,
<span style="color: #483d8b;">&quot;&quot;&quot;
def initial_imports():
&nbsp;
    # ne faites pas ça dans un code de prod :-)
    global path, relativedelta, requests 
&nbsp;
    print(&quot;<span style="color: #000099; font-weight: bold;">\\</span>nImported : 'sys', 'os', 're', 'json', 'base64', 'calendar', 'csv', 'datetime', 'itertools', 'random', 'hashlib', 'tempfile', 'argparse', 'math', 'random', 'glob', 'uuid4', 'datetime', 'timedelta', 'Counter', 'OrderedDict', 'subprocess'<span style="color: #000099; font-weight: bold;">\\</span>n&quot;)
&nbsp;
    try:
        from path import path
        print('Imported : &quot;path&quot;')
    except ImportError:
        print(&quot;'path' is not available&quot;)
&nbsp;
    try:
        from dateutil import relativedelta
        print('Imported : &quot;relativedelta&quot;')
    except ImportError:
        print(&quot;'dateutil' is not available&quot;)
&nbsp;
    try:
        import requests
        print('Imported : &quot;requests&quot;')
    except ImportError:
        print(&quot;'requests' is not available&quot;)
&nbsp;
    try:
        env = os.environ['VIRTUAL_ENV']
        print(&quot;<span style="color: #000099; font-weight: bold;">\\</span>nENV '{}'. You can import:<span style="color: #000099; font-weight: bold;">\\</span>n&quot;.format(os.path.basename(env)))
        cmd = subprocess.check_output([env + &quot;/bin/pip&quot;, &quot;freeze&quot;],
                                      stderr=subprocess.STDOUT).strip().split(&quot;<span style="color: #000099; font-weight: bold;">\\</span>n&quot;)
        p = re.compile(r'(^.*<span style="color: #000099; font-weight: bold;">\:</span><span style="color: #000099; font-weight: bold;">\s</span>)|((#|@).*$)|(==.*$)')
        print(&quot;'&quot; + &quot;', '&quot;.join(sorted(set(os.path.basename(p.sub('', f)) for f in cmd))) + &quot;'&quot;)
    except KeyError:
        pass
&nbsp;
    print('')
&quot;&quot;&quot;</span>,
<span style="color: #483d8b;">&quot;initial_imports()&quot;</span>
<span style="color: black;">&#93;</span></pre></div></div>

<p>Du coup, au démarrage d&#8217;iPython j&#8217;ai les bénéfices suivant :</p>
<ul>
<li>Comportement de Python 3 pour l&#8217;unicode, les imports et la division. Ils sont plus sains et facile à manipuler (plus besoin de préfixer de &#8216;u&#8217; les chaînes par exemple).</li>
<li>J&#8217;ai tout de suite sous la main une tonne de modules que j&#8217;utilise souvent sans avoir à les importer (os, datetime, random, etc).</li>
<li>J&#8217;importe aussi des modules optionnels (path, requests&#8230;).</li>
<li>Je sais si je suis dans un environnement virtuel, et si oui, ce qu&#8217;il y a installé dedans.</li>
</ul>
<p>Je vire aussi la bannière de démarrage :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">c.<span style="color: black;">TerminalIPythonApp</span>.<span style="color: black;">display_banner</span> = <span style="color: #008000;">False</span></pre></div></div>

<p>Et hop, mon affichage au démarrage ressemble à ça :</p>
<pre>$ ipython
Exception reporting mode: Plain
Doctest mode is: ON

Imported : 'sys', 'os', 're', 'json', 'base64', 'calendar', 'csv', 'datetime', 'itertools', 'random', 'hashlib', 'tempfile', 'argparse', 'math', 'random', 'glob', 'uuid4', 'datetime', 'timedelta', 'Counter', 'OrderedDict', 'subprocess'

'path' is not available
'dateutil' is not available
Imported : "requests"

ENV 'my_env'. You can import:

'BeautifulSoup', 'Django', 'Fabric', 'Jinja2', 'Pillow', 'Pygments', 'Sphinx', 'URLObject', 'Werkzeug', 'argparse', 'beautifulsoup4', 'colorlog', 'distribute', 'django-appconf', 'django-bootstrap-pagination', 'django-bootstrap-toolkit', 'django-compressor', 'django-debug-toolbar', 'django-extensions', 'django-guardian', 'django-loginas', 'django-model-utils', 'django-pdb', 'django-pytest', 'django-rest-framework.git', 'django-template-repl', 'docutils', 'easy-thumbnails', 'feedparser', 'gunicor
</pre>
<p>Ça fait un gros bloc visuellement, mais ça ne s&#8217;affiche qu&#8217;une fois, et le délai est acceptable.</p>
<p>Si j&#8217;ai besoin de l&#8217;info à nouveau, je peux toujours appeler :</p>

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

<p>Que ce genre de choses soient possibles et faciles me font adorer Python. La force du langage, ce n&#8217;est pas seulement son core, c&#8217;est tout son environnement, ses libs, ses outils qui gravitent autour qui rendent l&#8217;expérience de dev fantastique.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6158&amp;md5=6eff89bdb98100a1faaf0fa4efa6d050" 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=6098
title: Il faut coucher utile
uri: Il-faut-coucher-utile
url: http://sametmax.com/il-faut-coucher-utile/
content:
<p>Petit transcript, parce que j&#8217;adore rappeler que tous les avis sont dans la nature.</p>
<p>Je déjeune avec une très ancienne amie d&#8217;enfance, chanteuse lyrique de métier, glamour, voir cul-cul, bobo bio récupérant ses meubles dans les poubelles, amatrice de chats, d&#8217;une grande gentillesse, le sourire tendre servi avec des tâches de rousseur. Bref, pas la Paris Hilton de base.</p>
<p>Sam : &#8220;En fait tu considères que ta carrière décolle vraiment quand ? Quand tu n&#8217;as plus besoin de faire d&#8217;auditions ?&#8221;</p>
<p>Coraline : &#8220;Plutôt quand tu es payée ce que tu dois être payée pour ton travail. Les auditions, ça n&#8217;a rien à voir. Moi je galère toujours. Tu te souviens de mon amie Pascaline ? Celle qui a couché avec < Insérer ici le nom d'un grand ténor >. Dans la foulée elle a eu 3 auditions avec 3 des plus grandes maisons de Paris. Il faudrait que j&#8217;apprenne à faire comme elle.&#8221;</p>
<p>&#8220;Au moins vous les filles, vous pouvez faire ça. Nous on peut même pas coucher pour réussir.&#8221; (Sauf avec les gays, mais j&#8217;y ai pas pensé sur le coup. Remarque je devrais peut être tenter la cougar.)</p>
<p>&#8220;Attend, c&#8217;est le minimum. Déjà elle couche avec lui, c&#8217;est normal qu&#8217;il fasse quelque chose pour elle. Elle a pu se faire écouter par une agence qui m&#8217;a répondu qu&#8217;ils n&#8217;avaient plus le temps d&#8217;écouter personne. Comme ça, sur un coup de fil du mec. Moi je suis pour, hein. Si le mec te plaît pas, non, mais si il te plaît, y a pas de raison. J&#8217;avais un prof de chant qui me disait &#8216;Il faut coucher utile. Agréable, mais utile.&#8217;&#8221;</p>
<p>FEMA, où es-tu ?</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6098&amp;md5=a595818f5b9aab715cde34ff16dba52c" 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=5976
title: Des années plus tard, je n’aime toujours pas les CBV
uri: Des-années-plus-tard-je-n-aime-toujours-pas-les-CBV
url: http://sametmax.com/des-annees-plus-tards-je-naime-toujours-pas-les-cbv/
content:
<p>Les Class Based Views se trouvent maintenant partout en Django. Je les comprends aujourd&#8217;hui très bien, et les utilise souvent au mieux. Dernièrement j&#8217;ai dû utiliser <a href="http://django-rest-framework.org/">django-rest-framework</a>, une très belle application, qui fait un usage utile et massif des CBV, et effectivement, cette architecture m&#8217;a rendu très productif.</p>
<p>Mais je maintiens ce que je dis depuis le début : ce n&#8217;est pas un pas en avant.</p>
<p>D&#8217;abord, qui dit CBV dit référence constante à la documentation. J&#8217;ai été productif avec CBV parce que :</p>
<ul>
<li>Je connais l&#8217;API Django sur le bout des doigts.</li>
<li>Je comprends parfaitement les CBV (et la POO en Python en général).</li>
<li>Je lis très vite, et j&#8217;ai l&#8217;habitude de fouiller dans les docs.</li>
<li>Je me balade dans le code source naturellement.</li>
</ul>
<p>Mais ce n&#8217;est pas comme ça que c&#8217;est censé être. Si vous utilisez une belle API, comme <a href="http://sametmax.com/sept-petites-libs-qui-changent-la-vie-dun-dev-python/">requests ou path.py</a>, vous n&#8217;avez PAS besoin de tout cela. Vous jetez un coup d’œil à la doc, et vous faites 80% du boulot dans le shell, puis de temps à autre, vous vous référez à la documentation sur les points ambiguës. Je n&#8217;ai jamais du aller dans le code source de <code>requests</code>, je n&#8217;ai jamais eu besoin de comprendre <code>urllib</code> de fond en comble pour utiliser <code>requests</code>, et je n&#8217;ai pas besoin de connaître les subtilités de plusieurs paradigmes de programmation pour utiliser <code>requests</code>.</p>
<p>Alors oui, <code>requests</code> ne peut en aucun cas être comparé à Django en terme de taille et de couverture de besoin, et certes, en tant que professionnel averti, je suis tenu d&#8217;être capable de faire tout cela. Mais il y a quand même une énorme différence d&#8217;effort à fournir, et de qualification à avoir, pour l&#8217;usage de cette techno.</p>
<p>En prime, il est TRÈS difficile de débugger une CBV :</p>
<ul>
<li>Dans une vue générique sous forme de fonction, on peut juste faire <a href="http://sametmax.com/debugger-en-python-les-bases-de-pdb/">import ipdb</a>, et faire un step puis débugger tranquillement. Dans une CBV, vous le mettez où le break point ? Soit vous overridez une méthode (et il faut savoir par cœur laquelle), soit vous faites un wrapper provisoir sous forme de fonction (!), soit vous mettez le break cash dans le code source de la lib. C&#8217;est nul à chier, et improductif. Et certainement pas à la portée d&#8217;un débutant.</li>
<li>Les mixins ont un tas de comportements implicites, qu&#8217;il faut connaître pour comprendre pourquoi ceci fait cela. Et comme il y a généralement 3 ou 4 mixins (d&#8217;ailleurs, combien de dev peuvent donner la définition d&#8217;un mixin ?), et bien si il y a un problème, il y a 4 sources possibles. Qui héritent parfois d&#8217;autres classes, ce qui démultiplie le truc.</li>
<li>Quand ça plante le stack trace est blindée de références à droite et à gauche. Un putain de labyrinthe.</li>
</ul>
<p>Rajoutez à cela que la syntaxe est verbeuse comme c&#8217;est pas permis :</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_context_data<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>:
    context = <span style="color: #008000;">super</span><span style="color: black;">&#40;</span>MaClass, <span style="color: #008000;">self</span><span style="color: black;">&#41;</span>.<span style="color: black;">get_context_data</span><span style="color: black;">&#40;</span><span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>
    context<span style="color: black;">&#91;</span><span style="color: #483d8b;">'ma_var'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">&quot;ma valeur&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> context</pre></div></div>

<p>Pour rajouter UNE variable dans le contexte ? Rhaaaaaaaaaaa. Je code en Python, pas en Java !</p>
<p>Et terminez sur le fait que pour utiliser tous les décorateurs codés depuis 5 ans, vous avez <a href="http://stackoverflow.com/questions/6069070/how-to-use-permission-required-decorators-on-django-class-based-views">une syntaxe bien pourrie</a> ou alors des <a href="https://github.com/lukaszb/django-guardian/issues/48">réimplementations complètes</a> sous forme de mixins. Yeah !</p>
<p>Vous comprendrez que ça me gonfle.</p>
<p>Tout ça pour quel gain ? Oui on gagne un peu en flexibilité, mais ça ne compense pas tout le reste, et ça ne permet en rien de faire des choses qu&#8217;on ne pouvait pas faire avant.</p>
<p>Je n&#8217;ai pas vu encore la moindre utilisation des CBV qui me fasse dire, &#8220;putain c&#8217;est tellement mieux qu&#8217;avant pour cette partie&#8221;. Ni aucune lib qui me fasse dire : &#8220;ouais, on aurait pas pu le faire aussi bien avec des vues sous forme de fonctions&#8221;.</p>
<p>Avec les CBV devenant la manière par défaut de coder les vues en Django, le framework devient beaucoup moins accessible au débutant, alors que sa facilité d&#8217;usage était un de ses points forts.</p>
<p>Bref, je suis de <a href="http://www.boredomandlaziness.org/2012/05/djangos-cbvs-are-not-mistake-but.html">l&#8217;avis de Nick Coghlan</a>, les CBV ne sont pas une erreur, elles ont leur utilité, mais balancer à la poubelle les vues sous forme de fonction est une vaste connerie.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=5976&amp;md5=2006171290b5ea019c93fdd3d4ba381e" 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=6197
title: Ça ferait de très bons noms de serveur…
uri: Ça-ferait-de-très-bons-noms-de-serveur
url: http://sametmax.com/ca-ferait-de-tres-bon-nom-de-serveur/
content:
<ul>
<li>Hakuna matata</li>
<li>Yabadabadoo</li>
<li>Cowabunga</li>
<li>Scoobidoobidoo</li>
<li>Hey, Listen !</li>
<li>Fatality</li>
<li>GogoGadgeto</li>
<li>Doh</li>
<li>What&#8217;s up, doc</li>
<li>Beep-beep</li>
<li>Arriba</li>
<li>M&#8217;enfin</li>
<li>Par toutatis</li>
<li>Pas glop</li>
<li>Kamehameha</li>
<li>Fulguro point</li>
<li>Supercalifragilisticexpialidocious (ok, chiant à taper celui là)</li>
<li>Treguna, Mekoides, Trecorum, Satis, Dee (5 machines)</li>
</ul>
<p>Non ?</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6197&amp;md5=3b636cd7749c8216f6112faad037e330" 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=6204
uri: Avez-vous-une-méthode-propre-pour-jouer-avec-des-Objets-du-mode
title:
Avez vous une méthode “propre” pour jouer avec des Objets du model sans les sauvegarder en BDD sur #Django ?

url:
http://sametmax.com/avez-vous-un-methode-propre-pour-jouer-avec-des-objets-du-model-sans-les-sauvegarder-en-bdd-sur-django/

content:
<p>Mais oui <a href="https://twitter.com/CedricTouit/status/337288682803449856">cher interlocuter du Web</a>.</p>
<p>Créer un fichier &#8220;settings_test.py&#8221; à côté du fichier de settings, qui contient ça:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> settings <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
&nbsp;
DATABASES<span style="color: black;">&#91;</span><span style="color: #483d8b;">'default'</span><span style="color: black;">&#93;</span> = <span style="color: black;">&#123;</span>
    <span style="color: #483d8b;">'ENGINE'</span>: <span style="color: #483d8b;">'django.db.backends.sqlite3'</span>,
    <span style="color: #483d8b;">'NAME'</span>: <span style="color: #483d8b;">':memory:'</span>,
<span style="color: black;">&#125;</span></pre></div></div>

<p>Et lancer les commandes <code>./manage.py</code> avec <code>--settings=settings_test</code> :</p>
<p>Par exemple :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">.<span style="color: #000000; font-weight: bold;">/</span>manage.py shell <span style="color: #660033;">--settings</span>=settings_test
&nbsp;
.<span style="color: #000000; font-weight: bold;">/</span>manage.py runserver <span style="color: #660033;">--settings</span>=settings_test</pre></div></div>

<p>Et voilà, toute manipulation va automatiquement sauvegarder les données en mémoire vive, et pas dans votre base de données initiale. Elles seront perdues à chaque redémarrage.</p>
<p>D&#8217;une manière générale, souvenez vous que vous pouvez faire autant de configurations alternatives et même dynamiques que vous le souhaitez avec les fichiers de settings : c&#8217;est juste du Python.</p>
<p>Si vous avez besoin des données de votre base de données initiale, vous pouvez faire une copie de la base de données et changer <code>DATABASES</code> pour pointer sur cette copie. Du coup vous manipulerez votre copie, et pas la base de données initiale.</p>
<p>Enfin, on peut <a href="https://docs.djangoproject.com/en/dev/topics/db/multi-db/">manipuler plusieurs bases de données en même temps</a> en faisant plusieurs entrées dans <code>DATABASES</code> (une &#8216;default&#8217;, une &#8216;test&#8217;, une &#8216;prod&#8217;, etc), par exemple :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">DATABASES = <span style="color: black;">&#123;</span>
    <span style="color: #483d8b;">'default'</span>: <span style="color: black;">&#123;</span>
        <span style="color: #483d8b;">'ENGINE'</span>: <span style="color: #483d8b;">'django.db.backends.postgresql_psycopg2'</span>,
        <span style="color: #483d8b;">'USER'</span>: <span style="color: #483d8b;">'postgres'</span>,
        <span style="color: #483d8b;">'PASSWORD'</span>: <span style="color: #483d8b;">'secret of mana'</span>
    <span style="color: black;">&#125;</span>
    <span style="color: #483d8b;">'test'</span>: <span style="color: black;">&#123;</span>
    <span style="color: #483d8b;">'ENGINE'</span>: <span style="color: #483d8b;">'django.db.backends.sqlite3'</span>,
    <span style="color: #483d8b;">'NAME'</span>: <span style="color: #483d8b;">':memory:'</span>,
    <span style="color: black;">&#125;</span>
<span style="color: black;">&#125;</span></pre></div></div>

<p>On peut alors spécifier la base de données à utiliser, soit par paramètre de <code>./manage.py</code> (<code>--database=bdd_a_utiliser</code>), soit directement dans le code de manipulation de l&#8217;ORM avec <code>using</code> :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> Model.<span style="color: black;">objects</span>.<span style="color: #008000;">all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># tape dans le BDD par défaut</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> Model.<span style="color: black;">objects</span>.<span style="color: black;">using</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'test'</span><span style="color: black;">&#41;</span>.<span style="color: #008000;">all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># tape dans la bdd de test</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> mon_model.<span style="color: black;">save</span><span style="color: black;">&#40;</span>using=<span style="color: #483d8b;">'test'</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># sauvegarde dans la bdd de test</span></pre></div></div>

 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6204&amp;md5=228a632ae0f4e25fd348d43cb9d8ce66" 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=6211
title: Forcer une identity SSH pour un host en particulier
uri: Forcer-une-identity-SSH-pour-un-host-en-particulier
url: http://sametmax.com/forcer-une-identity-ssh-pour-un-host-en-particulier/
content:
<p>Vous avez accumulé un certain nombre de clés SSH, et pour certains serveur ou certains sites Web (github, bitbucket&#8230;), vous voulez utiliser une clé SSH et pas une autre. Ce serait en effet dommage de pusher votre commit Git avec la mauvaise identité.</p>
<p>Sous unix, le fichier <em>~/.ssh/config</em> est votre ami, rajoutez lui :</p>
<pre>Host Un alias pour l'host
HostName Une IP ou un nom de domaine pour l'host
User votre nom d'utilisateur
IdentityFile le fichier de clé public à utiliser
</pre>
<p>Par exemple :</p>
<pre>Host bitbucket.org
HostName bitbucket.org
User sam
IdentityFile ~/.ssh/sam.pub

Host local-dev
HostName 192.169.0.10
User dev
IdentityFile ~/.ssh/local-dev.pub</pre>
<p>On peut créer plusieurs Host pour le même hostname, avec des résultats intéressant quand on a <a href="http://sametmax.com/utiliser-deux-comptes-github-separement/">plusieurs identités en ligne</a>.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6211&amp;md5=341e7230ee7dfd3e7d2fa1a0844588eb" 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=4014
title: Plus besoin d’images pour les smileys grâce à Unicode
uri: Plus-besoin-d-images-pour-les-smileys-grâce-à-Unicode
url: http://sametmax.com/plus-besoin-dimages-pour-les-smileys-grace-a-unicode/
content:
<h2>☹</h2>
<h2>☺</h2>
<h2>☻</h2>
<p>Maintenant ça passe partout ce genre de truc. Et c&#8217;est dingue ce qu&#8217;ils ont réussi à stuffer dans cet encoding. </p>
<p>Des formes géométriques :</p>
<h2>■</h2>
<p>Des tas de faces :</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;<br />
<strong><br />
Grace au support absolument minable de l&#8217;encoding de wordpress, cet article est à moité tronqué. Merci codeur PHP de merde qui n&#8217;a jamais su gérer le texte correctement de ta putain de viiiiiiiiiiiiiiie.</p>
<p>Afin de pouvoir lire l&#8217;article en entier, je <a href="http://goo.gl/zbjJo">l&#8217;ai déporté sur 0bin</a>. Putain.</p>
<p>Moralité, non en fait on ne peut pas utiliser ces smileys partout. Les navigateurs les supportent, les fonts sont sur vos systèmes, les OS les supportent. Mais les développeurs sont toujours trop cons. 10 ans bordel, wordpress a 10 ans et des millions de users. Vous pourriez penser qu&#8217;ils font au minimum le traitement des chaînes de caractères correctement, non ? Je sais pas, un blog, le principe, c&#8217;est pas de TRAITER DU PUTAIN DE TEXTE, MERDE ? </p>
<p></strong></p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=4014&amp;md5=4fd8b1347d663ba9f17427c8602e54ca" 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=1285
title: Permettre de télécharger un fichier proprement avec Django et nginx
uri: Permettre-de-télécharger-un-fichier-proprement-avec-Django-et-nginx
url: http://sametmax.com/permettre-de-telecharger-une-fichier-proprement-avec-django-et-nginx/
content:
<p>À un moment vous allez devoir proposer à vos utilisateurs de télécharger un fichier. Mais Django n&#8217;est pas du tout fait pour streamer des données, et du coup lui laisser cette tâche est un gros gouffre à performance qui va bloquer un de vos workers pendant tout le transfert. </p>
<p>Seulement parfois, il faut quand même générer le fichier via Django, ou au moins checker des permissions, bref, faire un traitement quelconque du côté du code Python. Comment faire alors ?</p>
<p>La solution est le header <a href="http://wiki.nginx.org/X-accel">X-Accel-Redirect</a> :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">http</span> <span style="color: #ff7700;font-weight:bold;">import</span> HttpResponse
&nbsp;
<span style="color: #808080; font-style: italic;"># ici ou pourrait mettre @login_required si on veut</span>
<span style="color: #ff7700;font-weight:bold;">def</span> telecharger_fichier<span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># Faire un truc ici qui génère le fichier</span>
    <span style="color: #808080; font-style: italic;"># ou qui récupère un fichier existant.</span>
    <span style="color: #808080; font-style: italic;"># l'important est d'avoir le chemin ABSOLU du fichier</span>
    chemin_vers_fichier = get_chemin_absolu<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># On crée la réponse à la main</span>
    response = HttpResponse<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> 
&nbsp;
    <span style="color: #808080; font-style: italic;"># On laisse nginx s'occuper de détecter le mimetype</span>
    <span style="color: #ff7700;font-weight:bold;">del</span> response<span style="color: black;">&#91;</span><span style="color: #483d8b;">'content-type'</span><span style="color: black;">&#93;</span> 
    <span style="color: #808080; font-style: italic;"># On met un header que nginx va comprendre comme &quot;sert le fichier à ma place&quot;</span>
    response<span style="color: black;">&#91;</span><span style="color: #483d8b;">'X-Accel-Redirect'</span><span style="color: black;">&#93;</span> = chemin_vers_fichier
    <span style="color: #ff7700;font-weight:bold;">return</span> response</pre></div></div>

<p>Et voilà, vous pouvez plugger <code>telecharger_fichier</code> comme vue n&#8217;importe où dans <em>urls.py</em>. Quand nginx va voir <code>X-Accel-Redirect</code>, il va servir le fichier automatiquement. Django lui, n&#8217;a a gérer que cette vue très légère et passe tout de suite la main au serveur en front.</p>
<p>Afin de rendre votre setup plus sécurisé, mettez la même url que vous avez dans <em>urls.py</em> dans votre fichier de conf nginx :</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">location <span style="color: #339933;">/</span>url<span style="color: #339933;">/</span>de<span style="color: #339933;">/</span>urls.<span style="color: #660066;">py</span><span style="color: #339933;">/</span>pour<span style="color: #339933;">/</span>télécharger<span style="color: #339933;">/</span>les<span style="color: #339933;">/</span>fichiers <span style="color: #009900;">&#123;</span>
    internal<span style="color: #339933;">;</span> # interdit l<span style="color: #3366CC;">'accès au fichier depuis l'</span>exterieur du serveur
    alias <span style="color: #339933;">/</span>chemin<span style="color: #339933;">/</span>vers<span style="color: #339933;">/</span>le<span style="color: #339933;">/</span>dossier<span style="color: #339933;">/</span>contenant<span style="color: #339933;">/</span>les<span style="color: #339933;">/</span>fichiers<span style="color: #339933;">/;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Il existe d&#8217;autres headers selon les serveurs en front (WSGI, lighttpd, etc) et parfois en développement, on peut vouloir servir le fichier via Django quand même pour éviter d&#8217;installer nginx. L&#8217;application <a href="https://github.com/johnsensible/django-sendfile">django-sendfile</a> fournit des fonctions pour chacun de ces cas d&#8217;utilisations, car même si c&#8217;est facile à coder, il faut être feinéant.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=1285&amp;md5=d89f8e2409d9abd89cd1680e85233072" 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=6235
title: Life is hard and then you die
uri: Life-is-hard-and-then-you-die
url: http://sametmax.com/life-is-hard-and-then-you-die/
content:
<p>Je me baladais sur <a href="http://www.korezian.net/liens/?HykyTA">le shaarli de notre gendarme préféré</a> me que je suis tombé sur <a href="http://julienboye.com/blog/2013/5/23/2ooe2lt6m8203zj9gnhdvdh4bz9row">cet article</a> de &#8220;motivation&#8221;.</p>
<p>je suis pour un bon coup de pied au cul de temps en temps et dire la vérité en face. Les gens en ont besoin, la tendance à chercher des coupables et de l’assistance pour le moindre soucis m&#8217;agace fortement. Mais le problème c&#8217;est que ce texte, bien qu&#8217;intéressant, énonce aussi d&#8217;énormes conneries. Et sous forme de règles. <a href="http://xkcd.com/386/">Grrrrr</a>.</p>
<p>D&#8217;abord, <a href="http://julienboye.com/blog/2013/5/23/2ooe2lt6m8203zj9gnhdvdh4bz9row">il n&#8217;est pas de Bill Gates</a>, comme annoncé.</p>
<p>Et ensuite, point par point :</p>
<blockquote><p>Règle 1 : La vie est injuste : habituez vous!</p></blockquote>
<p>Non la vie n&#8217;est pas injuste, elle est ajuste. Il n&#8217;y a pas de bien et de mal. Pas de karma.</p>
<p>Personne ne va vous taper sur la tête. La plupart de vos misères, vous vous les infligez vous-même. Oui il y a des inconvenances régulières, et des catastrophes ponctuelles, mais globalement, à l&#8217;échelle d&#8217;une vie, c&#8217;est équilibré. Si ça ne l&#8217;est pas, c&#8217;est que vous ne réagissez pas assez (ou alors que statistiquement, vous avez la malchance d&#8217;être sur l&#8217;extrême de la courbe de Gauss :-p).</p>
<p>Le <em>habituez-vous</em>, c&#8217;est de la merde en boîte. Il n&#8217;y a rien à s&#8217;habituer, s&#8217;habituer c&#8217;est le contraire de la vie. La vie c&#8217;est un changement perpétuel, il faut s&#8217;adapter, pas s&#8217;habituer. Et il n&#8217;y a pas de règle, donc certainement pas d&#8217;injustice, qui suppose une &#8220;mauvaise&#8221; justice.</p>
<blockquote><p>Règle 2 : Le monde se fout de votre amour-propre.<br />
Le monde s&#8217;attendra à ce que vous accomplissiez quelque chose AVANT que vous ne vous félicitiez vous-même.</p></blockquote>
<p>Le monde ne s&#8217;attend à rien du tout. Le monde s&#8217;en branle. Et la notion d&#8217;accomplissement n&#8217;a aucun sens. En tout cas pas d&#8217;autre que celui que vous lui donnez.</p>
<p>On n&#8217;est pas dans une série américaine avec les &#8220;winners&#8221; d&#8217;un côté qui accomplissent, et les autres.</p>
<p>On est juste tous des survivants, en sursis qui plus est, et chacun comme on peut.</p>
<blockquote><p>
Règle 3 : Vous ne gagnerez pas $60,000 par an en sortant de l&#8217;école.<br />
Vous ne serez pas vice-président en commençant, avec GSM et voiture de fonction fournis, avant d&#8217;avoir mérité, gagné ces privilèges.</p></blockquote>
<p>Je vois l&#8217;idée, mais la conclusion a un arrière goût de pourri.</p>
<p>Ceux qui on ces privilèges (mais en sont-ce ?) ne les ont en rien mérité. D&#8217;abord parce que notre monde récompense (avec ces &#8220;privilèges&#8221; en tout cas) les meilleurs marchands et créateurs de réseaux, pas les meilleures personnes. Et ensuite parce que même si vous pouviez les obtenir en vous donnant à fond, aucune somme de travail d&#8217;une personne ne justifie qu&#8217;elle accumule la valeur du travail de centaines d&#8217;autres pour son usage personnel. Quand vous êtes blindés, vous ne l&#8217;avez pas mérité. Ça ne fait pas de vous une mauvaise personne. Ça ne veut pas dire que vous ne pouvez pas ou ne devez pas profiter de votre argent. Mais prétendre l&#8217;avoir mériter, ça n&#8217;a aucun sens.</p>
<p>Il y a de tas de personne qui sont plus belles, plus compétentes, plus travailleuses que l&#8217;auteur et qui gagnent le SMIC. L&#8217;univers se fout du mérite. Le mérite est une notion humaine, et qui suppose le proportionnalité. La richesse n&#8217;est pas proportionnel à l&#8217;accomplissement d&#8217;un homme. Si on prend un homme riche et qu&#8217;on déplace sa naissance 10 ans avant ou après dans le temps, si on le fait naitre dans un autre pays, d&#8217;un autre sexe, dans une autre famille ou même juste d&#8217;une autre religion, il ne devient plus riche. Il est devenu riche dans un contexte. Sa personnalité n&#8217;est qu&#8217;une composante, influente mais petite, de ce contexte.</p>
<blockquote><p>Règle 4 : Si vous croyez que votre professeur est dur avec vous, attendez d&#8217;avoir un patron.
</p></blockquote>
<p>D&#8217;abord, il y a des tas de patrons très sympas. Qu&#8217;est-ce que c&#8217;est encore que cette mentalité à la noix de placer le patron comme une figure autoritaire exigeante qui projette ses sauts d&#8217;humeurs de connard sur ses employés ?</p>
<p>Ensuite, vous pouvez choisir votre job, un job dans lequel vous êtes bons et qui vous intéresse, alors que les matières à l&#8217;école (et l&#8217;école en générale) vous sont imposées. </p>
<p>Et vous êtes payés pour ça. Et si votre patron est con, vous pouvez en changer. On est pas esclaves dans une usine Apple en Chine.</p>
<p>Le monde du travail est par bien des aspects plus simple que l&#8217;école. Essayez de vous souvenir de votre enfance, bordel. L&#8217;école c&#8217;était difficile, l&#8217;environnement social laisse peu de place aux erreurs, et on les paye sur des années. La somme de travail est importante, et pas toujours gratifiante. Les profs ne sont pas tous bienveillants. L&#8217;école, ce n&#8217;est pas l&#8217;île aux enfants.</p>
<p>Oui on peut se toucher à l&#8217;école et c&#8217;est vrai qu&#8217;il y a plein de protections pour les enfants, et qu&#8217;ils se plaingnent souvent de non-problèmes car ils ont besoin de se construire. Mais nier la difficulté de l&#8217;école, c&#8217;est faire l&#8217;autruche.</p>
<blockquote><p>Règle 5 : Travailler dans une friterie n&#8217;est pas s&#8217;abaisser. Vos grands-parents avaient un mot différent pour ça : ils l&#8217;appelaient une opportunité.</p></blockquote>
<p>On se retrouve sur ce point. J&#8217;aime les friteries. Si j&#8217;en veux, j&#8217;ai besoin de gens qui travaillent dans les friteries. Donc je respecte les gens qui travaillent dans les friteries. Et ce respect passe par le fait que j&#8217;accepte de travailler dans une friterie. J&#8217;ai travaillé dans les bars / restaurants / champs / usines avant de trouver ma voie. C&#8217;est important de donner du crédit à tous ces métiers car nous consommons leurs produits.</p>
<p>Après, il est tout aussi important de choisir le plus possible un métier qui vous plait. Et non, travailler dans une friterie ne me plait pas.</p>
<blockquote><p>Règle 6 : Si vous gaffez, CE N&#8217;EST PAS LA FAUTE DE VOS PARENTS, arrêtez de chialer et apprenez de vos erreurs.</p></blockquote>
<p>Arrêtez de chialer, oui. </p>
<p>Personnellement je n&#8217;entends pas souvent des gosses dire que leurs échecs sont la faute de leurs parents, mais admettons.</p>
<p>Ce qui me gène, c&#8217;est nier la faute des parents. Les parents modèlent votre vie que vous le vouliez ou non, et une grande partie de vos tares sont directement liées au fait qu&#8217;ils vous ont élevé : vos peurs, vos doutes, vos incapacités ont tout à voir avec vos parents. Pas seulement. Mais énormément.</p>
<p>Comme en plus ils sont votre première et plus importante échelle de valeurs quand vous êtes momes, c&#8217;est eux qui vous balancent les fameux critères de réussite dont j&#8217;ai parlé plus haut.</p>
<p>Faut-il leur en vouloir ? Inutile et contre productif.</p>
<p>Faut-il se reposer sur cette idée pour s&#8217;excuser de merder ? Non, bouge ton cul.</p>
<p>Mais il est temps de re-responsabiliser les parents : faire un môme, c&#8217;est prendre la responsabilité d&#8217;une vie. Oui, vous pouvez le bousiller. De très très très nombreux parents transmettent leurs névroses, et d&#8217;autres trucs graves, par le simple fait d&#8217;exister au contact de leurs enfants.</p>
<p>Les parents sont souvent de pitoyable adultes.</p>
<p>Et visiblement, ce que je lis dans ce texte, c&#8217;est un parent qui a des gosses en difficultés et qui écrit un article à ce sujet, sans jamais se remettre en question. Mec, tu te dis pas que tu as peut être et avant tout raté le coche quelque part ? Les gosses qui sont nuls en tout et se plaignent tout le temps par nature, ça n&#8217;existe pas. Ça le devient.</p>
<p>P.S: j&#8217;aime beaucoup mes parents.</p>
<blockquote><p>
Règle 7 : Avant que vous naissiez, vos parents n&#8217;étaient pas aussi ennuyants qu&#8217;ils le sont maintenant !<br />
Ils sont devenus comme ça :<br />
* En payant vos factures,<br />
* En nettoyant vos vêtements<br />
* Et en vous entendant répéter sans arrêt combien vous êtes bons et cools.<br />
Ainsi, avant de sauver les forêts tropicales des parasites de la génération de vos parents, commencez donc par faire le ménage dans votre propre chambre et tout ce qui s&#8217;y trouve</p>
</blockquote>
<p>Qu&#8217;est-ce que ça vient foutre la dedans ? Petit moment de frustration avec tes enfants, man ?</p>
<p>Tous les mômes trouvent leurs parents ringards ou gênants, ou les deux.</p>
<p>Le boulot de parent est un boulot ingrat. On torche les gosses. On casque pour eux. Et on a rarement un merci. </p>
<p>Qu&#8217;est-ce qu&#8217;on s&#8217;en branle ? Tu as pas fais des enfants pour qu&#8217;ils te pumped up ton égo quand même ? </p>
<p>Ce sont des gamins, bien sur qu&#8217;ils sont égoïstes et qu&#8217;ils n&#8217;ont aucun sens des réalités. Ils débutent dans la vie. Oui, à la sortie de l&#8217;université, on est encore un gamin. Y a rien de mal à ça.</p>
<p>Pauvre bichou. Aller, viens faire un câlin.</p>
<blockquote><p>
Règle 8 : Votre école s&#8217;est peut-être débarrassé du système « gagnant-perdant », PAS LA VIE !<br />
Dans certaines écoles, on a aboli les notes de passage et on vous donne autant de chances que vous voulez pour obtenir la bonne réponse.<br />
Ceci n&#8217;existe pas dans la vraie vie !</p></blockquote>
<p>Si. Justement. La vie n&#8217;a pas de gagnant ou de perdant.</p>
<p>La vie n&#8217;a pas de note.</p>
<p>Ce sont les humains qui jugent si on a réussi ou pas. C&#8217;est une notion humaine qui change d&#8217;un lieu à l&#8217;autre, d&#8217;une culture à l&#8217;autre, d&#8217;une période de l&#8217;histoire à l&#8217;autre, d&#8217;un groupe social à l&#8217;autre&#8230;</p>
<p>La vie s&#8217;en tamponne le coquillard avec une patte d&#8217;astrakan femelle.</p>
<p>Les notes ne sont pas censées être une évaluation pour permettre au gens de &#8220;passer&#8221; un truc. C&#8217;est censé donner aux gens une échelle pour savoir où ils en sont dans leurs objectifs d&#8217;apprentissage. Le problème c&#8217;est que plus personne ne les utilise comme ça : on assiste à un combat entre étudiants et enseignants avec notes interposées, avec la société (et les parents en première ligne) qui juge sur cette échelle de valeur. On ne cherche pas à apprendre, mais à passer, ou à devenir le meilleur.</p>
<p>Le &#8220;meilleur&#8221; est une notion humaine.</p>
<p>Pour la vie, la seule sanction c&#8217;est la survie ou la mort, et dans nos sociétés de riches, ceux qui vont à l&#8217;école n&#8217;ont pas cette épée de Damoclès au dessus de la tête. Pour les autres, c&#8217;est un problème qui n&#8217;a rien à voir avec cet article.</p>
<p>Réfléchir comme ça, c&#8217;est créer des générations de frustrés qui vont se battre pour &#8220;attrapez les tous&#8221; et &#8220;devenir le meilleur dresseur&#8221;. Personne n&#8217;est heureux comme ça.</p>
<p>Le fric faisant maintenant office de note générique, le bulletin de notes et ses conséquences idiotes dépassent de loin le cadre de l&#8217;école. C&#8217;est ridicule.</p>
<p>Un système de compétition n&#8217;est pas une mauvaise chose. Une carotte n&#8217;est pas une mauvaise chose. Un statut, de l&#8217;abondance ne sont pas des mauvaises choses. Mais cette arrogance de jeter l’opprobre sur ceux qui n&#8217;atteignent pas le sommet de cette échelle artificielle et temporaire, c&#8217;est complètement con. Les humains ne sont pas fait pour être au service d&#8217;un type de société en particulier et s&#8217;y tenir. L&#8217;humanité grandit organiquement, et ses accomplissement dépassent largement cette vision réductrice. Il n&#8217;y a pas que ton système, monseigneur. On peut faire plus. Et différemment. On a besoin des artistes, des humanistes, des gens qui prennent leur temps, des gens humbles, des gens qui font le pont entre les groupes sociaux, des pères et mères qui veulent peu travailler pour s&#8217;occuper des mômes, des philosophes, des chercheurs, des inventeurs, des transgresseurs, des engagés et de ceux qui creusent leur spiritualité. Pas juste des producteurs, des business man, et de ceux qui font plus et plus vite, et que l&#8217;on qualifie aujourd&#8217;hui de &#8220;gagnant&#8221;.</p>
<p>On a besoin d&#8217;eux aussi. J&#8217;aime avoir de l&#8217;argent. J&#8217;aime quand quelqu&#8217;un fait de grandes choses grâce à la puissance que lui donne l&#8217;argent. Mais ce n&#8217;est pas une échelle de valeur saine. Tout au plus un indicateur d&#8217;état.</p>
<blockquote><p>Règle 9 : La vie n&#8217;est pas divisée en semestres.<br />
L&#8217;été n&#8217;est pas une période de congé.<br />
Et très peu d&#8217;employeurs sont disposés à vous aider à VOUS ASSUMER, c&#8217;est votre responsabilité.</p></blockquote>
<p>Bon +1. Et je rajouterais, les WE, les jours fériés, Noël et la fête des mères n&#8217;existent pas. Ce sont des conventions sociales, utiles pour interagir avec les autres, mais c&#8217;est tout. Faites votre propre calendrier. </p>
<p>Au passage, vous êtes tout seul. L&#8217;entraide, c&#8217;est bien, mais ne comptez pas dessus par défaut. C&#8217;est un bonus. Assumez-vous.</p>
<blockquote><p>Règle 10 : La télévision n&#8217;est pas la «vraie vie».<br />
Dans la vraie vie, les gens quittent le café et vont travailler.</p></blockquote>
<p>Débranchez la télévision (vendez la chez cash express). Mais allez travailler de temps à autre dans un café. Ça vous fera du bien.</p>
<p>Si votre métier ne vous le permet pas, à la sortie du boulot, allez au café avec vos collègues. Le distributeur d&#8217;erzatz du boulot, ce n&#8217;est PAS la même chose.</p>
<blockquote><p>Si vous êtes d&#8217;accord, faites circuler, sinon, mettez-vous la tête dans le sable et prenez une grande respiration</p></blockquote>
<p>J&#8217;adore l&#8217;humilité qui transpire de cette conclusion. Que tout ceux qui ne sont pas d&#8217;accord avec moi aillent se faire foutre !</p>
<p>Ça, ça va me convaincre de la puissance de tes arguments.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6235&amp;md5=c59e470bdd7eb9fbd641bc470ee484cc" 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=6254
title: Nouveau modèle de fichier Python
uri: Nouveau-modèle-de-fichier-Python
url: http://sametmax.com/nouveau-modele-de-fichier-python/
content:
<p>Il fallait bien s&#8217;y mettre un jour. Dans un an Python 3 sera probablement assez mûr et répandu pour envisager un switch. Du coup j&#8217;ai changé mon modèle de fichier Python vide, il ressemble dorénavant à ceci :</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>
<span style="color: #808080; font-style: italic;"># vim: ai ts=4 sts=4 et sw=4 nu</span>
&nbsp;
&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></pre></div></div>

<p>Tous mes nouveaux modules Python avait déjà par défaut les 3 premières (exécutable sous Unix, encodé en UTF8 et avec une indentation de 4 espaces sous VI). En prime maintenant :</p>
<ul>
<li>Toutes les chaînes sont automatiquement de l&#8217;<a href="sametmax.com/lencoding-en-python-une-bonne-fois-pour-toute/">unicode</a>.</li>
<li>Les imports sont absolus par défaut. Il faut forcer l&#8217;<a href="http://sametmax.com/les-imports-en-python/">import relatif</a>.</li>
<li>La division ne tronque pas. Pour obtenir l&#8217;ancien comportement, il faut utiliser <code>//</code>.</li>
<li><code>print()</code> est forcé d&#8217;être une fonction (snif).</li>
</ul>
<p>Je me dédinausorise petit à petit.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6254&amp;md5=4cdeea134c47d0237d9867da02be0578" 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=6260
title: Max se barre
uri: Max-se-barre
url: http://sametmax.com/max-se-barre/
content:
<p>Marre de voir 70% (sic) de son CA partir en fumée depuis 7 ans, notre Max va s&#8217;exiler dans des terres plus gentilles avec les PME.</p>
<p>Rassurez-vous, il ne quitte pas le blog, et j&#8217;irai lui rendre visite, mais je ne pourrai plus squatter sur son canapé en cas de coup dur. Snif.</p>
<p>Histoire de se fendre un peu la gueule, voici ce qu&#8217;on a trouvé en vidant ses tiroirs:</p>
<div id="attachment_6261" class="wp-caption aligncenter" style="width: 601px"><a href="media/143b9eed.DSC00018.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/05/DSC00018.jpg"><img class=" wp-image-6261  " title="C'est l'histoire de la viiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiie" src="media/143b9eed.DSC00018.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/05/DSC00018.jpg" alt="Photo d'affaires dans un déménagement" width="591" height="394" /></a><p class="wp-caption-text">C&#39;est l&#39;histoire de la viiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiie</p></div>
<p>&nbsp;</p>
<p>Comme je suis un photographe pitoyable vous ne pouvez pas voir que le portefeuille est plein de bahts, que l&#8217;hélico est pété en deux et qu&#8217;il y a un équipement de chasse-d&#8217;eau non déballé dans le fond :-)</p>
<p>&nbsp;</p>
<div id="attachment_6263" class="wp-caption aligncenter" style="width: 601px"><a href="media/e93eb32e.DSC000191.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/05/DSC000191.jpg"><img class=" wp-image-6263  " title="N'avez-vous  pas un souvenir ému en voyant cette petite disquette Voyetra ?" src="media/e93eb32e.DSC000191.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/05/DSC000191.jpg" alt="Photo d'affaires récupérées dans un déménagment" width="591" height="394" /></a><p class="wp-caption-text">N&#39;avez-vous pas un souvenir ému en voyant cette petite disquette Voyetra ?</p></div>
<p>Comme dirais Max &#8220;t&#8217;es en surex là&#8221;. Et comme je lui ai répondu: &#8220;merde !&#8221;. Mais sur votre gauche vous verrez une souris dite &#8220;ergonomique&#8221;, c&#8217;est à dire inutilisable, au centre un point mister pizza gardé &#8220;au cas où&#8221; surplombé d&#8217;un cable Mac à 2000 euros le centimètre jamais déballé car ce n&#8217;est pas le bon (il en a 3). Sur votre droite, vous ne pouvez pas admirer une DS customisée avec des petits stickers trop choupinets ! Et une vache  et un PQ. Logique.</p>
<p>Ah, comme le tampax&#8230;</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6260&amp;md5=38b892f08167c6146b029ff1e099d099" 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=6276
title: Nouveau modèle économique
uri: Nouveau-modèle-économique
url: http://sametmax.com/nouveau-modele-economique/
content:
<p>Je suis sûr qu&#8217;il y a un truc à creuser. Non ?</p>
<div id="attachment_6277" class="wp-caption aligncenter" style="width: 610px"><a href="media/f4738736.nouveau-model-economique.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/05/nouveau-model-economique.jpg"><img class="size-full wp-image-6277" title=":-)" src="media/f4738736.nouveau-model-economique.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/05/nouveau-model-economique.jpg" alt="Photo d'une femme nue censurée par des logos de navigateurs" width="600" height="359" /></a><p class="wp-caption-text">:-)</p></div>
<p>Avec Opéra c&#8217;est rigolo aussi.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6276&amp;md5=6388119afcdf3eaa25fcccb5179e882b" 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=3972
title: Créer un bookmarklet
uri: Créer-un-bookmarklet
url: http://sametmax.com/creer-un-bookmarklet/
content:
<p>Vous avez un super outil JS que vous voulez partager avec le monde entier ? Faites un bookmarklet ! Il s&#8217;agit de compresser tout votre code sur une ligne de telle sorte qu&#8217;il puisse être mis en bookmark dans le browser et utilisé en un clic.</p>
<p>Problème : débugger un pâté de JS d&#8217;une ligne, c&#8217;est relou. Et pour les gros outils, il n&#8217;y a pas la place de toute coder. L&#8217;idée est donc de packer juste l&#8217;import de votre outil.</p>
<p>D&#8217;abord, mettre le script de votre outil quelque part (par exemple votre serveur Web). Pour l&#8217;article, je vais mettre le script sur <a href="http://yourjavascript.com">yourjavascript.com</a>.</p>
<p>Il <a href="http://yourjavascript.com/11356413275/test.js">affiche une des tag lines du blog avec clippy</a> (on m&#8217;avait demandé une fois comment on faisait, ben voilà). Il ne marche que sur le blog et tout en haut à gauche d&#8217;une page non scrollée, mais OSEF, c&#8217;est un exemple.</p>
<p>Ensuite, on fait le code d&#8217;include, qui va juste créer une balise SCRIPT et ajoute votre outil une fois que la page est chargée :</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// on frabrique le tag SCRIPT</span>
<span style="color: #003366; font-weight: bold;">var</span> url <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;http://yourjavascript.com/11356413275/test.js&quot;</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> head <span style="color: #339933;">=</span> document.<span style="color: #660066;">getElementsByTagName</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'head'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> script <span style="color: #339933;">=</span> document.<span style="color: #660066;">createElement</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'script'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
script.<span style="color: #660066;">type</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'text/javascript'</span><span style="color: #339933;">;</span>
<span style="color: #006600; font-style: italic;">// on met la date dans l'url pour éviter le cache</span>
script.<span style="color: #660066;">src</span> <span style="color: #339933;">=</span> url <span style="color: #339933;">+</span> <span style="color: #3366CC;">'?'</span> <span style="color: #339933;">+</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">new</span> Date<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">getTime</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #006600; font-style: italic;">// on ajoute le tag ce qui va charger votre outil</span>
head.<span style="color: #660066;">appendChild</span><span style="color: #009900;">&#40;</span>script<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Puis il faut le mettre au format bookmarklet, c&#8217;est à dire :</p>
<ul>
<li>Faire tenir le code sur une ligne.</li>
<li>L&#8217;enfermer dans une <a href="http://sametmax.com/la-fonction-anonyme-appelee-immediatement-en-javascript-function/">fonction appelée immédiatement</a>.</li>
<li>Transformer tout ça en URL (urlencoder + ajouter le protocole &#8220;javascript:&#8221;)</li>
</ul>
<p>Faites le une fois pour vous entraîner à comprendre ce qui se passe (avec un code plus simple, genre un <code>alert()</code>) :</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">javascript<span style="color: #339933;">:</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;test&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span></pre></div></div>

<p>Ensuite faites le avec votre vrai code, encore à la main. Une fois. Vous noterez qu&#8217;il faut un code super propre (pas de &#8220;;&#8221; manquant) pour que ça marche.</p>
<p>Quand vous en aurez marre de galérer, vous ferez comme moi, vous utiliserez un <a href="http://chriszarate.github.io/bookmarkleter/">outil en ligne</a> pour le faire automatiquement.</p>
<p>Le code résultant est celui-ci:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">javascript<span style="color: #339933;">:</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>var<span style="color: #339933;">%</span>20url<span style="color: #339933;">=%</span>22http<span style="color: #339933;">:</span><span style="color: #006600; font-style: italic;">//yourjavascript.com/11356413275/test.js%22;var%20head=document.getElementsByTagName('head')[0];var%20script=document.createElement('script');script.type='text/javascript';script.src=url+'%3F'+(new%20Date().getTime());head.appendChild(script);})();</span></pre></div></div>

<p>On peut le mettre directement à la place de l&#8217;URL HTTP dans un bookmark. Si on clique sur le bookmark, il va lancer ce code, qui va ajouter la balise SCRIPT avec mon autre code, qui va se lancer et faire apparaitre clippy pour notre plus grand plaisir.</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="100%" height="300" src="http://jsfiddle.net/ngxuC/2/embedded/result,html/presentation/" allowfullscreen="allowfullscreen" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<p>Comme je suis une feignasse, clippy apparait en haut de la page, donc il vous faudra scroller tout en haut pour voir le résultat. J&#8217;avais pas envie de me taper les calculs pour faire une posionnement relatif au viewport.</p>
<p>Personnellement je m&#8217;en sers pour faire des petits outils comme lire des sites plein d&#8217;images en mettant toutes les images à la suite des autres en auto loading, pour charger des outils d&#8217;admin sur la page principale d&#8217;un site (genre le casting des videos pornos) ou juste debugger.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=3972&amp;md5=b13c1289c759008fa99c902d3c28840d" 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=6288
title: Mon environnement de travail
uri: Mon-environnement-de-travail
url: http://sametmax.com/mon-environnement-de-travail/
content:
<p>En informatique, on passe beaucoup de temps à tester des logiciels, encore plus dans le monde du libre, pour trouver celui qui va être le plus adapté à ses besoins.</p>
<p>Du coup, partager sa config peut vraiment faire gagner beaucoup de temps à d&#8217;autres pour la découverte. Et je suis sûr que les comments vont être spammés de &#8220;moi j&#8217;utilise X&#8221;, ce qui pourrait nous faire connaître encore plus de truc.</p>
<p>Réfrénez-vous quand même de vendre ArchLinux / BSD, vim / emacs en comments. On sait que ça existe. On sait pourquoi vous les utilisez. Ca a été dit.</p>
<h2>Boulot</h2>
<h3>Ubuntu 12.04 LTS</h3>
<p>Bon, on commence par le banale, mais c&#8217;est mon OS principal. Je reste sur la LTS pour la stabilité, j&#8217;utilise Unity par goût, et occasionnellement Gnome Shell pour rester à la page.</p>
<p>J&#8217;ai un dual boot avec Windows 7 afin de pouvoir tester les sites sous IE. Et jouer à League of Legend. Mais c&#8217;est un détail.</p>
<h3>Sublime Text et quelques autres</h3>
<p>Tout le monde sait qu&#8217;on est des <a href="http://sametmax.com/liste-des-plugins-sublime-text-que-jutilise/">fans de ST</a> sur ce blog, mais pas que. J&#8217;utilise massivement vi (par paresse de toucher la souris quand je suis dans un shell, ou en remote) et un peu gedit pour des tâches très spécifiques.</p>
<p>Pour Python spécifiquement j&#8217;utilise dreampie et reinteract dans le cadre des formations.</p>
<div id="attachment_6312" class="wp-caption aligncenter" style="width: 503px"><a href="media/d8ca9711.DreamPie_013.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/DreamPie_013.jpg"><img class=" wp-image-6312 " title="Dreampie est pas mal pour montrer un gros bloc de code d'un coup qu'on execute et modifie puis relance" src="media/d8ca9711.DreamPie_013.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/DreamPie_013.jpg" alt="Capture d'écran du logiciel Dreampie" width="493" height="359" /></a><p class="wp-caption-text">Dreampie est pas mal pour montrer un gros bloc de code d&#39;un coup qu&#39;on execute et modifie puis relance</p></div>
<div id="attachment_6313" class="wp-caption aligncenter" style="width: 490px"><a href="media/ff0d3573.reinteract.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/reinteract.jpg"><img class=" wp-image-6313 " title="Reinteract est pas mal pour montrer la construction d'un script et le modifier par petit bouts tout en voyant l'évolution. Mais il est assez buggé." src="media/ff0d3573.reinteract.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/reinteract.jpg" alt="Capture d'écran du logiciel Reinteract" width="480" height="336" /></a><p class="wp-caption-text">Reinteract est pas mal pour montrer la construction d&#39;un script et le modifier par petit bouts tout en voyant l&#39;évolution. Mais il est assez buggé.</p></div>
<h3>Guake</h3>
<p><a href="http://guake.org/">Guake</a> est un terminal drop down, c&#8217;est à dire que je l&#8217;ai réglé pour qu&#8217;il apparaisse en glissant du haut de mon écran quand j’appuie sur la touche <kbd>²</kbd>, ce qui fait que j&#8217;ai toujours un shell sous la main. Il gère les tabs et la transparence, mais pas les profiles avancés ni les écrans splittés.</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="560" height="315" src="http://www.youtube.com/embed/kHrIXQNY8VE#t=198s" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<p>J&#8217;attends beaucoup de <a href="http://www.webupd8.org/2013/03/terra-terminal-update-brings-improved.html">Terra</a> pou combler ces manques, que j&#8217;essaye en ce moment. Oui, j&#8217;ai essayé TOUS vos terminaux alternatifs. Tous.</p>
<h3>Git</h3>
<p>Directement en ligne de commande. Je n&#8217;utilise aucun autre client. Git reste mon logiciel de gestion de source favoris, après avoir essayé HG, bazar et SVN, mais j&#8217;utilise ces derniers quand même pour des raisons professionnelles de temps à autre.</p>
<p><a href="http://sametmax.com/scm-breeze-facilite-la-selection-de-vos-fichiers-a-commiter-sous-git-avec/">scm_breeze</a> aide tout de même beaucoup à l&#8217;usage. Si j&#8217;étais sous un autre OS j&#8217;utiliserais probablement le <a href="http://windows.github.com/">client de Github</a>.</p>
<h3>Le package Python habituel</h3>
<p><a href="http://sametmax.com/nouvelle-config-ipython/">iPython</a> + <a href="http://sametmax.com/votre-python-aime-les-pip/">Pip</a> + <a href="http://sametmax.com/les-environnement-virtuels-python-virtualenv-et-virtualenvwrapper/">virtualenv</a> +<a href="http://sametmax.com/sept-petites-libs-qui-changent-la-vie-dun-dev-python/"> un tas de libs</a></p>
<p>Là on va pas rentrer dans les détails, si ce n&#8217;est que je n&#8217;utilise presque jamais les versions deb des libs Python, que bpython ne m&#8217;a pas convaincu et que je déteste buildout qui a la simplicité de tous les outils issus de Zope.</p>
<div id="attachment_6293" class="wp-caption aligncenter" style="width: 496px"><a href="media/40c685e8.nautilus.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/nautilus.jpg"><img class=" wp-image-6293 " title="Les modèles Nautilus, un vrai bonheur" src="media/40c685e8.nautilus.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/nautilus.jpg" alt="Capture d'écran d'un clic droit montrant le menu des modèle nautilus" width="486" height="343" /></a><p class="wp-caption-text">Les modèles Nautilus, un vrai bonheur</p></div>
<h3>Grin (et grep)</h3>
<p>J&#8217;en ai déjà parlé <a href="http://sametmax.com/grin-le-grep-python-sous-steroid/">ici</a>. Sublime Text fournis cette fonction en standard, mais je trouve grin plus lisible et flexible. Ou alors j&#8217;ai des habitudes de vieux con.</p>
<h3>Regexxer</h3>
<p>C&#8217;est du search and replace dans tout un projet. <a href="http://regexxer.sourceforge.net/">Simple et efficace. </a></p>
<div id="attachment_6294" class="wp-caption aligncenter" style="width: 480px"><a href="media/fac98924.regexxer.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/regexxer.jpg"><img class=" wp-image-6294  " title="Search and destroyyyyyyyyyyyyyyyy" src="media/fac98924.regexxer.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/regexxer.jpg" alt="Capture d'écran du logiciel regexxer" width="470" height="268" /></a><p class="wp-caption-text">Search and destroyyyyyyyyyyyyyyyy</p></div>
<h3>Meld</h3>
<p>Mon outil de comparaison de fichier par défaut, git est <a href="http://nathanhoad.net/how-to-meld-for-git-diffs-in-ubuntu-hardy">réglé</a> pour l&#8217;utilisr, j&#8217;ai un add-on nautilus pour le proposer en clic-droit.</p>
<div id="attachment_6296" class="wp-caption aligncenter" style="width: 480px"><a href="media/1f31b2e8.meld.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/meld.jpg"><img class=" wp-image-6296  " title="Il manque à Meld une meilleure intégration au VCS en cours, mais ça reste un bel outil. Écrit en Python :-)" src="media/1f31b2e8.meld.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/meld.jpg" alt="Capture d'écran du logiciel meld en train d'éditer le code de 0bin" width="470" height="268" /></a><p class="wp-caption-text">Il manque à Meld une meilleure intégration au VCS en cours, mais ça reste un bel outil. Écrit en Python :-)</p></div>
<div id="attachment_6295" class="wp-caption aligncenter" style="width: 420px"><a href="media/f3924c81.compare-with-meld.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/compare-with-meld.jpg"><img class=" wp-image-6295" title="Une des raisons qui font que je ne passe pas en 13.04: les plugins de Nautilus sont incompatibles" src="media/f3924c81.compare-with-meld.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/compare-with-meld.jpg" alt="Capture d'écran de clic droit sur nautilus montrant &quot;compare with meld&quot;" width="410" height="461" /></a><p class="wp-caption-text">Une des raisons qui font que je ne passe pas en 13.04: les plugins de Nautilus sont incompatibles</p></div>
<p><a href="http://doc.ubuntu-fr.org/meld">Doc Ubuntu sur le Meld</a>.</p>
<p>Parfois sur le serveur je suis contraint d&#8217;utiliser vimdiff.</p>
<h3>GTG</h3>
<p>Todo list flexible et simple. En plus c&#8217;est pondu par <a href="http://ploum.net/post/gtg-0-2-9">ploum</a>.</p>
<div id="attachment_6297" class="wp-caption aligncenter" style="width: 564px"><a href="media/daeddf54.gtg.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/gtg.jpg"><img class=" wp-image-6297 " title="J'ai eu ma période David Allen + LifeHacker " src="media/daeddf54.gtg.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/gtg.jpg" alt="Capture d'écran du logiciel Getting Things Gnome" width="554" height="331" /></a><p class="wp-caption-text">J&#39;ai eu ma période David Allen + LifeHacker</p></div>
<h3>Redshift</h3>
<p>Max vous en a parlé <a href="http://sametmax.com/redshift-f-lux-pour-eviter-de-sexploser-le-yeux-devant-lordi/">ici</a>, ça sert essentiellement à pas se tuer les yeux quand on passe ses journées sur un écran.</p>
<h3>Skype + Pidgin + Thunderbird</h3>
<p>J&#8217;ai horreur de skype, mais c&#8217;est le seul truc en VOIP que je peux utiliser avec mes clients. Ils ne connaissent rien d&#8217;autre. Hyper relou, car c&#8217;est une bouse infame, lente et instable, et un gros spyware en prime. Je cherche toujours un moyen de m&#8217;en séparé puisque j&#8217;ai réussi à viré mes comptes Google, ça doit être possible sur le long terme.</p>
<p><a href="http://www.pidgin.im/">Pidgin </a>est le seul logiciel d&#8217;IM multiprotocole (ert multiplateforme) potable qui gère <a href="http://www.cypherpunks.ca/otr/">OTR</a>. Je vire toujours empathy d&#8217;Ubuntu, c&#8217;est absolument useless ce truc.</p>
<p>Thunderbird, parce ce que c&#8217;est le pire à l&#8217;exception de tous les autres. Et <a href="http://www.enigmail.net/home/index.php">enigmail</a> marche bien. J&#8217;espère que Postler et Geary vont évoluer dans le bon sens, je les surveille régulièrement.</p>
<h3>Liferea</h3>
<p>Le client Web, c&#8217;est pas pour moi. Il faudrait un client Web qui soit aussi intégré à l&#8217;OS et demande pas de setup. Faudra que je code ça un jour (car franchement l&#8217;explosion des clients Web que je lis dans le flux de Sebsauvage ne me donne pas envie).</p>
<p>En attendant, <a href="http://lzone.de/liferea/">liferea</a> fait ma revue quotidienne.</p>
<div id="attachment_6298" class="wp-caption aligncenter" style="width: 479px"><a href="media/ecbc38e8.Liferea_006.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/Liferea_006.jpg"><img class=" wp-image-6298  " title="Depuis la dernière version, Liferea ne freeze plus au reload de tous les flux. C'est pas trop tôt." src="media/ecbc38e8.Liferea_006.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/Liferea_006.jpg" alt="Capture d'écran du logiciel Liferea" width="469" height="268" /></a><p class="wp-caption-text">Depuis la dernière version, Liferea ne freeze plus au reload de tous les flux. C&#39;est pas trop tôt.</p></div>
<h3>Truecrypt (et GPG)</h3>
<p>J&#8217;ai fais <a href="http://sametmax.com/eviter-davoir-la-queue-a-lair-en-publique-avec-truecrypt/">un article sur Truecrypt</a>, je met tout dedans : clés SSH, mails, photos de mes copines à poil, etc.</p>
<p>Quand à GPG, pour le moment c&#8217;est surtout pour discuter avec mes potes paranos en chiffré, mais je sens que je fais l&#8217;utiliser de plus en plus. Internet est trop surveillé, ça devient n&#8217;importe quoi. Prochaine étape, le VPN systématique.</p>
<h3>Gimp (et shutter)</h3>
<p>Pour retoucher les photos (ou faire des faux documents ^^), j&#8217;utilise The Gimp. Le <a href="http://askubuntu.com/questions/136992/how-to-make-gimp-run-as-a-single-window">mode fenêtré</a> le rend vachement plus pratique.</p>
<p>Vous connaissez sans doute moins <a href="http://doc.ubuntu-fr.org/shutter">shutter </a>: c&#8217;est un logiciel pour faire des captures d&#8217;écran très avancé qui possède moult options et en prime un éditeur d&#8217;image intégré super pratique.</p>
<div id="attachment_6299" class="wp-caption aligncenter" style="width: 495px"><a href="media/410f8705.shutter.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/shutter.jpg"><img class=" wp-image-6299 " title="Software inception. D'ailleurs le flou est aussi rajouté avec Shutter." src="media/410f8705.shutter.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/shutter.jpg" alt="Capture d'écran du logiciel Shutter" width="485" height="317" /></a><p class="wp-caption-text">Software inception. D&#39;ailleurs le flou est aussi rajouté avec Shutter.</p></div>
<h3>SSHplus</h3>
<p>En gros, c&#8217;est un <a href="http://astuces.absolacom.com/ubuntu/sshplus-le-sshmenu-pour-unity/">menu docké</a> en haut de l&#8217;écran qui permet de lancer des commandes arbitraires. Je m&#8217;en sers pour ouvrir un nouvel onglet dans guake et me connecter automatiquement à un serveur distant. J&#8217;ai tous mes parcs de serveurs listés là dedans.</p>
<div id="attachment_6300" class="wp-caption aligncenter" style="width: 542px"><a href="media/365a8da3.sshplus.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/sshplus.jpg"><img class="size-full wp-image-6300" title="Malgré le nom, ça ne sert pas qu'à SSH : toute automatisation en ligne de commande est possible." src="media/365a8da3.sshplus.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/sshplus.jpg" alt="Capture d'écran du logiciel SSHplus" width="532" height="487" /></a><p class="wp-caption-text">Malgré le nom, ça ne sert pas qu&#39;à SSH : toute automatisation en ligne de commande est possible.</p></div>
<h3>Dropbox + Rsync + scp + wget + clé USB + disque dur externe + dukto + Filezilla</h3>
<p>En matière de partage et de syncro des fichiers, y a rien de parfais. Alors j&#8217;utilise tout ce qui traîne selon la tâche, l&#8217;humeur et le destinataire.</p>
<p>Y a vraiment un truc à faire dans ce domaine. La synchro, le backup, le partage&#8230; C&#8217;est toujours pas résolu. Le mec qui solutionne ça fera des millions.</p>
<p>Moralité : un seul outil suffit rarement. En général, j&#8217;ai toujours une collection de soft. Même quand je vous en est listé un seul, la vérité c&#8217;est que j&#8217;ai 2/3 alternatives sous le coude, &#8220;au cas où&#8221;.</p>
<h3>WordPress</h3>
<p>Sniff. On peut pas vivre avec (bug, lenteur, code immonde), mais on peut pas vivre sans (productivité sans pareille, 10000 plugins et thêmes, comments hébergés&#8230;).</p>
<p>J&#8217;ai longtemps penser à coder un blog, mais c&#8217;est super ingrat et chronophage.</p>
<h3>Bash (avec un bashrc bien chargé)</h3>
<p>zsh ne m&#8217;a pas convaincu de son utilité. Je reste sur bash, avec un <a href="http://sametmax.com/a-linterieur-de-mon-bashrc/">.bashrc bien étudié</a>.</p>
<h3>Teamviewer</h3>
<p><a href="http://doc.ubuntu-fr.org/teamviewer">C&#8217;est proprio</a>, mais en même temps, c&#8217;est tellement bien foutu. C&#8217;est le soft le plus simple avec la meilleur qualité pour prendre le contrôle de l&#8217;ordi de ma maman à distance. Et c&#8217;est important les mamans.</p>
<h3>Inkscape + pdfmod</h3>
<p><a href="http://inkscape.org/?lang=fr">Inkscape</a> permet de faire du dessin vectoriel à la Illustrator. C&#8217;est un très beau produit, pratique pour faire des schémas ou modifier un PDF (par exemple pour trafiquer sa fiche de paie et obtenir un meilleur job en frimant à l&#8217;entretien). Je rappelle que le faux et usage de faux est puni pénalement sévèrement, et je vous encourage donc&#8230; à ne pas vous faire prendre.</p>
<div id="attachment_6301" class="wp-caption aligncenter" style="width: 524px"><a href="media/1f00b8c9.inskape.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/inskape.jpg"><img class=" wp-image-6301 " title="C'est beau le logiciel libre quand même. Vous imaginez le boulot pour pondre un truc pareil ?" src="media/1f00b8c9.inskape.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/inskape.jpg" alt="Capture d'écran du logiciel inkscape éditant le PDF du livre flatland" width="514" height="407" /></a><p class="wp-caption-text">C&#39;est beau le logiciel libre quand même. Vous imaginez le boulot pour pondre un truc pareil ?</p></div>
<p><a href="https://live.gnome.org/PdfMod">Pdfmod</a> est un petit soft qui permet de réorganiser les pages d&#8217;un ou plusieurs PDF pour en faire un nouveau document.</p>
<div id="attachment_6302" class="wp-caption aligncenter" style="width: 395px"><a href="media/3844b521.pdfmod.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/pdfmod.jpg"><img class=" wp-image-6302 " title="&quot;Comment je fais pour modifier un PDF&quot; est dans le top 10 des questions posées à un Geek" src="media/3844b521.pdfmod.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/pdfmod.jpg" alt="Capture d'écran du logiciel PDFmod" width="385" height="305" /></a><p class="wp-caption-text">&quot;Comment je fais pour modifier un PDF&quot; est dans le top 10 des questions posées à un Geek</p></div>
<h3>Make et GCC</h3>
<p>Il faut ce qu&#8217;il faut ma chère Thérèse.</p>
<p>On fait pas toujours ce qu&#8217;on veut.</p>
<p>Demain est un autre jour.</p>
<p>Qui vol un oeuf vol un boeuf.</p>
<h3>Firefox, chromium, opera, epifany&#8230; et IE</h3>
<p>Firefox est mon browser par défaut (ne serait-ce que parce qu&#8217;il a les <a href="http://support.mozilla.org/en-US/kb/tab-groups-organize-tabs">groupes d&#8217;onglets</a> et <a href="https://addons.mozilla.org/fr/firefox/addon/video-downloadhelper/">download video helper</a>). Après je test sur le reste des navigateurs. Parfois j&#8217;utilise Opera pour les sites qui font chier avec adblock.</p>
<h3>Qwit</h3>
<p>Tout simplement l&#8217;interface la plus moche de tous les clients twitter du monde. Accessoirement aussi le client le plus rapide et le moins gourmand en ressource. <a href="http://code.google.com/p/qwit/">Simple, rapide, efficace</a>.</p>
<div id="attachment_6303" class="wp-caption aligncenter" style="width: 590px"><a href="media/6457e2e7.qwit.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/qwit.jpg"><img class=" wp-image-6303 " title="Le compteur de mot n'est pas génial, mais ce logiciel à le bon goût de se faire oublier et de gérer les multicomptes." src="media/6457e2e7.qwit.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/qwit.jpg" alt="Capture d'écran de qwit" width="580" height="371" /></a><p class="wp-caption-text">Le compteur de mot n&#39;est pas génial, mais ce logiciel à le bon goût de se faire oublier et de gérer les multicomptes.</p></div>
<h3>Gcolor</h3>
<p>Un <a href="http://gcolor2.sourceforge.net/">color picker</a> bien foutu avec pipette. Rien à dire, ça marche.</p>
<div id="attachment_6304" class="wp-caption aligncenter" style="width: 553px"><a href="media/9c883e00.gcolor2_009.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/gcolor2_009.jpg"><img class="size-full wp-image-6304" title="En jaune de Damas. J'ai le même à la maison." src="media/9c883e00.gcolor2_009.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/gcolor2_009.jpg" alt="Capture d'écran du logiciel Gcolor2" width="543" height="554" /></a><p class="wp-caption-text">En jaune de Damas. J&#39;ai le même à la maison.</p></div>
<h3>Balsamiq mockup</h3>
<p>Quand j&#8217;ai besoin d&#8217;un mockup pro pour un client, j&#8217;utilise ça. <a href="http://www.balsamiq.com/products/mockups">Ca fait sérieux</a>. En plus c&#8217;est ludique à utiliser.</p>
<h3>Transmission</h3>
<p>Et oui, j&#8217;utilise ce <a href="http://www.transmissionbt.com/">client bittorrent</a> pour le travail. Dès que je télécharge un gros truc, genre ISO linux, je passe par torrent. C&#8217;est juste plus efficace. J&#8217;en fais aussi usage pour télécharger des vidéos dans une autre langue que celle diffusée en France afin de pouvoir apprendre ce langage, ce que je fais entrer dans la catégorie &#8220;travail&#8221;.</p>
<p>Pour moi bittorent est devenu un protocole incontournable dans l&#8217;internet moderne.</p>
<h3>Boabab</h3>
<p>Ce logiciel <a href="http://www.marzocca.net/linux/baobab/">analyse votre disque dur</a> et trouve ce qui prend le plus de place. L&#8217;équivalent de Win Dir Stats, mais sous Linux. Simplissime. Indispenable quand vous avez un petit SSD pour pouvoir virer tous ces dossiers <em>.machin</em> accumulés au fil du temps.</p>
<div id="attachment_6309" class="wp-caption aligncenter" style="width: 493px"><a href="media/7eb48a75.Analyseur-dutilisation-des-disques_001.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/Analyseur-dutilisation-des-disques_001.jpg"><img class=" wp-image-6309 " title="Le dossier le plus gros dans est le dossier &quot;Musique&quot;. Le deuxième est le dossier &quot;Work&quot;." src="media/7eb48a75.Analyseur-dutilisation-des-disques_001.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/Analyseur-dutilisation-des-disques_001.jpg" alt="Capture d'écran du logiciel Baobab" width="483" height="317" /></a><p class="wp-caption-text">Le dossier le plus gros dans est le dossier &quot;Musique&quot;. Le deuxième est le dossier &quot;Work&quot;.</p></div>
<h3>Evince</h3>
<p>Le <a href="http://fr.wikipedia.org/wiki/Evince">visualiseur de documents</a> (PDF principalement, mais pas que) par défaut sous Ubuntu, ce truc est rapide et fiable. J&#8217;adore ce genre de petit outil qui sait se faire oublier.</p>
<h3>sqliteman et pgadmin</h3>
<p>Des UI pour administrer des bases <a href="sqliteman ">SQLite</a> et <a href="http://www.pgadmin.org/">PostGres</a>. Quand l&#8217;ORM montre ses limites, on est très content de les trouver.</p>
<div id="attachment_6305" class="wp-caption aligncenter" style="width: 555px"><a href="media/157af6cd.sqlitemanager.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/sqlitemanager.jpg"><img class=" wp-image-6305 " title="Existe aussi en extension Firefox" src="media/157af6cd.sqlitemanager.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/sqlitemanager.jpg" alt="Capture d'écran du logiciel SqlMan" width="545" height="391" /></a><p class="wp-caption-text">Existe aussi en extension Firefox</p></div>
<div id="attachment_6306" class="wp-caption aligncenter" style="width: 480px"><a href="media/ab79db4b.pgAdmin-III_021.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/pgAdmin-III_021.jpg"><img class=" wp-image-6306  " title="Postgres: 247 niveaux avant d'atteindre tes putains de table. Et mon client adore créer un cluster par appli." src="media/ab79db4b.pgAdmin-III_021.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/pgAdmin-III_021.jpg" alt="Capture d'écran du logiciel PGadmin " width="470" height="268" /></a><p class="wp-caption-text">Postgres: 247 niveaux avant d&#39;atteindre tes putains de table. Et mon client adore créer un cluster par appli.</p></div>
<h3>LibreOffice</h3>
<p>Que ce genre de produit aux capacités gigantesques existe en logiciel libre me fascine toujours. J&#8217;en utilise 10% des capacités mais ça reste indispensable pour faire des lettres, des calculs ou des slides en 2 secondes chrono.</p>
<h2>Pour la détente</h2>
<p>Bon, je devais parler de mon env de travail, mais entre deux sessions de travail, y a bien une pause non ?</p>
<h3>Rhythmbox</h3>
<p>Le lecteur de musique par défaut d&#8217;Ubuntu, ne casse pas 3 pattes à un canard, mais je ne veux surtout pas un truc plus gros. J&#8217;ai aucune envie de gérer ma collection musical, je veux juste un bouton play et un putain champ de recherche. Le bouton &#8220;play/pause&#8221; intégré dans le menu son de l&#8217;OS est un bonus.</p>
<div id="attachment_6307" class="wp-caption aligncenter" style="width: 520px"><a href="media/e6a17262.rythmbox.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/rythmbox.jpg"><img class=" wp-image-6307 " title="Now paying *sweat child of mine*. Where do we go, where do we go now ?" src="media/e6a17262.rythmbox.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/rythmbox.jpg" alt="Capture d'écran du logiciel rhythmbox" width="510" height="395" /></a><p class="wp-caption-text">Now paying *sweat child of mine*. Where do we go, where do we go now ?</p></div>
<h3>Sound Converter</h3>
<p><a href="http://soundconverter.org/">On ne peut pas faire plus simple</a> pour convertir sa musique d&#8217;un format à un autre. On ne peut pas.</p>
<div id="attachment_6308" class="wp-caption aligncenter" style="width: 512px"><a href="media/c548d8c7.SoundConverter_018.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/SoundConverter_018.jpg"><img class="size-full wp-image-6308" title="Et j'utilise handbrake pour la même chose pour les videos. Mais j'ai oublié de le mettre et maintenant j'ai la flemme d'éditer." src="media/c548d8c7.SoundConverter_018.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/SoundConverter_018.jpg" alt="Capture d'écran du logiciel sound converter" width="502" height="529" /></a><p class="wp-caption-text">Et j&#39;utilise handbrake pour la même chose pour les videos. Mais j&#39;ai oublié de le mettre et maintenant j&#39;ai la flemme d&#39;éditer.</p></div>
<h3>Audacity</h3>
<p>C&#8217;est le <a href="http://audacity.sourceforge.net/?lang=fr">The Gimp de l&#8217;audio</a>. C&#8217;est hyper dur à utiliser. Mais ça marche.</p>
<h3>Comix</h3>
<p>Logiciel super sympas pour<a href="http://comix.sourceforge.net/"> lire les mangas</a> scannés. Ca gère les jpeg, en affiche deux d&#8217;un coup, permet un mode de sens de lecture inversé, lit une archive zip directement&#8230; Bref, pour les amateurs de scan, c&#8217;est cool.</p>
<h3>VLC</h3>
<p>Bon. Heu. Hein.</p>
<h3>Caffeine</h3>
<p><a href="http://www.omgubuntu.co.uk/2011/01/the-omg-guide-to-must-have-indicator-applets">Un applet</a> qui désactive l&#8217;écran de veille et l&#8217;hibernation quand une vidéo se joue. C&#8217;est con, mais il fallait y penser.</p>
<h2>Occasionellement</h2>
<p>J&#8217;utilise peu ces trucs, mais ça arrive.</p>
<h3>Ghex</h3>
<p>Pour <a href="https://live.gnome.org/Ghex">éditer de l&#8217;hexa</a>. Une fois tous les 5 ans. Par erreur. Bourré.</p>
<div id="attachment_6311" class="wp-caption aligncenter" style="width: 509px"><a href="media/02c7d068.ghex1.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/ghex1.jpg"><img class=" wp-image-6311 " title="Je dois être très cuit, j'arrive rien à lire" src="media/02c7d068.ghex1.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/ghex1.jpg" alt="Capture d'écran du logiciel Ghex" width="499" height="344" /></a><p class="wp-caption-text">Je dois être très cuit, j&#39;arrive rien à lire</p></div>
<h3>Virtualbox, vmware</h3>
<p>De quoi faire toutes sortes de <a href="https://www.virtualbox.org/">machines virtuelles</a>.</p>
<p>Pour tester les nouvelles distribs ou un nouveau script fabric de déploiement. Ou même IE.</p>
<h3>Wireshark</h3>
<p>Le <a href="http://www.wireshark.org/">sniffeur de paquets</a>.</p>
<p>Pour la culture. Pour me faire passer pour quelqu&#8217;un d&#8217;intelligent.</p>
<h3>Dia</h3>
<p>Cette <a href="http://doc.ubuntu-fr.org/dia">immonde bous</a>e de créateur de diagramme. C&#8217;est nul, mais alors c&#8217;est nulllllllll. Mais y a aucune alternative desktop sous Linux.</p>
<h3>Kompozer</h3>
<p>Un éditeur HTML WYSIWYG. Quand j&#8217;ai besoin d&#8217;un tableau HTML, je le dessine là dedans. Maintenant appelé <a href="http://www.bluegriffon.org/">BlueGriffon</a>.</p>
<h3>Recordmydesktop</h3>
<p>Pour <a href="http://doc.ubuntu-fr.org/recordmydesktop">filmer mon bureau</a> pour des tutos.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6288&amp;md5=d04339707e78b185c2cce4519e038ff4" 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=6327
title: Batbelt, la lib des petits outils Python qui vont bien
uri: Batbelt-la-lib-des-petits-outils-Python-qui-vont-bien
url: http://sametmax.com/batbelt-la-lib-des-petits-outils-python-qui-vont-bien/
content:
<p>A force de coder plein de projets, il y a des opérations qui reviennent très souvent. Ces traitements sont petits et complètement sans relation, difficile d&#8217;en faire quelque chose. J&#8217;ai tout de même finit par en faire un lib, <a href="https://github.com/sametmax/Bat-belt/">batbelt</a>, qui au final n&#8217;est qu&#8217;une grosse collections de snippets que j&#8217;utilise régulièrement. Il y a aussi des trucs que j&#8217;utilise moins ou des astuces / hacks un peu crades, c&#8217;est toujours pratique pour geeker à l&#8217;arrache vite fait. Vous allez d&#8217;ailleurs retrouver des bouts de code dont j&#8217;ai déjà parlé sur le site</p>
<p><code><a href="http://sametmax.com/votre-python-aime-les-pip/">pip</a> install batbelt</code></p>
<p>Et la plupart des fonctions sont accessible avec un <code>from batbelt import...</code></p>
<p>Voici les choses qui pourraient vous intéresser le plus dans batbelt&#8230;</p>
<h2>To timestamp</h2>
<p>Mais combien de fois j&#8217;ai du la coder celle-là ? En plus l&#8217;inverse existe, alors pourquoi, mon Dieu, pourquoi ?</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;">datetime</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">datetime</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> to_timestamp<span style="color: black;">&#40;</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;">2</span>, <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">946692061</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">datetime</span>.<span style="color: black;">fromtimestamp</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">946688461</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># tu as codé celle là et pas l'autre connard !</span>
<span style="color: #dc143c;">datetime</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;">2</span>, <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span></pre></div></div>

<h2>Récupérer une valeur dans une structure de données imbriquée</h2>
<p>Au lieu de faire :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">try</span>:
    res = data<span style="color: black;">&#91;</span><span style="color: #483d8b;">'cle'</span><span style="color: black;">&#93;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'autre cle'</span><span style="color: black;">&#93;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
<span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: black;">&#40;</span><span style="color: #008000;">KeyError</span>, <span style="color: #008000;">IndexError</span><span style="color: black;">&#41;</span>:
    res = <span style="color: #483d8b;">&quot;valeur&quot;</span></pre></div></div>

<p>On peut faire :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">get<span style="color: black;">&#40;</span>data, <span style="color: #483d8b;">'cle'</span>, <span style="color: #ff4500;">0</span>, <span style="color: #483d8b;">'autre cle'</span>, <span style="color: #ff4500;">1</span>, default=<span style="color: #483d8b;">&quot;valeur&quot;</span><span style="color: black;">&#41;</span></pre></div></div>

<h2>Récupérer la valeur d&#8217;un attribut dans un attribut dans un attribut&#8230;</h2>
<p>Pareil, mais pour les attributs.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">try</span>:
    devise = voiture.<span style="color: black;">moteur</span>.<span style="color: black;">prix</span>.<span style="color: black;">devise</span>
<span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">AttributeError</span>:
    devise = <span style="color: #483d8b;">&quot;euro&quot;</span></pre></div></div>

<p>On peut faire :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">devise = attr<span style="color: black;">&#40;</span>voiture, <span style="color: #483d8b;">'moteur'</span>, <span style="color: #483d8b;">'prix'</span>, <span style="color: #483d8b;">'devise'</span>, default=<span style="color: #483d8b;">'euro'</span><span style="color: black;">&#41;</span></pre></div></div>

<h2>Itérons, mon bon</h2>
<p>Ces fonctions retournent des générateurs qui permettent d&#8217;itérer par morceau ou par fenêtre glissante.</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> <span style="color: #dc143c;">chunk</span> <span style="color: #ff7700;font-weight:bold;">in</span> chunks<span style="color: black;">&#40;</span>l, <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>:
...     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">chunk</span><span style="color: black;">&#41;</span>
...
<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">3</span>, <span style="color: #ff4500;">4</span>, <span style="color: #ff4500;">5</span><span style="color: black;">&#93;</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">6</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;">9</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">for</span> slide <span style="color: #ff7700;font-weight:bold;">in</span> window<span style="color: black;">&#40;</span>l, <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>:
...     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>slide<span style="color: black;">&#41;</span>
...
<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span><span style="color: black;">&#93;</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;">2</span>, <span style="color: #ff4500;">3</span>, <span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">3</span>, <span style="color: #ff4500;">4</span>, <span style="color: #ff4500;">5</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;">5</span>, <span style="color: #ff4500;">6</span>, <span style="color: #ff4500;">7</span><span style="color: black;">&#93;</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">6</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;">7</span>, <span style="color: #ff4500;">8</span>, <span style="color: #ff4500;">9</span><span style="color: black;">&#93;</span></pre></div></div>

<p>Ça devrait être en standard dans Python.</p>
<p>Parfois on veut juste le premier élément d&#8217;une collection. Ou juste le premier à être vrai:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> first<span style="color: black;">&#40;</span><span style="color: #008000;">xrange</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">0</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> first_true<span style="color: black;">&#40;</span><span style="color: #008000;">xrange</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">1</span></pre></div></div>

<p>Marche avec n&#8217;importe quel itérable, contrairement à <code>[0]</code> qui ne marche que sur les indexables. Et en prime on peut spécifier une valeur par défaut:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> first<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>, default=<span style="color: #483d8b;">&quot;What the one thing we say to the God of Death ?&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'What the one thing we say to the God of Death ?'</span></pre></div></div>

<h2>Set ordonné</h2>
<p>On a des dicts ordonnés dans la lib standard, mais pas de set ordonné. On en a pas besoin souvent, mais ça peut être TRES pratique, et TRES chiant à implémenter soi-même.</p>
<p>Donc acte.</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;">set</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>: <span style="color: #808080; font-style: italic;"># booooooo</span>
...     <span style="color: #ff7700;font-weight:bold;">print</span> x
...
<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;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> sset<span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>: <span style="color: #808080; font-style: italic;"># clap clap !</span>
...     <span style="color: #ff7700;font-weight:bold;">print</span> x
...
<span style="color: #ff4500;">3</span>
<span style="color: #ff4500;">2</span>
<span style="color: #ff4500;">1</span></pre></div></div>

<p>Attention, c&#8217;est pas la structure de données la plus rapide du monde&#8230;</p>
<h2>Je suis une feignasse et j&#8217;aime les one-liners sur les dicos</h2>
<p>Je ne comprends pas pourquoi <code>+</code> ne fonctionne pas sur les dico.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> dmerge<span style="color: black;">&#40;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;a&quot;</span>: <span style="color: #ff4500;">1</span>, <span style="color: #483d8b;">&quot;b&quot;</span>: <span style="color: #ff4500;">2</span><span style="color: black;">&#125;</span>, <span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;b&quot;</span>: <span style="color: #ff4500;">2</span>, <span style="color: #483d8b;">&quot;c&quot;</span>: <span style="color: #ff4500;">3</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#123;</span><span style="color: #483d8b;">'a'</span>: <span style="color: #ff4500;">1</span>, <span style="color: #483d8b;">'c'</span>: <span style="color: #ff4500;">3</span>, <span style="color: #483d8b;">'b'</span>: <span style="color: #ff4500;">2</span><span style="color: black;">&#125;</span></pre></div></div>

<p>Ne modifie pas les dictionnaires originaux.</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> batbelt.<span style="color: black;">structs</span> <span style="color: #ff7700;font-weight:bold;">import</span> rename
<span style="color: #66cc66;">&gt;&gt;&gt;</span> rename<span style="color: black;">&#40;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;a&quot;</span>: <span style="color: #ff4500;">1</span>, <span style="color: #483d8b;">&quot;b&quot;</span>: <span style="color: #ff4500;">2</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> rename<span style="color: black;">&#40;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;a&quot;</span>: <span style="color: #ff4500;">1</span>, <span style="color: #483d8b;">&quot;b&quot;</span>: <span style="color: #ff4500;">2</span><span style="color: black;">&#125;</span>, <span style="color: #483d8b;">'b'</span>, <span style="color: #483d8b;">'z'</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'a'</span>: <span style="color: #ff4500;">1</span>, u<span style="color: #483d8b;">'z'</span>: <span style="color: #ff4500;">2</span><span style="color: black;">&#125;</span></pre></div></div>

<p>Modifie le dictionnaire original et n&#8217;est PAS thread safe.</p>
<p>Et le cas tordu mais tellement satisfaisant :</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> batbelt.<span style="color: black;">structs</span> <span style="color: #ff7700;font-weight:bold;">import</span> unpack
<span style="color: #66cc66;">&gt;&gt;&gt;</span> dct = <span style="color: black;">&#123;</span><span style="color: #483d8b;">'a'</span>: <span style="color: #ff4500;">2</span>, <span style="color: #483d8b;">'b'</span>: <span style="color: #ff4500;">4</span>, <span style="color: #483d8b;">'z'</span>: <span style="color: #ff4500;">42</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> a, b, c = unpack<span style="color: black;">&#40;</span>dct, <span style="color: #483d8b;">'a'</span>, <span style="color: #483d8b;">'b'</span>, <span style="color: #483d8b;">'c'</span>, default=<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> a
<span style="color: #ff4500;">2</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> b
<span style="color: #ff4500;">4</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> c
<span style="color: #ff4500;">1</span></pre></div></div>

<h2>Slugifier</h2>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> slugify<span style="color: black;">&#40;</span>u<span style="color: #483d8b;">&quot;Hélo Whorde&quot;</span><span style="color: black;">&#41;</span>
helo-whorde</pre></div></div>

<p>Il y a pas mal de réglages possibles avec <code>slugify()</code>, mais je vous laisse les découvrir :-) Cette fonction fait partie du sous-module <code>strings</code>, qui contient d&#8217;autres utilitaires comme <code>escape_html/unescape_html</code> (qui transforme les caractères spéciaux en HTML entities et inversement) ou <code>json_dumps/json_loads</code> (qui fait un dump / load du JSON en prenant en compte le type <codde>datetime</codde>).</p>
<h2>Importer une classe ou une fonction depuis une string</h2>
<p>Dès que vous faites un fichier de config vous avez besoin de ce genre de truc, mais la fonction <code>__import__</code> a une signature uber-zarb. Voici une version beaucoup plus simple:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">TaClasse = import_from_path<span style="color: black;">&#40;</span><span style="color: #483d8b;">'foo.bar.TaClasse'</span><span style="color: black;">&#41;</span>
ton_obj = TaClasse<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<h2>Capturer les prints</h2>
<p>Parfois on a une lib qui <code>print</code> plutôt que de retourner une valeur. C&#8217;est très chiant. J&#8217;ai donc fait un context manager qui permet de récupérer tout ce qui est printé dans le block du <code>with</code>.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">with</span> capture_ouput<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> <span style="color: black;">&#40;</span>stdout, stderr<span style="color: black;">&#41;</span>:
...    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;hello&quot;</span>,
...
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span> stdout.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
hello</pre></div></div>

<h2>Créer un décorateur qui accepte des arguments</h2>
<p>Même dans le cas où vous avez parfaitement compris les décorateurs grâce à un très <a href="http://sametmax.com/comprendre-les-decorateurs-python-pas-a-pas-partie-1/">bon tuto</a> (^^), se souvenir de comment faire un décorateur qui attend des arguments en paramètre, c&#8217;est mission impossible. Voici donc un décorateur&#8230; pour créer un décorateur.</p>
<p>Étape un, écrire votre décorateur :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># tout les arguments après 'func' sont ceux que votre décorateur acceptera</span>
@decorator_with_args<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> votre_decorateur<span style="color: black;">&#40;</span>func, arg1, arg2=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> arg1:
        <span style="color: #808080; font-style: italic;"># faire un truc</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># ici on fait juste le truc habituel des décorateurs</span>
    <span style="color: #808080; font-style: italic;"># wrapper, appel de la fonction wrappée et retour du wrapper...</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> wrapper<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;"># arg2 est dans une closure, on peut donc l'utiliser dans</span>
        <span style="color: #808080; font-style: italic;"># la fonction appelée</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> func<span style="color: black;">&#40;</span>arg2<span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> wrapper</pre></div></div>

<p>Et on peut utiliser son décorateur tranquile-bilou :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">@votre_decorateur<span style="color: black;">&#40;</span><span style="color: #008000;">False</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> hop<span style="color: black;">&#40;</span>un_arg<span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># faire un truc dans la fonction décorée</span></pre></div></div>

<h2>Les processus parallèles finissent toujours par se rencontrer à l&#8217;infini et corrompre leurs données</h2>
<p>Mais en attendant on en a quand même besoin. Parfois un petit worker, c&#8217;est sympa, pas besoin de faire compliqué et de sortir des libs de task queue complètes:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> batbelt.<span style="color: black;">parallel</span> <span style="color: #ff7700;font-weight:bold;">import</span> worker
&nbsp;
@worker<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> une_tache<span style="color: black;">&#40;</span>arg<span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># faire un truc avec arg</span>
    arg = arg + <span style="color: #ff4500;">10</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> arg
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;"># on demarre le worker</span>
process = une_tache.<span style="color: black;">start</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># on balance des tâches au worker</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;">10</span><span style="color: black;">&#41;</span>:
    process.<span style="color: black;">put</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># on récupère les résultats (optionnel)</span>
<span style="color: #808080; font-style: italic;"># ca peut être dans un fichier différent</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;">10</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> process.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">## 10</span>
<span style="color: #808080; font-style: italic;">## 11</span>
<span style="color: #808080; font-style: italic;">## 12</span>
<span style="color: #808080; font-style: italic;">## 13</span>
<span style="color: #808080; font-style: italic;">## 14</span>
<span style="color: #808080; font-style: italic;">## 15</span>
<span style="color: #808080; font-style: italic;">## 16</span>
<span style="color: #808080; font-style: italic;">## 17</span>
<span style="color: #808080; font-style: italic;">## 18</span>
<span style="color: #808080; font-style: italic;">## 19</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># on arrête le worker</span>
process.<span style="color: black;">stop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Le worker est un subprocess par défaut, mais vous pouvez en faire un thread avec @worker(method=&#8221;tread&#8221;). Toujours utile, par exemple pour avec un processeur de mails qui envoit tous les mails hors du cycle requête / réponse de votre site Web. Par contre si votre process meurt la queue est perdue.</p>
<h2>Template du pauvre</h2>
<p>Avec format(), on a déjà un mini-langage de template intégré. Pas de boucle, mais pour des tâches simples ça suffit. Du coup j&#8217;ai une fonction <code>render()</code> qui prend un fichier de template au format string Python et qui écrit le résultat dans un autre. Pratique pour faire des fichiers de conf configurable.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> batbelt.<span style="color: black;">strings</span> <span style="color: #ff7700;font-weight:bold;">import</span> render
&nbsp;
render<span style="color: black;">&#40;</span><span style="color: #483d8b;">'truc.conf.tpl'</span>, <span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;var&quot;</span>: <span style="color: #483d8b;">&quot;value&quot;</span><span style="color: black;">&#125;</span>, <span style="color: #483d8b;">&quot;/etc/truc.conf&quot;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Il y a aussi des implémentations de Singleton, du Null Pattern, etc. Mais ça s&#8217;utilise moins souvent alors je vais pas faire une tartine.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6327&amp;md5=508e8e245d0d31a0f68eeac4eaeb070d" 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=6321
title: Game of thrones, le jeu de plateau
uri: Game-of-thrones-le-jeu-de-plateau
url: http://sametmax.com/game-of-thrones-le-jeu-de-plateau/
content:
<p>J&#8217;avais le choix entre écrire un article et rejoindre une bande de geeks pour tester GOT en jeu de plateau. J&#8217;adore les jeux de société (labyrinthe, muchkin, risk, loup garou, times up, boggle, etc), et je connaissais pas celui là.</p>
<p>Mon hôte possède un nombre impressionant de boîtes, j&#8217;ai rencontré un mec qui avait dans sa collec magic un lotus noir, les pizzas sont sorties, Tenacious D est en fond. Bref, une bonne soirée d&#8217;ados.</p>
<p>Conclusion : pas de gros article aujourd&#8217;hui, mais GOT en jeu est super cool (mais tellement compliqué qu&#8217;il faut pas imaginer apprendre le truc en lisant les règles par soi-même).</p>
<p>C&#8217;est dimanche, bon dimanche, sous vos applaudissements.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6321&amp;md5=2a9beade08bf02481512c5b4a699363a" 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=6333
title: Non aux Google Glasses
uri: Non-aux-Google-Glasses
url: http://sametmax.com/non-aux-google-glasses/
content:
<p>J&#8217;ai découvert l&#8217;excellent blog soat.fr, mais dernièrement un article m&#8217;a fait très peur : <a href="http://blog.soat.fr/2013/04/apercu-sur-google-glass-google-mirror-api/">il s&#8217;enthousiasme</a> de l&#8217;arrivée des Google glasses.</p>
<p>C&#8217;est déjà assez dur de voir cette monstruosité arriver, mais que des gens intelligents soit super jouasses à ce propos, ça me fait mal au fion.</p>
<div id="attachment_6339" class="wp-caption aligncenter" style="width: 272px"><a href="media/5408214f.NlPA0.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/NlPA0.gif"><img class="size-full wp-image-6339" title="What. The. Actual. Fuck ?" src="media/5408214f.NlPA0.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/NlPA0.gif" alt="Gif animé de Leonardo Dicaprio retirant ses lunettes de soleil à l'infini" width="262" height="200" /></a><p class="wp-caption-text">What. The. Actual. Fuck ?</p></div>
<p>Je vous rappelle les qualités de la bête:</p>
<ul>
<li>Caméra.</li>
<li>Micro.</li>
<li>GPS.</li>
<li>Connexion haut débit.</li>
</ul>
<p>Rappelez-vous que Google possède les technologies suivantes :</p>
<ul>
<li>Couverture géographique et localisation complète, précise et en contexte.</li>
<li>Analyse de la voix.</li>
<li>Reconnaissance faciale.</li>
</ul>
<p>Souvenez-vous aussi que Google possède déjà :</p>
<ul>
<li>Vos conversations mails, chats et bientôt visio.</li>
<li>Votre historique Web, y compris comportementale.</li>
<li>Votre calendrier.</li>
<li>Vos contacts mails, et probablement téléphoniques et postaux.</li>
</ul>
<p>Donc l&#8217;idée, c&#8217;est de lui fournir gratuitement des systèmes micro + caméra connectés localisés en temps réel partout dans le monde ?</p>
<p>Vous êtes des malades ou quoi ?</p>
<p>Parce que avec un téléphone Android, vous pouvez faire attention à VOTRE usage. Et encore c&#8217;est difficile.</p>
<p>Mais quand ce sera des millions de connards qui seront dehors avec ces machins (parque c&#8217;est trop cool !), vous faites comment ? Vous les éduquez tous pour leur dire faire attention à ce qu&#8217;ils enregistrent de vous ? Bah oui, <strong>vous êtes dedans même si vous n&#8217;en portez pas.</strong></p>
<p>Et l&#8217;utilisateur moyen laissera les settings par défaut, voir de grosses failles de sécurité. En plus la tentation d&#8217;usage gouvernemental va être bien trop grande.</p>
<div id="attachment_6338" class="wp-caption aligncenter" style="width: 453px"><a href="media/90ba79f1.pfzwnKN.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/pfzwnKN.jpg"><img class=" wp-image-6338  " title="Sur imgur, cette photo est légendée &quot;votre gadget est votre prison&quot;." src="media/90ba79f1.pfzwnKN.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/pfzwnKN.jpg" alt="Composition d'une prison arrangée pour avoir la forme d'un iphone" width="443" height="292" /></a><p class="wp-caption-text">Sur imgur, cette photo est légendée &quot;votre gadget est votre prison&quot;.</p></div>
<p>Ces trucs là sont dangereux. Très, très dangereux. Il ne faut en aucun cas acheter des Google glasses, en aucun cas en faire la promotion. Si on doit en parler c&#8217;est pour avertir les autres de faire très attention à ce qu&#8217;ils font en s&#8217;intéressant à ces dispositifs.</p>
<p>Si vous travaillez dessus, songez à démissionner. Je suis très sérieux. Il y a des choses qui ne doivent pas se faire. Ne sortez pas l&#8217;excuse limite godwinienne du &#8220;si ce n&#8217;est pas nous, d&#8217;autres le feront&#8221;. J&#8217;ai bien refusé un entretien d&#8217;embauche chez Google (rien à voir avec les glasses) l&#8217;année dernière pour des raisons éthiques. <strong>Vous êtes responsables.</strong></p>
<p>Même si vous êtes un utilisateur avancé, ces systèmes sont tellement complexes que votre contrôle dessus est illusoire, quand bien même c&#8217;est open source. Et vous êtes humains vous ferez des erreurs. Imaginez les autres, les milliers d&#8217;autres qui vont filmer des heures par jour des visages, taggés par lieu, heure et reconnus par la base de données Google automatiquement, liés à leurs profiles Web et contacts.</p>
<p>C&#8217;est un cauchemar.</p>
<p>N&#8217;achetez pas ces trucs. <strong>Faites savoir autour de vous qu&#8217;il faut se tenir loin, très très loin, de ces machins.</strong></p>
<div id="attachment_6343" class="wp-caption aligncenter" style="width: 510px"><a href="media/1a6a81cb.vUwzK7N.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/vUwzK7N.jpg"><img class="size-full wp-image-6343" title="La plupart des gens ne le verront pas venir, ça à l'air tellement bon de l'extérieur. Et puis une fois que ce sera officiel, l'excuse se sera : &quot;les oignons crus et le caramel, c'est bon séparément, on a jamais pensé qu'il ne faudrait pas les mélanger ?&quot;" src="media/1a6a81cb.vUwzK7N.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/vUwzK7N.jpg" alt="Photo d'oignons enrobés dans du caramel" width="500" height="492" /></a><p class="wp-caption-text">La plupart des gens ne le verront pas venir, ça à l&#39;air tellement bon de l&#39;extérieur. Et puis une fois que ce sera officiel, l&#39;excuse se sera : &quot;les oignons crus et le caramel, c&#39;est bon séparément, on a jamais pensé qu&#39;il ne faudrait pas les mélanger&quot;</p></div>
<p>Ça vaut aussi pour la xbox one et son kinect nouvelle génération qui <a href="http://vigilantcitizen.com/latestnews/new-game-console-xbox-one-will-have-always-on-camera-and-mic/">n&#8217;est rien d&#8217;autre qu&#8217;une caméra et un micro actif en permanence</a> dans votre salon, connecté à une console qui ne marche pas si elle n&#8217;est pas reliée au net. Et <a href="http://sebsauvage.net/links/?fkpP2A">ces sociétés ne sont pas bienveillantes</a>.</p>
<p>Faites pas les cons putain. Vous n&#8217;en avez pas besoin. Il y a des tas d&#8217;autres choses à acheter. Où n&#8217;achetez rien et payez vous une semaine au Costa Rica. Ça vous fera plus de bien.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6333&amp;md5=fd62b5bef77910e6f962cc41c1146fd7" 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=216
title: Comment parser du HTML avec des Regex ?
uri: Comment-parser-du-HTML-avec-des-Regex
url: http://sametmax.com/comment-parser-de-html-avec-des-regex/
content:
<p>Il y a longtemps que je voulais traduire <a href="http://stackoverflow.com/a/1732454">cette réponse</a> de StackOverflow, qui donne une bonne fois pour toute la réponse à cette question souvent posée.</p>
<p>Voici (le formatage exotique a été conservé au maximum):</p>
<p>Vous ne pouvez pas analyser [X]HTML avec des regex. Parce qu&#8217;HTML ne peut être analysé par des regex. Les regex sont un outil qui ne peut être utilisé pour analyser correctement du HTML. Comme je l&#8217;ai répondu dans des question HTML-et-regex ici de nombreuses fois auparavant, l&#8217;utilisation de regex ne permet pas de consommer du HTML. Les expressions rationnelles sont un outil qui n&#8217;est pas suffisamment sophistiqué pour comprendre les constructions employées par HTML. HTML n&#8217;est pas une langage rationnel, et de fait ne peut être parsé par des expressions rationnelles. Les requêtes par regex ne sont pas équipées pour diviser du HTML en parties qui ont du sens. Tant de fois, mais je ne m&#8217;en lasse pas. Même des expressions irrationnelles telles qu&#8217;utilisées par Perl en sont pas à la hauteur de la tâche que représente l&#8217;analyse de HTML. Vous ne me ferez pas céder. HTML est un langage d&#8217;une complexité telle qu&#8217;il ne peut être analysé par des expressions rationnelles. Même Chuck Norris ne peut analyser du HTML avec des expressions rationnelles. Chaque fois que vous essayez d&#8217;analyser du HTML avec des expressions rationnelles, l&#8217;enfant damné pleure du sang de vierge, et des hackers russes pown votre webapp. Analyser du HTML avec des regex invoque des âmes perdues dans le royaume des vivants. HTML et les regex vont ensemble comme l&#8217;amour, le mariage et les rituels infanticides. Le &lt;center&gt; ne peut tenir, il est trop tard. La force des regex et du HTML ensemble dans le même espace conceptuel détruira votre esprit comme l&#8217;humidité détruit les joints. Si vous analysez du HTML avec des regex, vous vous adonnez à Eux et leurs traditions blasphématoires qui nous condamnent tous à un labeur inhumain pour Celui dont le Nom ne peut être exprimé avec le Plan Multilingue Basique, il arrive. HTML-plus-regex liquéfiera les nerfs des êtres les plus sensibles sous vos yeux, votre psyché dépérissant sous les assauts de l&#8217;horreur. Les an̷al̵y͘s̕e͝urs ̸HT͝M͡L basés sur les regex sont le cancer qui tue StackOverflow <em>il est trop tard il est trop tard nous ne pouvons être sauvé</em>s la trangession d&#8217;un en̵f͝ant amènera les regex à consommer tout tissue vivant (excepté pour le HTML puisqu&#8217;il ne le peut, tel que prophétisé précédemment) <em>oh seigneur aide nous comment qui que ce soit peut-il survire à cet fléau</em> utiliser des regex pour analyser du HTML a condamné l&#8217;humanité à la terreur de la torture and aux failles de sécurité <em>utiliser les regex</em> comme outil pour travailler du HTML établie un brèche<em> entre ce monde</em> et le royaume terrifiant des entités corrompues (comme les entités SGML, mais plus<em> corrompues) un bref regard</em> vers le monde des analy<strong>seurs regex pour HTML transportera ins</strong>tantanément la <em>conscience d&#8217;un programmeur</em> d<em>a</em>ns un <em>m</em>onde de cris sans fin, il arrive, la <del>nauséabonde</del> plaie des infections regex <strong>dévoreront votre parser HT</strong>ML, votre application et votre existence pour l&#8217;éternité comme l&#8217;a fait Visual Basic mais en pire<em> il arrive il arrive ne vous déba</em>ttez pas <em>i̢l͞ a͘rr̸i҉v̡é,̨ <strong>sa radiance</strong> damnée</em> détruisant toute illumination, <em>des ͠t̕a̕g͡s ̶<strong>H͞TM̵L͞ ̕c̸o͜ùlan͜t̀ de̶ vos͜ ͟y͏eưx te̷l̛s̡ de l͜a̶ ̛d͝ǫ</strong>u͜lȩur҉ ͝l̡iquid͝ee,</em> la chanson de l&#8217;ana<del>lyse par expressions</del> rationnelles <em>reduit a<strong>u silence les voix de l&#8217;homme mortel depuis la sp</strong>hère je peux le voir pouvez-vous le voir c&#8217;est magnifique</em> l&#8217;expurgation de tous les mensonges de l&#8217;Homme  TOUT EST PERDU TOUT EST PERDU le poney il arrive i͟l arrive il̸ ̕arr̴i҉ve͢ ̕l&#8217;̵ich҉or ̸p̴é͝n͘è͟t̡r͞e tout MON V̴ISA҉ĢE͘͜ M̵̢͟O̶N ͢͏V͏I̧̨S͞AG̶̕͞E̷̡̕ oh mon dieu no Ņ̵̨ON̕ ̢҉̀N̸͡͞OO͏̢͝O̶͠O̷҉N҉͝ ͡N̶͘͏O̧N͟ ́͜͡s̀͟͡t̶͟o̧͝p̧ ̕͘l̴e҉͠s ͟ań̴gl͏ę̀͏s͢͝ ͜͝n̡e͏̡ ́so҉͜nt̵̡ ͢p̧͘a̛s̀ ̸͞r͞é̕͞e̛l̸͏s̨ ̧̀ZA̷Ĺ͝GO̸ ̸E̴͜͝Ş̵̛T̴̸͠ ̨T̨̢Ó͜N͡Y̢ ̷̨̕L̀E̵͠ PONE̕Y͟ I͖̮̝̥̞͟L̴̬͈͍͞ ̞̦A̴҉͕̩͉R͎͉̯̼̹̫͈̹R̩͎̙̥̦I̶̢͓̘̗V̤̳͓͓͇̯̭̯̥͜͢͢E̹̣͚̩̯̙͡.</p>
<p>Avez vous essayé un parser XML à la place ?</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=216&amp;md5=b9082d6c1c3a81567ac74fad14e35104" 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=6360
title: Recherche téléphone
uri: Recherche-téléphone
url: http://sametmax.com/recherche-telephone/
content:
<p>Hello cher internautes, </p>
<p>J&#8217;ai besoin de votre connaissance pour savoir si un tel modèle de téléphone existe. Voici mon cahier des charges :</p>
<li>PAS de wifi, 3G, GPS ou bluetooth.</li>
<li>Autonomie de 7 jours de batteries min.</li>
<li>Chargeable en USB.</li>
<li>Clavier AZERTY complet (physique ou virtuel).</li>
<li>SMS présentés sous forme de conversation.</li>
<li>Pas d&#8217;apps, pas de store, pas de truc en plus. Je veux juste téléphoner, pas écouter des MP3 ou jouer à des jeux Java.</li>
<li>Un 1.5 cm d&#8217;épaisseur max.</li>
<li>Déblocable (débloqué si possible).</li>
<p>Je me branle d&#8217;avoir un écran noir et blanc ou un design des années soixante.</p>
<p>Est-ce que ça existe ? Si ça n&#8217;existe pas, est-ce que quelqu&#8217;un peut lancer un putain de kickstarter ?</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6360&amp;md5=d47dcc2c9b48dc459a877a65d5e6439d" 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=6364
title: Django: That page number is less than 1
uri: Django-That-page-number-is-less-than-1
url: http://sametmax.com/django-that-page-number-is-less-than-1/
content:
<p>Vous avez fait une upgrade vers Django 1.5 et paf, votre pagination vous dégobille une erreur.</p>
<p>C&#8217;est normal, et <a href="https://docs.djangoproject.com/en/dev/releases/1.5/#validation-of-previous-page-number-and-next-page-number">c&#8217;est dans le changelog</a> : à partir de maintenant, l&#8217;objet page lève une exception si vous essayez de récupérer une page précédente ou suivante quand elle n&#8217;existe pas.</p>
<p>Par exemple, si vous êtes à la page 1, il n&#8217;y a pas de page 0, et donc si dans votre template vous faites ça :</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">{{ page_obj.previous_page_number }}</pre></div></div>

<p>Vous allez vous retrouver avec ça :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">***</span> EmptyPage: That page number <span style="color: #ff7700;font-weight:bold;">is</span> less than <span style="color: #ff4500;">1</span></pre></div></div>

<p>La solution est simplement de vérifier qu&#8217;il existe une page précédente (ou suivante). Par exemple :</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">{{ if page_obj.has_previous }}
    {{ page_obj.previous_page_number }}
{{ endif }}</pre></div></div>

 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6364&amp;md5=76ca90b429efcdc744235a0c75d939d6" 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=6378
title: Pouce
uri: Pouce
url: http://sametmax.com/pouce/
content:
<p>Je me casse pour quelques jours, y aura pas d&#8217;articles de ma part.</p>
<p>A plus dans l&#8217;bus.</p>
<p>&nbsp;</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6378&amp;md5=385b85c0b6c5dde71ffafaf1e14e1907" 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=6369
title: Mesurer les performances d’un snippet Python
uri: Mesurer-les-performances-d-un-snippet-Python
url: http://sametmax.com/mesurer-les-performances-dun-snippet-python/
content:
<p>Ca fait longtemps que j&#8217;avais pas musique.</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="420" height="315" src="http://www.youtube.com/embed/qeMFqkcPYcg" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<p>L&#8217;open source c&#8217;est fantastique. Github c&#8217;est merveilleux. On parle de <a href="http://sametmax.com/batbelt-la-lib-des-petits-outils-python-qui-vont-bien/">batbelt</a>, et paf, quelques jours plus tard on a notre <a href="https://github.com/sametmax/Bat-belt/pull/1">première contribution</a>.</p>
<p>Ce qui est sympa avec cette lib, c&#8217;est que ce sont des fonctions simples et courtes, axées sur des tâches très précises. Le code est donc généralement <a href="https://github.com/sametmax/Bat-belt/blob/master/batbelt/structs.py">intéressant à lire</a>, mais pas trop compliqué, et on tombe souvent sur des cas d&#8217;école.</p>
<p>C&#8217;est le cas de cette modification de la fonction <code>dmerge()</code>. Originalement, <code>dmerge</code> permet de créer un dictionnaire à partir de la fusion de de 2 autres dicos, et ça marchait comme ça:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> dmerge<span style="color: black;">&#40;</span>d1, d2<span style="color: black;">&#41;</span>:
    d = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
    d.<span style="color: black;">update</span><span style="color: black;">&#40;</span>d1<span style="color: black;">&#41;</span>
    d.<span style="color: black;">update</span><span style="color: black;">&#40;</span>d2<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> d</pre></div></div>

<p>Facile à comprendre, rapide, simple, et le comportement par défaut est intuitif : si une clé est en double, la clé du deuxième dico écrase la première.</p>
<p>Comme le <a href="http://sametmax.com/batbelt-la-lib-des-petits-outils-python-qui-vont-bien/#comment-9657">précisait Etienne,</a> ce comportement est néanmoins un parmi de nombreux possibles. On pourrait aussi vouloir:</p>
<ul>
<li>Lever une exception en cas de doublon.</li>
<li>Concaténer ou additionner les doublons.</li>
<li>Mettre les doublons dans une liste.</li>
<li>Garder la valeur originale en cas de doublon.</li>
<li>Prendre la valeur la plus grande / petite en cas de doublon.</li>
<li>Etc.</li>
</ul>
<p>Pour cela, notre contributeur a proposé qu&#8217;on puisse passer en paramètre une fonction qui choisit quelle valeur garder en cas de doublon. Le code devient donc :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> dmerge<span style="color: black;">&#40;</span>d1, d2, merge_func=<span style="color: #ff7700;font-weight:bold;">lambda</span> v1, v2: v2<span style="color: black;">&#41;</span>:
    d = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
    d.<span style="color: black;">update</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#40;</span>k, v<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> d1.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> k <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> d2<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    d.<span style="color: black;">update</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#40;</span>k, v<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> d2.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> k <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> d1<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    d.<span style="color: black;">update</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#40;</span>k, merge_func<span style="color: black;">&#40;</span>v, d2<span style="color: black;">&#91;</span>k<span style="color: black;">&#93;</span><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> d1.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> k <span style="color: #ff7700;font-weight:bold;">in</span> d2<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> d</pre></div></div>

<p>Avoir une valeur par défaut nous permet de garder le comportement initial. Pour cela on utilise une <a href="http://sametmax.com/fonctions-anonymes-en-python-ou-lambda/">lambda</a>. C&#8217;est ce qu&#8217;on appelle l&#8217;injection de dépendance.</p>
<p>Comme j&#8217;ai bien faire mumuse avec Python, je me suis demandé : &#8220;quelle est la stratégie de merge la plus rapide ?&#8221;. J&#8217;ai donc fait plusieurs tests de merge, avec plusieurs algos. Voici ce que ça donne:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"> <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">itertools</span> <span style="color: #ff7700;font-weight:bold;">import</span> chain
&nbsp;
&nbsp;
 <span style="color: #ff7700;font-weight:bold;">def</span> dmerge1<span style="color: black;">&#40;</span>d1, d2, merge_func=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
     <span style="color: #483d8b;">&quot;&quot;&quot;
         Mon premier essai, en virant la lambda et en utilisant itertools.
     &quot;&quot;&quot;</span>
     d = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
&nbsp;
     <span style="color: #ff7700;font-weight:bold;">if</span> merge_func <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">None</span>:
&nbsp;
         d.<span style="color: black;">update</span><span style="color: black;">&#40;</span>d1<span style="color: black;">&#41;</span>
         d.<span style="color: black;">update</span><span style="color: black;">&#40;</span>d2<span style="color: black;">&#41;</span>
         <span style="color: #ff7700;font-weight:bold;">return</span> d
&nbsp;
     <span style="color: #ff7700;font-weight:bold;">for</span> k, v <span style="color: #ff7700;font-weight:bold;">in</span> chain<span style="color: black;">&#40;</span>d1.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, d2.<span style="color: black;">iteritems</span><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;">if</span> k <span style="color: #ff7700;font-weight:bold;">in</span> d1 <span style="color: #ff7700;font-weight:bold;">and</span> k <span style="color: #ff7700;font-weight:bold;">in</span> d2:
             d<span style="color: black;">&#91;</span>k<span style="color: black;">&#93;</span> = merge_func<span style="color: black;">&#40;</span>d1<span style="color: black;">&#91;</span>k<span style="color: black;">&#93;</span>, d2<span style="color: black;">&#91;</span>k<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
         <span style="color: #ff7700;font-weight:bold;">else</span>:
             d<span style="color: black;">&#91;</span>k<span style="color: black;">&#93;</span> = v
&nbsp;
     <span style="color: #ff7700;font-weight:bold;">return</span> d
&nbsp;
&nbsp;
&nbsp;
 <span style="color: #ff7700;font-weight:bold;">def</span> dmerge2<span style="color: black;">&#40;</span>d1, d2, merge_func=<span style="color: #ff7700;font-weight:bold;">lambda</span> v1, v2: v2<span style="color: black;">&#41;</span>:
     <span style="color: #483d8b;">&quot;&quot;&quot;
         Le code du PR original
     &quot;&quot;&quot;</span>
     d = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
     d.<span style="color: black;">update</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#40;</span>k, v<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> d1.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> k <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> d2<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
     d.<span style="color: black;">update</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#40;</span>k, v<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> d2.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> k <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> d1<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
     d.<span style="color: black;">update</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#40;</span>k, merge_func<span style="color: black;">&#40;</span>v, d2<span style="color: black;">&#91;</span>k<span style="color: black;">&#93;</span><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> d1.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> k <span style="color: #ff7700;font-weight:bold;">in</span> d2<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
     <span style="color: #ff7700;font-weight:bold;">return</span> d
&nbsp;
&nbsp;
 <span style="color: #ff7700;font-weight:bold;">def</span> dmerge3<span style="color: black;">&#40;</span>d1, d2, merge_func=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
     <span style="color: #483d8b;">&quot;&quot;&quot;
        Un mélange du code original et de mon premier essai.
     &quot;&quot;&quot;</span>
     d = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
&nbsp;
     d.<span style="color: black;">update</span><span style="color: black;">&#40;</span>d1<span style="color: black;">&#41;</span>
&nbsp;
     <span style="color: #ff7700;font-weight:bold;">if</span> merge_func <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">None</span>:
         d.<span style="color: black;">update</span><span style="color: black;">&#40;</span>d2<span style="color: black;">&#41;</span>
         <span style="color: #ff7700;font-weight:bold;">return</span> d
&nbsp;
     <span style="color: #ff7700;font-weight:bold;">for</span> k, v <span style="color: #ff7700;font-weight:bold;">in</span> d2.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
         <span style="color: #ff7700;font-weight:bold;">if</span> k <span style="color: #ff7700;font-weight:bold;">in</span> d:
             d<span style="color: black;">&#91;</span>k<span style="color: black;">&#93;</span> = merge_func<span style="color: black;">&#40;</span>d<span style="color: black;">&#91;</span>k<span style="color: black;">&#93;</span>, v<span style="color: black;">&#41;</span>
         <span style="color: #ff7700;font-weight:bold;">else</span>:
             d<span style="color: black;">&#91;</span>k<span style="color: black;">&#93;</span> = v
&nbsp;
     <span style="color: #ff7700;font-weight:bold;">return</span> d
&nbsp;
&nbsp;
&nbsp;
 <span style="color: #ff7700;font-weight:bold;">def</span> dmerge4<span style="color: black;">&#40;</span>d1, d2, merge_func=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
     <span style="color: #483d8b;">&quot;&quot;&quot;
         Le code original, en virant la lambda
     &quot;&quot;&quot;</span>
     d = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
&nbsp;
     <span style="color: #ff7700;font-weight:bold;">if</span> merge_func <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">None</span>:
         d.<span style="color: black;">update</span><span style="color: black;">&#40;</span>d1<span style="color: black;">&#41;</span>
         d.<span style="color: black;">update</span><span style="color: black;">&#40;</span>d2<span style="color: black;">&#41;</span>
         <span style="color: #ff7700;font-weight:bold;">return</span> d
&nbsp;
     d.<span style="color: black;">update</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#40;</span>k, v<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> d1.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> k <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> d2<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
     d.<span style="color: black;">update</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#40;</span>k, v<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> d2.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> k <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> d1<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
     d.<span style="color: black;">update</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#40;</span>k, merge_func<span style="color: black;">&#40;</span>v, d2<span style="color: black;">&#91;</span>k<span style="color: black;">&#93;</span><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> d1.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> k <span style="color: #ff7700;font-weight:bold;">in</span> d2<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
     <span style="color: #ff7700;font-weight:bold;">return</span> d
&nbsp;
&nbsp;
 <span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
&nbsp;
     <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">random</span>
     <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">timeit</span>
&nbsp;
     <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Generate test dicts'</span><span style="color: black;">&#41;</span>
&nbsp;
     <span style="color: #808080; font-style: italic;"># pour que le test soit juste, il faut créer plusieurs types de dicos:</span>
     <span style="color: #808080; font-style: italic;"># des longs, et des courts avec plein de collisions ou moins</span>
     d1 = <span style="color: black;">&#123;</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: #483d8b;">'d1'</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">xrange</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10000</span><span style="color: black;">&#41;</span><span style="color: black;">&#125;</span>
     d2 = <span style="color: black;">&#123;</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: #483d8b;">'d2'</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">xrange</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10000</span><span style="color: black;">&#41;</span><span style="color: black;">&#125;</span>
     d3 = <span style="color: black;">&#123;</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;">10000000</span><span style="color: black;">&#41;</span>: <span style="color: #483d8b;">'d1'</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">xrange</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1000000</span><span style="color: black;">&#41;</span><span style="color: black;">&#125;</span>
     d4 = <span style="color: black;">&#123;</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;">10000000</span><span style="color: black;">&#41;</span>: <span style="color: #483d8b;">'d2'</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">xrange</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1000000</span><span style="color: black;">&#41;</span><span style="color: black;">&#125;</span>
&nbsp;
     merge_to_list = <span style="color: #ff7700;font-weight:bold;">lambda</span> a, b: <span style="color: black;">&#91;</span>a, b<span style="color: black;">&#93;</span>
&nbsp;
     <span style="color: #808080; font-style: italic;"># ensuite il faut s'assurer que toutes ces fonctions retournent bien</span>
     <span style="color: #808080; font-style: italic;"># la même chose</span>
&nbsp;
     <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Testing returns value all match&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
     <span style="color: #ff7700;font-weight:bold;">assert</span> <span style="color: black;">&#40;</span>dmerge1<span style="color: black;">&#40;</span>d1, d2<span style="color: black;">&#41;</span> == dmerge2<span style="color: black;">&#40;</span>d1, d2<span style="color: black;">&#41;</span>
             == dmerge3<span style="color: black;">&#40;</span>d1, d2<span style="color: black;">&#41;</span> == dmerge4<span style="color: black;">&#40;</span>d1, d2<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
     <span style="color: #ff7700;font-weight:bold;">assert</span> <span style="color: black;">&#40;</span>dmerge1<span style="color: black;">&#40;</span>d1, d2, merge_to_list<span style="color: black;">&#41;</span> == dmerge2<span style="color: black;">&#40;</span>d1, d2, merge_to_list<span style="color: black;">&#41;</span>
            == dmerge3<span style="color: black;">&#40;</span>d1, d2, merge_to_list<span style="color: black;">&#41;</span> == dmerge4<span style="color: black;">&#40;</span>d1, d2, merge_to_list<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
     <span style="color: #ff7700;font-weight:bold;">assert</span> <span style="color: black;">&#40;</span>dmerge1<span style="color: black;">&#40;</span>d3, d4<span style="color: black;">&#41;</span> == dmerge2<span style="color: black;">&#40;</span>d3, d4<span style="color: black;">&#41;</span>
             == dmerge3<span style="color: black;">&#40;</span>d3, d4<span style="color: black;">&#41;</span> == dmerge4<span style="color: black;">&#40;</span>d3, d4<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
     <span style="color: #ff7700;font-weight:bold;">assert</span> <span style="color: black;">&#40;</span>dmerge1<span style="color: black;">&#40;</span>d3, d4, merge_to_list<span style="color: black;">&#41;</span> == dmerge2<span style="color: black;">&#40;</span>d3, d4, merge_to_list<span style="color: black;">&#41;</span>
             == dmerge3<span style="color: black;">&#40;</span>d3, d4, merge_to_list<span style="color: black;">&#41;</span> == dmerge4<span style="color: black;">&#40;</span>d3, d4, merge_to_list<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
     <span style="color: #ff7700;font-weight:bold;">assert</span> <span style="color: black;">&#40;</span>dmerge1<span style="color: black;">&#40;</span>d1, d4<span style="color: black;">&#41;</span> == dmerge2<span style="color: black;">&#40;</span>d1, d4<span style="color: black;">&#41;</span>
             == dmerge3<span style="color: black;">&#40;</span>d1, d4<span style="color: black;">&#41;</span> == dmerge4<span style="color: black;">&#40;</span>d1, d4<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
     <span style="color: #ff7700;font-weight:bold;">assert</span> <span style="color: black;">&#40;</span>dmerge1<span style="color: black;">&#40;</span>d1, d4, merge_to_list<span style="color: black;">&#41;</span> == dmerge2<span style="color: black;">&#40;</span>d1, d4, merge_to_list<span style="color: black;">&#41;</span>
             == dmerge3<span style="color: black;">&#40;</span>d1, d4, merge_to_list<span style="color: black;">&#41;</span> == dmerge4<span style="color: black;">&#40;</span>d1, d4, merge_to_list<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
     <span style="color: #808080; font-style: italic;"># enfin on lance l'évaluation du temps d'éxécution avec timeit()</span>
&nbsp;
     <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Start timing&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
     <span style="color: #808080; font-style: italic;"># ce code est exécuté une fois par appel de timeit</span>
     <span style="color: #808080; font-style: italic;"># notez l'astuce 'from __main__ import x' qui importe du code</span>
     <span style="color: #808080; font-style: italic;"># du fichier en cours, ce qui sert rarement</span>
     setup = <span style="color: #483d8b;">''</span><span style="color: #483d8b;">'from __main__ import (dmerge1, dmerge2, dmerge3, dmerge4,
                                      d1, d2, d3, d4, merge_to_list)'</span><span style="color: #483d8b;">''</span>
&nbsp;
&nbsp;
&nbsp;
     <span style="color: #808080; font-style: italic;"># ensuite on fait des appels à timeit : </span>
     <span style="color: #808080; font-style: italic;"># - le premier paramètre est le code à mesurer: il faut qu'il </span>
     <span style="color: #808080; font-style: italic;">#   soit le plus simple et court possible</span>
     <span style="color: #808080; font-style: italic;"># - le second et le code d'initialisation avant le test (hors mesure)</span>
     <span style="color: #808080; font-style: italic;"># - le 3e est le nombre de fois que le code va être appelé. </span>
&nbsp;
&nbsp;
     <span style="color: #808080; font-style: italic;"># on va tester chaque fonction pour chaque type de dico, une fois</span>
     <span style="color: #808080; font-style: italic;"># avec l'approche par défaut, et une fois avec une fonction de merge</span>
     <span style="color: #808080; font-style: italic;"># personnalisée</span>
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Lots of collisions&quot;</span>
&nbsp;
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Default merge strategy&quot;</span>
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;1&quot;</span>, <span style="color: #dc143c;">timeit</span>.<span style="color: #dc143c;">timeit</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dmerge1(d1, d2)&quot;</span>, setup=setup, number=<span style="color: #ff4500;">1000000</span><span style="color: black;">&#41;</span>
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;2&quot;</span>, <span style="color: #dc143c;">timeit</span>.<span style="color: #dc143c;">timeit</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dmerge2(d1, d2)&quot;</span>, setup=setup, number=<span style="color: #ff4500;">1000000</span><span style="color: black;">&#41;</span>
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;3&quot;</span>, <span style="color: #dc143c;">timeit</span>.<span style="color: #dc143c;">timeit</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dmerge3(d1, d2)&quot;</span>, setup=setup, number=<span style="color: #ff4500;">1000000</span><span style="color: black;">&#41;</span>
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;4&quot;</span>, <span style="color: #dc143c;">timeit</span>.<span style="color: #dc143c;">timeit</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dmerge4(d1, d2)&quot;</span>, setup=setup, number=<span style="color: #ff4500;">1000000</span><span style="color: black;">&#41;</span>
&nbsp;
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Custom merge strategy&quot;</span>
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;1&quot;</span>, <span style="color: #dc143c;">timeit</span>.<span style="color: #dc143c;">timeit</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dmerge1(d1, d2, merge_to_list)&quot;</span>,
                               setup=setup, number=<span style="color: #ff4500;">100000</span><span style="color: black;">&#41;</span>
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;2&quot;</span>, <span style="color: #dc143c;">timeit</span>.<span style="color: #dc143c;">timeit</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dmerge2(d1, d2, merge_to_list)&quot;</span>,
                               setup=setup, number=<span style="color: #ff4500;">100000</span><span style="color: black;">&#41;</span>
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;3&quot;</span>, <span style="color: #dc143c;">timeit</span>.<span style="color: #dc143c;">timeit</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dmerge3(d1, d2, merge_to_list)&quot;</span>,
                               setup=setup, number=<span style="color: #ff4500;">100000</span><span style="color: black;">&#41;</span>
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;4&quot;</span>, <span style="color: #dc143c;">timeit</span>.<span style="color: #dc143c;">timeit</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dmerge4(d1, d2, merge_to_list)&quot;</span>,
                               setup=setup, number=<span style="color: #ff4500;">100000</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
    <span style="color: #808080; font-style: italic;"># le nombre de répétitions est bien plus faible ici car sinon le test</span>
    <span style="color: #808080; font-style: italic;"># est très très long</span>
&nbsp;
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Long dictionaries&quot;</span>
&nbsp;
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Default merge strategy&quot;</span>
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;1&quot;</span>, <span style="color: #dc143c;">timeit</span>.<span style="color: #dc143c;">timeit</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dmerge1(d3, d4)&quot;</span>, setup=setup, number=<span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;2&quot;</span>, <span style="color: #dc143c;">timeit</span>.<span style="color: #dc143c;">timeit</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dmerge2(d3, d4)&quot;</span>, setup=setup, number=<span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;3&quot;</span>, <span style="color: #dc143c;">timeit</span>.<span style="color: #dc143c;">timeit</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dmerge3(d3, d4)&quot;</span>, setup=setup, number=<span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;4&quot;</span>, <span style="color: #dc143c;">timeit</span>.<span style="color: #dc143c;">timeit</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dmerge4(d3, d4)&quot;</span>, setup=setup, number=<span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
&nbsp;
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Custom merge strategy&quot;</span>
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;1&quot;</span>, <span style="color: #dc143c;">timeit</span>.<span style="color: #dc143c;">timeit</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dmerge1(d3, d4, merge_to_list)&quot;</span>,
                               setup=setup, number=<span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;2&quot;</span>, <span style="color: #dc143c;">timeit</span>.<span style="color: #dc143c;">timeit</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dmerge2(d3, d4, merge_to_list)&quot;</span>,
                               setup=setup, number=<span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;3&quot;</span>, <span style="color: #dc143c;">timeit</span>.<span style="color: #dc143c;">timeit</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dmerge3(d3, d4, merge_to_list)&quot;</span>,
                               setup=setup, number=<span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;4&quot;</span>, <span style="color: #dc143c;">timeit</span>.<span style="color: #dc143c;">timeit</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dmerge4(d3, d4, merge_to_list)&quot;</span>,
                               setup=setup, number=<span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
&nbsp;
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Mixed dictionaries&quot;</span>
&nbsp;
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Default merge strategy&quot;</span>
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;1&quot;</span>, <span style="color: #dc143c;">timeit</span>.<span style="color: #dc143c;">timeit</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dmerge1(d1, d4)&quot;</span>, setup=setup, number=<span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;2&quot;</span>, <span style="color: #dc143c;">timeit</span>.<span style="color: #dc143c;">timeit</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dmerge2(d1, d4)&quot;</span>, setup=setup, number=<span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;3&quot;</span>, <span style="color: #dc143c;">timeit</span>.<span style="color: #dc143c;">timeit</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dmerge3(d1, d4)&quot;</span>, setup=setup, number=<span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;4&quot;</span>, <span style="color: #dc143c;">timeit</span>.<span style="color: #dc143c;">timeit</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dmerge4(d1, d4)&quot;</span>, setup=setup, number=<span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
&nbsp;
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Custom merge strategy&quot;</span>
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;1&quot;</span>, <span style="color: #dc143c;">timeit</span>.<span style="color: #dc143c;">timeit</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dmerge1(d1, d4, merge_to_list)&quot;</span>,
                              setup=setup, number=<span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;2&quot;</span>, <span style="color: #dc143c;">timeit</span>.<span style="color: #dc143c;">timeit</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dmerge2(d1, d4, merge_to_list)&quot;</span>,
                              setup=setup, number=<span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;3&quot;</span>, <span style="color: #dc143c;">timeit</span>.<span style="color: #dc143c;">timeit</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dmerge3(d1, d4, merge_to_list)&quot;</span>,
                              setup=setup, number=<span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
     <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;4&quot;</span>, <span style="color: #dc143c;">timeit</span>.<span style="color: #dc143c;">timeit</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;dmerge4(d1, d4, merge_to_list)&quot;</span>,
                              setup=setup, number=<span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;"># Et voici le résultat que ça nous ressort. On voit clairement </span>
<span style="color: #808080; font-style: italic;"># que la 3eme fonction donne les meilleurs perfs, du coup</span>
<span style="color: #808080; font-style: italic;"># c'est celle qu'on a choisit</span>
&nbsp;
 <span style="color: #808080; font-style: italic;">## Generate test dicts</span>
 <span style="color: #808080; font-style: italic;">## Testing returns value all match</span>
 <span style="color: #808080; font-style: italic;">## Start timing</span>
 <span style="color: #808080; font-style: italic;">## Lots of collisions</span>
 <span style="color: #808080; font-style: italic;">## Default merge strategy</span>
 <span style="color: #808080; font-style: italic;">## 1 19.9299340248</span>
 <span style="color: #808080; font-style: italic;">## 2 148.185166121</span>
 <span style="color: #808080; font-style: italic;">## 3 21.2276539803</span>
 <span style="color: #808080; font-style: italic;">## 4 21.2074358463</span>
 <span style="color: #808080; font-style: italic;">## Custom merge strategy</span>
 <span style="color: #808080; font-style: italic;">## 1 30.646312952</span>
 <span style="color: #808080; font-style: italic;">## 2 18.522135973</span>
 <span style="color: #808080; font-style: italic;">## 3 14.0125968456</span>
 <span style="color: #808080; font-style: italic;">## 4 18.5139119625</span>
 <span style="color: #808080; font-style: italic;">## Long dictionaries</span>
 <span style="color: #808080; font-style: italic;">## Default merge strategy</span>
 <span style="color: #808080; font-style: italic;">## 1 84.4819910526</span>
 <span style="color: #808080; font-style: italic;">## 2 383.444111109</span>
 <span style="color: #808080; font-style: italic;">## 3 80.7273669243</span>
 <span style="color: #808080; font-style: italic;">## 4 86.0287930965</span>
 <span style="color: #808080; font-style: italic;">## Custom merge strategy</span>
 <span style="color: #808080; font-style: italic;">## 1 294.41114521</span>
 <span style="color: #808080; font-style: italic;">## 2 377.38009119</span>
 <span style="color: #808080; font-style: italic;">## 3 154.505481005</span>
 <span style="color: #808080; font-style: italic;">## 4 256.771039963</span>
 <span style="color: #808080; font-style: italic;">## Mixed dictionaries</span>
 <span style="color: #808080; font-style: italic;">## Default merge strategy</span>
 <span style="color: #808080; font-style: italic;">## 1 19.9574320316</span>
 <span style="color: #808080; font-style: italic;">## 2 87.1410660744</span>
 <span style="color: #808080; font-style: italic;">## 3 19.3570361137</span>
 <span style="color: #808080; font-style: italic;">## 4 19.524998188</span>
 <span style="color: #808080; font-style: italic;">## Custom merge strategy</span>
 <span style="color: #808080; font-style: italic;">## 1 60.6157000065</span>
 <span style="color: #808080; font-style: italic;">## 2 86.3876900673</span>
 <span style="color: #808080; font-style: italic;">## 3 59.0331327915</span>
 <span style="color: #808080; font-style: italic;">## 4 87.0504939556</span>
 <span style="color: #808080; font-style: italic;">## [Finished in 2494.7s]</span></pre></div></div>

<p> Le test complet a pris en tout 2494.7s, soit 41 minutes, pour tourner sur ma machine, et je l&#8217;ai lancé plusieurs fois avec différentes modifs au fil de la journée. Il faut vraiment est un geek pour aimer faire ce genre de connerie. Parce que soyons honnête, tout le monde s&#8217;en branle des perfs de cette fonction :-)</p>
<p> Il faut savoir aussi qu&#8217;après coup j&#8217;ai réalisé que son code utilisait des listes en intention, et non des <a href="http://sametmax.com/python-love-les-listes-en-intention-partie-2/">expressions génératrices</a>, ce qui fait qu&#8217;il faut attendre que toute la liste soit générée avec que <code>update()</code> fasse son travail.</p>
<p> Il y avait donc des cas supplémentaires à tester et j&#8217;avais mergé son code dans batbelt. Arf, l&#8217;optimisation n&#8217;a jamais de fin ^^</p>
<p> Bref, j&#8217;ai relancé un test avec avec des listes en intentions (et même avec des expressions ternaires ce qui donne des trucs capilotractés):</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> dmerge1<span style="color: black;">&#40;</span>d1, d2, merge_func=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
        Une version de l'ancien dmerge3 qui utilise une expression génératrice.
    &quot;&quot;&quot;</span>
    d = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
&nbsp;
    d.<span style="color: black;">update</span><span style="color: black;">&#40;</span>d1<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> merge_func <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">None</span>:
        d.<span style="color: black;">update</span><span style="color: black;">&#40;</span>d2<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> d
&nbsp;
    d.<span style="color: black;">update</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>k, <span style="color: black;">&#40;</span>v <span style="color: #ff7700;font-weight:bold;">if</span> k <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> d <span style="color: #ff7700;font-weight:bold;">else</span> merge_func<span style="color: black;">&#40;</span>d<span style="color: black;">&#91;</span>k<span style="color: black;">&#93;</span>, v<span style="color: black;">&#41;</span><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> d2.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> d
&nbsp;
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> dmerge2<span style="color: black;">&#40;</span>d1, d2, merge_func=<span style="color: #ff7700;font-weight:bold;">lambda</span> v1, v2: v2<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
        La version du proposée par notre gentil contributeur, mais
        avec des expressions génératrices à la place des listes en 
        intention.
    &quot;&quot;&quot;</span>
    d = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
    d.<span style="color: black;">update</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>k, v<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> d1.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> k <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> d2<span style="color: black;">&#41;</span>
    d.<span style="color: black;">update</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>k, v<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> d2.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> k <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> d1<span style="color: black;">&#41;</span>
    d.<span style="color: black;">update</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>k, merge_func<span style="color: black;">&#40;</span>v, d2<span style="color: black;">&#91;</span>k<span style="color: black;">&#93;</span><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> d1.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> k <span style="color: #ff7700;font-weight:bold;">in</span> d2<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> d
&nbsp;
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> dmerge3<span style="color: black;">&#40;</span>d1, d2, merge_func=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
      La version la plus rapide du test précédent.
    &quot;&quot;&quot;</span>
    d = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
&nbsp;
    d.<span style="color: black;">update</span><span style="color: black;">&#40;</span>d1<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> merge_func <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">None</span>:
        d.<span style="color: black;">update</span><span style="color: black;">&#40;</span>d2<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> d
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">for</span> k, v <span style="color: #ff7700;font-weight:bold;">in</span> d2.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> k <span style="color: #ff7700;font-weight:bold;">in</span> d:
            d<span style="color: black;">&#91;</span>k<span style="color: black;">&#93;</span> = merge_func<span style="color: black;">&#40;</span>d<span style="color: black;">&#91;</span>k<span style="color: black;">&#93;</span>, v<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            d<span style="color: black;">&#91;</span>k<span style="color: black;">&#93;</span> = v
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> d
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> dmerge4<span style="color: black;">&#40;</span>d1, d2, merge_func=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
        La version proposée par notre contributeur, optimisée comme un connard.
    &quot;&quot;&quot;</span>
    d = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> merge_func <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">None</span>:
        d.<span style="color: black;">update</span><span style="color: black;">&#40;</span>d1<span style="color: black;">&#41;</span>
        d.<span style="color: black;">update</span><span style="color: black;">&#40;</span>d2<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> d
&nbsp;
    d.<span style="color: black;">update</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>k, v<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> d1.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> k <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> d2<span style="color: black;">&#41;</span>
    d.<span style="color: black;">update</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>k, v<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> d2.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> k <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> d1<span style="color: black;">&#41;</span>
    d.<span style="color: black;">update</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>k, merge_func<span style="color: black;">&#40;</span>v, d2<span style="color: black;">&#91;</span>k<span style="color: black;">&#93;</span><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> d1.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> k <span style="color: #ff7700;font-weight:bold;">in</span> d2<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> d
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;">## Generate test dicts</span>
<span style="color: #808080; font-style: italic;">## Testing returns value all match</span>
<span style="color: #808080; font-style: italic;">## Start timing</span>
<span style="color: #808080; font-style: italic;">## Lots of collisions</span>
<span style="color: #808080; font-style: italic;">## Default merge strategy</span>
<span style="color: #808080; font-style: italic;">## 1 12.2690660954</span>
<span style="color: #808080; font-style: italic;">## 2 97.121183157</span>
<span style="color: #808080; font-style: italic;">## 3 12.1084120274</span>
<span style="color: #808080; font-style: italic;">## 4 12.6807589531</span>
<span style="color: #808080; font-style: italic;">## Custom merge strategy</span>
<span style="color: #808080; font-style: italic;">## 1 8.73903894424</span>
<span style="color: #808080; font-style: italic;">## 2 12.0493769646</span>
<span style="color: #808080; font-style: italic;">## 3 8.00074601173</span>
<span style="color: #808080; font-style: italic;">## 4 11.4764301777</span>
<span style="color: #808080; font-style: italic;">## Long dictionaries</span>
<span style="color: #808080; font-style: italic;">## Default merge strategy</span>
<span style="color: #808080; font-style: italic;">## 1 54.5233860016</span>
<span style="color: #808080; font-style: italic;">## 2 218.695598841</span>
<span style="color: #808080; font-style: italic;">## 3 70.213809967</span>
<span style="color: #808080; font-style: italic;">## 4 61.8348701</span>
<span style="color: #808080; font-style: italic;">## Custom merge strategy</span>
<span style="color: #808080; font-style: italic;">## 1 103.258821964</span>
<span style="color: #808080; font-style: italic;">## 2 217.720175982</span>
<span style="color: #808080; font-style: italic;">## 3 96.5204670429</span>
<span style="color: #808080; font-style: italic;">## 4 214.480421066</span>
<span style="color: #808080; font-style: italic;">## Mixed dictionaries</span>
<span style="color: #808080; font-style: italic;">## Default merge strategy</span>
<span style="color: #808080; font-style: italic;">## 1 19.169850111</span>
<span style="color: #808080; font-style: italic;">## 2 66.9599928856</span>
<span style="color: #808080; font-style: italic;">## 3 19.4371211529</span>
<span style="color: #808080; font-style: italic;">## 4 19.5183057785</span>
<span style="color: #808080; font-style: italic;">## Custom merge strategy</span>
<span style="color: #808080; font-style: italic;">## 1 64.7940750122</span>
<span style="color: #808080; font-style: italic;">## 2 66.9712991714</span>
<span style="color: #808080; font-style: italic;">## 3 58.5918440819</span>
<span style="color: #808080; font-style: italic;">## 4 67.5281140804</span>
<span style="color: #808080; font-style: italic;">## [Finished in 1619.3s]</span></pre></div></div>

<p>La bonne nouvelle pour moi, c&#8217;est que l&#8217;algo 3 est toujours le plus rapide, j&#8217;ai pas à re pusher.</p>
<p>Mais il est intéressant de constater que globalement les 4 tests mettent 1619.3s à s’exécuter. Globalement utiliser des expressions génératrices boost bien les perfs.</p>
<hr />
<p><a href="https://github.com/sametmax/codes-des-articles/blob/master/2013/juin/perf.py">Télécharger le code de l&#8217;article.</a></p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6369&amp;md5=2a38eaff3f2a26f2b60529ac3e370e94" 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=6384
title: Que s’est-il passé en 2006 ?
uri: Que-s-est-il-passé-en-2006
url: http://sametmax.com/que-sest-il-passe-en-2006/
content:
<p>Bon sam est pas là alors je fais le con :)</p>
<p>Lançons un débat hautement philosophique sur cette mystèrieuse année 2006 qui restera je n&#8217;en doute pas dans les annales&#8230;</p>
<p style="text-align: center;"><img class="aligncenter  wp-image-6385" title="2006, une année choc!" src="media/d37b9294.R4rCz.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/R4rCz.jpg" alt="" width="505" height="372" /></p>
<p>&nbsp;</p>
<p>J&#8217;attends vos explications. N&#8217;ayez pas honte je suis un ancien pianiste.</p>
<p>&nbsp;</p>
<p>PS: Moi je pense que ça a à voir avec le film Bareback Mountain sorti fin 2005. c&#8217;est une théorie&#8230;</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6384&amp;md5=0d98f80953f52adc084ddd3de56a2250" 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=6395
title: Django, une app à la fois
uri: Django-une-app-à-la-fois
url: http://sametmax.com/django-une-app-a-la-fois/
content:
<p>Hello gens.</p>
<p>Pendant ma petite absence, j&#8217;ai concocté un nouveau concept : les cookbooks exécutables autonomes à sens giratoire inversé.</p>
<p>Le principe est simple, je fournis une liste de recettes sous forme de code commenté qui fonctionne, et qui font une tâche commune.</p>
<p>Je vais commencer par Django, car il en a vraiment besoin. Voici donc, &#8220;<a href="https://github.com/sametmax/Django--an-app-at-a-time/tree/fran%C3%A7ais">Django, une app à la fois</a>&#8220;, disponible en anglais et en français.</p>
<p>Il n&#8217;y a rien à faire sinon télécharger le truc, et le lancer, puis faire mumuse avec. Quand on veut savoir comment un snippet marche, on regarde les sources.</p>
<p>Pour le moment il n&#8217;y a que deux apps et un fichier de settings commentés avec amour. Néanmoins le but est d&#8217;ajouter de temps en temps une app par ci, par là.</p>
<p>Si la formule a du succès, je le ferai pour d&#8217;autres outils : Python pur, fabric, bottle, south, que sais-je.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6395&amp;md5=597411db60828b4f6b36350b174f6969" 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=6407
title: Vive les femmes qui simulent !
uri: Vive-les-femmes-qui-simulent
url: http://sametmax.com/vive-les-femmes-qui-simulent/
content:
<p>Combien de fois j&#8217;ai entendu cette réplique ou une variante : &#8220;moi les femmes elles simulent jamais avec moi.&#8221;</p>
<p>Quand on me pose la question : &#8220;est-ce que tu penses qu&#8217;elle simule ?&#8221;, généralement ma réponse c&#8217;est &#8220;j&#8217;espère bien !&#8221;.</p>
<p>Souvenez vous: le cul, c&#8217;est la dînette des adultes. Quand on a pas d&#8217;objectif de procréation, on est là pour s&#8217;amuser, sinon à quoi bon ?</p>
<p>Or, il faut bien avouer, des petits cris par ci, des gros râles par là, c&#8217;est vachement enthousiasmant. Chacun a sa manière, ce qui rend l&#8217;expérience unique, mais je pense qu&#8217;on est tous d&#8217;accord sur le fait que baiser avec une personne qui reste de marbre, ça fait un peu nécrophilie.</p>
<div id="attachment_6411" class="wp-caption aligncenter" style="width: 442px"><a href="media/296d2669.oo3N60V.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/oo3N60V.jpg"><img class=" wp-image-6411 " title="Regardez comme ils s'emmerdent. Non mais sérieux, quel intérerêt de partouser si c'est pour faire la gueule ?" src="media/296d2669.oo3N60V.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/oo3N60V.jpg" alt="Photo d'un group de kangourou" width="432" height="289" /></a><p class="wp-caption-text">Regardez comme ils s&#39;emmerdent. Non mais sérieux, quel intérerêt de partouser si c&#39;est pour faire la gueule ?</p></div>
<p>Et bien entendu, toutes les parties de jambe en l&#8217;air ne sont pas l&#8217;extase absolue :</p>
<ul>
<li>Vous ne connaissez pas forcément encore bien la personne. Les coups d&#8217;un soir, c&#8217;est un pile ou face, vous aimez pas nécessairement les mêmes choses mais bon, là, vous êtes à poil, alors va falloir faire avec.</li>
<li>Parfois vous êtes fatigué, ou elle, ou pas dans le mood.</li>
<li>Vous avez envie d&#8217;une levrette pékinoise et elle se sent plutôt humeur brouette congolaise.</li>
<li>Quelqu&#8217;un à manger de l&#8217;oignon, des flageolais ou un troisième dessert.</li>
<li>C&#8217;est la 4eme fois dans la journée.</li>
<li>Vous êtes nul aujourd&#8217;hui. Y a des jours comme ça&#8230;</li>
<li>Etc</li>
</ul>
<p>Est-ce une raison pour se faire chier sous la couette ? Non. A la dînette, on dirait que toi tu serais la marchande, et moi je serais le voleur à l&#8217;étalage.</p>
<p>Et bien là on fait pareil, on simule. Et c&#8217;est vachement plus sympa, souvent ça permet même de chauffer le moteur et de laisser la place à la vraie bonne humeur.</p>
<div id="attachment_6410" class="wp-caption aligncenter" style="width: 428px"><a href="media/3d5aea7f.zaargfT.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/zaargfT.jpg"><img class=" wp-image-6410  " title="Un peu d'artificiel permet parfois l'étincelle qui fait déborder le vase de la limite" src="media/3d5aea7f.zaargfT.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/06/zaargfT.jpg" alt="Composition photographique montrant la rencontre d'un couple, l'un tenant chalumeau, l'autre des feux d'artifices" width="418" height="271" /></a><p class="wp-caption-text">Un peu d&#39;artificiel permet parfois l&#39;étincelle qui fait déborder le vase de la limite</p></div>
<p>Bref, tout comme <a href="http://www.jde.fr/article/un-sourire-meme-force-c-est-bon-pour-la-sante---2528">se forcer à sourire</a> quand on en a pas envie a été prouvé scientifiquement comme améliorant sa journée et son moral, simuler le plaisir voir l&#8217;orgasme, c&#8217;est bon pour votre cul.</p>
<p>D&#8217;ailleurs, même sur le long terme c&#8217;est une bonne chose.</p>
<p>Par exemple, moi il m&#8217;arrive de ne pas venir du tout. Ça reste coincé. Bon, pas un drame, mais après moult galipettes, ça frustre généralement la demoiselle, surtout si elle s&#8217;est donné à fond sur l&#8217;examen oral. Là, on repart dans une position coquine, je fais genre &#8220;youppiiiiiiiiiiiiii&#8221;, et tout le monde est content. Ça évite les angoisses des filles qui ont généralement la confiance en soi d&#8217;un auvergnat devant un alcootest, des discussions inutiles, et plus d&#8217;énergie pour la prochaine sieste crapuleuse.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6407&amp;md5=6bf21fe8984ae9760fcd8ba407ca6d95" 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=6419
title: Tiens, je suis toujours sur OSX
uri: Tiens-je-suis-toujours-sur-OSX
url: http://sametmax.com/tiens-je-suis-toujours-sur-osx/
content:
<p style="text-align: center;"><em><small>Ceci est un post invité de <a href="http://sametmax.com/author/coyote/">coyote</a> posté sous licence <a href="http://creativecommons.org/licenses/by/3.0/">creative common 3.0 unported</a>.</small></em></p>
<p><strong>Attention</strong>: ce qui suit est un billet d&#8217;humeur personnel. Prenez le comme tel…</p>
<p>Je suis un <em>linuxien</em>. Pas un activiste, mais tout de même un fervent défenseur du logiciel libre et de Linux (oui pour moi écrire <em>GNU/Linux</em> partout c&#8217;est pédant et inutile – et ça te fait passer pour un gros nazi.). J&#8217;ai même créé une association de défense du libre, un <acronym title="Linux User Group">LUG</acronym> et fait <em>switcher</em> de très nombreuses personnes.</p>
<h2>Mais alors, <strong>bordel, que fais-je sur<sup>1</sup> OSX ?</strong></h2>
<p><sup>1</sup> Si quelqu&#8217;un a une règle pour décrire rapidement que l&#8217;on utilise un OS, en lieu et place de “<em>sur Ubuntu</em>”, “<em>sous Windows</em>’”, etc ; qu&#8217;il la balance car c&#8217;est juste insupportable.</p>
<p>Tout à commencé sans doute quand j&#8217;ai découvert Sublime Text (merci Sam!). J&#8217;ai alors rompu mon workflow entièrement libre pour y intégrer un outil proprio, mais fantastique et dont je me suis précipité pour payer la licence afin de remercier le développeur pour cette bouffée d&#8217;oxygène.</p>
<p>J&#8217;utilise régulièrement des Mac comme machine depuis plusieurs années (2003?) et ce pour plusieurs raisons:</p>
<ul>
<li>C&#8217;est propre. Pas de sticker dégueulasse, de look plastique ou autre.</li>
<li>C&#8217;est une grande marque avec peu de modèles: l&#8217;assurance d&#8217;avoir un support pour Linux relativement rapidement.</li>
<li>C&#8217;est de bonne qualité (oui il y a toujours des exceptions), ça dure longtemps et ça se revend pas trop mal.</li>
<li>Le connecteur d&#8217;alim aimanté ; tous ceux qui ont déjà cassé un laptop à cause de ça comprendront…</li>
<li>Je fais un peu de dev multiplateforme (libre!) et il faut toujours tester/ajuster sur OSX.</li>
</ul>
<p>Me voilà donc avec une machine Mac dont je suis satisfait, faisant tourner un Ubuntu que j&#8217;adore avec un dual boot que j&#8217;utilise dans les aéroports ou autre car la conso batterie est <strong>incomparable</strong> entre Ubuntu et OSX.</p>
<p>Linux a toujours eu des petits problèmes, la batterie dont je parlais, le WiFi, le suspend/hibernation, etc. Rien d&#8217;insurmontable pour quelqu&#8217;un de convaincu.</p>
<h2>L&#8217;aigle noir</h2>
<p>Soudain, je sais plus exactement vers quelle version, je crois que c&#8217;était la 10.10, Ubuntu a commencé à devenir de plus en plus pénible et les nouvelles versions n&#8217;ont fait qu&#8217;accroitre la frustration.</p>
<p>Le passage à Unity a été difficile, et le fait de tester d&#8217;autres alternatives (XFCE, Xmonad) permet de se rendre compte à quel point Ubuntu est <em>intégré</em>: beaucoup de composants ne sont plus vraiment interchangeable ou alors au prix de gros efforts de configurations voir de hacks. En bref, <strong>Ubuntu, c&#8217;est bien si tu y touches pas trop</strong>.</p>
<p>Au fil des versions, des nouveaux problèmes, des fonctionnalités perdues, toute tentative montrant à quel point Ubuntu s&#8217;écarte du Linux modulaire, j&#8217;ai décidé de franchir le Rubicon et de tester d&#8217;autres distros.</p>
<p>Pour faire (très) court :</p>
<ul>
<li>Toutes les non-debian ne m&#8217;ont pas plus: la gestion des paquets est contre-productive pour moi qui ait des années d&#8217;apt dans les dents. Surtout, c&#8217;est <strong>lent comme la mort</strong>. Incroyablement lent en 2013 ; WTF?</li>
<li>Les debian-ubuntu-based: la plupart sont des customisations d&#8217;Ubuntu avec des paquets différents, des thèmes et des outils. J&#8217;ai pas vu d&#8217;avantages vraiment et toutes ont des petits désagréments supplémentaires, sans compter que les problèmes spécifiques sont dur à résoudre car ils ont peu d&#8217;utilisateurs.</li>
<li>debian ; j&#8217;ai beaucoup aimé car c&#8217;est très simple, la modularité est là, la vitesse aussi ; c&#8217;est bien intégré. Malheureusement, la gestion non souple des paquets (soit tout est vieux, soit tout est jeune) couplé avec l&#8217;absence de PPA (<strong>les PPA, c&#8217;est génial!</strong>) font que j&#8217;ai renoncé.</li>
</ul>
<h2>Archlinux</h2>
<p>Je suis donc resté sur Archlinux. J&#8217;avais utilisé un peu par le passé et ça correspondait bien à ce que je voulais actuellement: quelque chose de propre, documenté ou je savais qu&#8217;en cas de problème, je pourrais l&#8217;identifier facilement.</p>
<p>Archlinux m&#8217;a prit du temps pour le configurer. C&#8217;est sans doute ce qui m&#8217;a le plus dérangé car <strong>j&#8217;utilise mon laptop pour travailler</strong>, pas pour geeker. Une journée de perdue à configurer la machine, c&#8217;est une journée de travail en moins avec des conséquences en sousous.</p>
<p>Mais j&#8217;étais satisfait d&#8217;Archlinux, c&#8217;était effectivement beaucoup plus simple et clair qu&#8217;Ubuntu. J&#8217;ai pu faire fonctionner des petites choses qui marchaient pas avec Ubuntu ; j&#8217;avais un Gnome à jour, etc.</p>
<p>Mais, car il y a toujours un mais ; Archlinux a aussi ses problèmes: il <strong>veut</strong> que vous soyez à jour, et vous avez pas intérêt à le contrarier ; mais en même temps, il faut vérifier ce qu&#8217;il fait donc re-perte de temps.</p>
<p>Au fil du temps, les problèmes des logiciels récents se faisaient plus frustrants ; une version qui marche ; une qui marche pas, etc.</p>
<p>Quand je me suis rendu compte que je devais redémarrer ma machine plus d&#8217;une fois par semaine, et que je perdais vraiment du temps avec des bêtises, je me suis dis “<em>oh et puis merde, je vais mettre OSX!</em>” (oui je reste relativement poli dans ma tête).</p>
<h2>Le trou noir</h2>
<p>J&#8217;ai formatté ma machine sur un coup de tête, un week-end, pour voir si vraiment Linux devenait de la fiente d&#8217;âne ou si c&#8217;était partout pareil. Je me suis dis, ce sera l&#8217;occasion de voir à quoi ressemble la concurrence, de voir comment se comporte cette machine dans son environnement naturel (genre voir ce que ça fait d&#8217;utiliser un SSD qui a couté la peau du Q). Je voulais tester ça une semaine, deux tout au plus.</p>
<p>C&#8217;était il y a des mois déjà. Je sais plus trop quand. Janvier ? Février ? Je ne m&#8217;en souviens pas car <strong>je ne pense plus à ma machine</strong>. Je l&#8217;oublie complètement.</p>
<p>Bien sûr, au début, je raillais ce système et ses perversions (installer GCC nécessite de passer par un Store à la con), et puis, passé les deux premiers jours de <em>setup</em>, je l&#8217;ai oublié. Le matin, j&#8217;arrive au boulot, la machine est là, allumée, prête, rapide, disponible. Je travaille, et je lui <em>clou le bec</em> en partant, chose qui ne marchait pas avant.</p>
<p>Je peux me promener avec sans craindre pour la batterie, je peux utiliser le Wifi à tout moment (pas besoin de patcher le kernel dans un hôtel), je peux faire de la visio-conf sans jongler avec 2 outils PulseAudio, le trackpad marche à merveille, le tout démarre en mois de 10s, j&#8217;ai mon Sublime Text, mon terminal, mon ipython et toute sa clique, bref, c&#8217;est le bonheur.</p>
<p>Je ne sais pas quand je vais retourner sous Linux ; la simple idée de me retaper le setup à l&#8217;envers alors que je suis si productif maintenant me donne la nausée. Je n&#8217;ai même pas été tenté à la sortie du 13.04. Tout juste ais-je pris le temps de lancer le Live-CD dans VirtualBox.</p>
<p>Bien sûr, tout n&#8217;est pas rose, je connais bien les arcanes de Linux, mais pas celles d&#8217;OSX ; dès qu&#8217;il y a une dépendances bizarre dans un projet (genre opencv), je prends peur car tout n&#8217;est pas aussi bien packagé, ou aussi facilement compilable, etc mais finalement, ça n&#8217;arrive pas très souvent.</p>
<p>Vous m&#8217;avez lu jusqu&#8217;ici, bravo, je n&#8217;ai pas écris tout ça pour vous convaincre de quoi que ce soit ou pour me justifier. Je suis toujours autant dérangé par Apple, je ne me sens pas à l&#8217;aise en utilisant OSX, mais je peux enfin utiliser ma machine comme l&#8217;outil de dev qu&#8217;il devrait être et rien d&#8217;autre ; c&#8217;est un soulagement très grand.</p>
<p>J&#8217;espère retrouver dans les commentaires de ce billet vos frustrations concernant Linux et pourquoi pas ce que vous faites pour y remédier (Punching Ball?).</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6419&amp;md5=faed6b478a934ae40deca6d09439e907" 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=6414
title: Tester une règle IPtable
uri: Tester-une-règle-IPtable
url: http://sametmax.com/tester-une-regle-iptable/
content:
<p>Je ne sais plus du tout où j&#8217;ai lu ça, mais vu le nombre de fois où je me suis fais connement kické de mon serveur parce que j&#8217;ai joué avec iptable et ai coupé mon accès SSH, je partage.</p>
<p>En gros, on fait comme votre OS quand vous changez la résolution de l&#8217;écran : on attend 30 secondes et on remet la configuration précédente :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> iptables-save <span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>iptables.bak <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #c20cb9; font-weight: bold;">sudo</span> iptables votre_nouvelle_regle <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #c20cb9; font-weight: bold;">sleep</span> <span style="color: #000000;">30</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #c20cb9; font-weight: bold;">sudo</span> iptables-restore <span style="color: #000000; font-weight: bold;">&lt;</span> <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>iptables.bak</pre></div></div>

<p>N&#8217;oubliez pas que le dernier <code>sudo</code> ne marchera pas si votre <code>sleep</code> dure trop longtemps (je crois que <code>sudo</code> ne demande pas le password dans les 5 minutes qui suivent la dernière commande avec <code>sudo</code>) donc n&#8217;augmentez pas trop ce chiffre.</p>
<p>Bon, warning, je l&#8217;ai pas encore testé (si la connexion se coupe, est-ce que le shell se ferme pas ?), donc c&#8217;est juste là pour l&#8217;inspiration.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6414&amp;md5=e3fb455dbf127cf0fcc2cee0cb785d54" 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=6416
title: % ou format() en Python ?
uri: ou-format()-en-Python
url: http://sametmax.com/ou-format-en-python/
content:
<p>On a réçu un mail du genre :</p>
<blockquote><p> Salut les mecs!</p>
<p> Je me demandais si il valait mieux utiliser format() ou % quand on veut insérer une variable dans une chaîne?<br />
 Je comprend pas vraiment quelle est la différence entre les deux&#8230;l&#8217;un est-il plus rapide? Plus fiable?</p>
<p> Merci les mecs!</p></blockquote>
<p>Donc je suppose que d&#8217;autres personnes se posent la même question, du coup je poste ça là une bonne fois pour toute.</p>
<p>En résumé :</p>
<p><code>%</code> c&#8217;est la manière de faire de Python 2, <code>format()</code>, c&#8217;est du Python 3. Mais <code>format()</code> a été backporté en Python 2.6.</p>
<p>Du coup, utilisez toujours <code>format()</code>, ça facilite le portage du code et ça donne de bonnes habitudes. Les mecs comme moi ont encore du mal (je me force) et parfois laissent échapper un <code>%</code> par réflexe, surtout que c&#8217;est plus court à taper et qu&#8217;on est des feinénants. D&#8217;ailleurs les anciens articles du blogs le montrent. C&#8217;est pas une excuse. <code>format()</code> pour tout le monde, et que ça saute !</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6416&amp;md5=0aa840c4fbf25231ec936d0d09ac5884" 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=6439
title: Django, une app à la fois : routing basique
uri: Django-une-app-à-la-fois-routing-basique
url: http://sametmax.com/django-une-app-a-la-fois-routing-basique/
content:
<p>J&#8217;ai rajouté une app dans le <a href="https://github.com/sametmax/Django--an-app-at-a-time/">repo des snippets Django</a> qui montre comment utiliser le système de routing de Django pour faire correspondre des URLs à des vues, et extraires des données de ces URLs.</p>
<p>J&#8217;en ai profité pour faire quelques modifs sur les anciennes apps:</p>
<ul>
<li>Descriptions plus claires et complètes.</li>
<li>Quelques ambiguïtés levées.</li>
<li>Un lien de retour ajouté sur chaque page.</li>
</ul>
<p>J&#8217;ai aussi ajouté des tests unitaires (pas dans la partie snippet, qui doit rester simple) pour m&#8217;assurer que je ne casse pas tout à chaque ajout.</p>
<p>Je pensais qu&#8217;ajouter une nouvelle app, quand l&#8217;app est aussi simple au moins, serait très rapide. Je m&#8217;assurais ainsi quelques articles simples et rapides à pondre.</p>
<p>Mouahahah, jeune incrédule.</p>
<p>Pour faire ces modifs ça m&#8217;a pris près de 3 heures : il faut bien réfléchir pour rendre les notions à la fois simples et utiles, mettre les bons comments, traduire tout ça de l&#8217;anglais vers le français, s&#8217;assurer que les deux branches soient bien synchro, ajouter les tests&#8230;</p>
<p>En me lançant dans le truc, je m&#8217;étais dit &#8220;pourquoi personne ne l&#8217;a fait avant ? C&#8217;est tellement évident que ça manque à la doc&#8221;. Maintenant je sais pourquoi. C&#8217;est long. Très très long.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6439&amp;md5=824c998bd2565178f8c6193d605c19d5" 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=6461
title: Exécuter du code à tout lancement de Python
uri: Exécuter-du-code-à-tout-lancement-de-Python
url: http://sametmax.com/executer-du-code-a-tout-lancement-de-python/
content:
<p>Je vous avais montré comment <a href="http://sametmax.com/personnalisez-le-demarrage-dipython/">lancer du code au démarrage du shell iPython</a>, et on peut faire quelque chose de similaire pour le shell Python ordinnaire avec la variable d&#8217;environnement <code>PYTHONSTARTUP</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">export</span> <span style="color: #007800;">PYTHONSTARTUP</span>=<span style="color: #000000; font-weight: bold;">/</span>chemin<span style="color: #000000; font-weight: bold;">/</span>vers<span style="color: #000000; font-weight: bold;">/</span>fichier<span style="color: #000000; font-weight: bold;">/</span>python<span style="color: #000000; font-weight: bold;">/</span>a<span style="color: #000000; font-weight: bold;">/</span>executer<span style="color: #000000; font-weight: bold;">/</span>au<span style="color: #000000; font-weight: bold;">/</span>demarrage.py</pre></div></div>

<p>Mais comment lancer du code au démarrage pour Python quand on est PAS dans un shell ?</p>
<p>Comme pour l&#8217;<a href="http://sametmax.com/lancer-une-fonction-automatiquement-a-larret-de-python/">exécution du code à la fermeture de la VM</a>, il existe bien entendu un mécanisme pour cela.</p>
<p>Ouvez un shell, et tapez:</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;">site</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">site</span>.<span style="color: black;">getusersitepackages</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'/home/sam/.local/lib/python2.7/site-packages'</span></pre></div></div>

<p>Vous obtenez ainsi le dossier des sites packages locaux, c&#8217;est à dire un dossier qui est dans le PYTHON PATH, mais uniquement pour l&#8217;utilisateur courant. Donc vous pouvez mettre dedans toute bibliothèque Python que vous voulez importable de partout, mais uniquement pour vous.</p>
<p>Dans ce dossier, créez un fichier nommé <em>usercustomize.py</em>, et voilà ! <a href="http://docs.python.org/2/tutorial/interpreter.html#the-customization-modules">Tout ce qui est dans ce fichier est automatiquement exécuté au démarrage de Python</a>.</p>
<p>Attention cependant, il est exécuté très tôt, et donc certaines choses ne sont pas encore chargées, telle que <code>sys.argv</code> ou <code>__builtin__</code>.</p>
<p>Il faut donc ruser un peut. Si vous êtes une loque qui n&#8217;aime pas taper <code>import ipdb; ipdb.set_trace()</code>, vous pouvez par exemple mettre dedans :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">__builtin__</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">pdb</span> <span style="color: #ff7700;font-weight:bold;">import</span> set_trace
&nbsp;
<span style="color: #dc143c;">__builtin__</span>.<span style="color: black;">set_trace</span> = set_trace</pre></div></div>

<p>Et maintenant, dans votre code, vous pourrez appeler <code>set_trace()</code> de <a href="http://sametmax.com/debugger-en-python-les-bases-de-pdb/">pdb</a> directement, sans import, sans préfixe.</p>
<p>Attention tout de même à ce que vous allez mettre là. Si vous commencez à trop trafiquer votre installation, vos programmes pourraient marcher dessus et pas ailleurs. Testez toujours vos logiciels sur des installations de Python standards.</p>
<p>Bonus point: le <a href="http://mail.python.org/pipermail/tutor/2012-August/090729.html">code de startup d&#8217;un codeur Python scientifique</a>.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6461&amp;md5=09a0cff96b2273ae8f5ef2cf017c9849" 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=6437
title: Refactoriser ses vérifications en Python
uri: Refactoriser-ses-vérifications-en-Python
url: http://sametmax.com/refactoriser-ses-verifications-en-python/
content:
<p>On nous a interpelé sur Twitter pour nous demander comment faire un code comme ceci (en tout cas similaire) plus propre:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*</span>
&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> unicode_literals
&nbsp;
<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> verification1<span style="color: black;">&#40;</span>val<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">bool</span><span style="color: black;">&#40;</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;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
verification2 = verification1
verification3 = verification1
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> function<span style="color: black;">&#40;</span>valeur<span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> verification1<span style="color: black;">&#40;</span>valeur<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;Erreur, la vérification 1 n'est pas passée&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> verification2<span style="color: black;">&#40;</span>valeur<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;Erreur, la vérification 2 n'est pas passée&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> verification3<span style="color: black;">&#40;</span>valeur<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;Erreur, la vérification 3 n'est pas passée&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> valeur</pre></div></div>

<p>Ceci est évidement un exemple tout bidon, mais la problématique, c&#8217;est qu&#8217;on a plein de vérifications à faire, et un code à lancer si jamais ces vérifications échouent. Et chaîner les <code>if</code>, c&#8217;est vrai que c&#8217;est pas super mignon (même si c&#8217;est tout à fait valide, faut pas non plus se prendre trop la tête avec ça).</p>
<p>En Python, on a plusieurs manières de s&#8217;occuper de ça. La première, j&#8217;en ai déjà parlé, c&#8217;est <a href="http://sametmax.com/quest-ce-quun-callback/">l&#8217;injection de dépendances</a>. On va passer ces checks en paramètres.</p>
<p>Car je le rappelle, on peut passer des fonctions en paramètres, on peut mettre des fonctions dans des listes, et on peut même passer des listes de fonctions en paramètres. Ce qui ici va nous permettre de :</p>
<ul>
<li>Regrouper les traitements.</li>
<li>Permettre de changer les traitements à la volée.</li>
<li>Avoir malgré tout un traitement par défaut.</li>
<li>Rendre les groupes de vérifications réutilisables</li>
</ul>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">&nbsp;
&nbsp;
VERIF = <span style="color: black;">&#40;</span>
    <span style="color: black;">&#40;</span>verification1, <span style="color: #483d8b;">&quot;Erreur, la vérification 1 n'est pas passée&quot;</span><span style="color: black;">&#41;</span>,
    <span style="color: black;">&#40;</span>verification2, <span style="color: #483d8b;">&quot;Erreur, la vérification 2 n'est pas passée&quot;</span><span style="color: black;">&#41;</span>,
    <span style="color: black;">&#40;</span>verification3, <span style="color: #483d8b;">&quot;Erreur, la vérification 3 n'est pas passée&quot;</span><span style="color: black;">&#41;</span>,
    <span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> v: <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">bool</span><span style="color: black;">&#40;</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;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>,
    <span style="color: #483d8b;">&quot;Erreur, la vérification 4 n'est pas passée&quot;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> faire_verifications<span style="color: black;">&#40;</span>verifications<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">for</span> verif, msg <span style="color: #ff7700;font-weight:bold;">in</span> verifications:
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> verif<span style="color: black;">&#40;</span>valeur<span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">print</span> msg
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> function<span style="color: black;">&#40;</span>valeur, verifications=VERIF<span style="color: black;">&#41;</span>:
    faire_verifications<span style="color: black;">&#40;</span>verifications<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> valeur</pre></div></div>

<p>Cette manière de faire est plus verbeuse si votre liste de <code>if</code> est courte, ou si vous n&#8217;avez à le faire que pour une fonction. Mais elle devient vite plus courte et clair dans le cas où votre code grandi.</p>
<p>Elle aussi l&#8217;avantage de pouvoir insérer ou retirer une modification très simplement (même avec une simple lambda). Enfin, le code de vérification est découplé du code de la fonction ce qui ajoute les bénéfices suivant :</p>
<ul>
<li>Votre code de vérification peut être déplacé dans un module dédié.</li>
<li>Si vous avez des vérifications en plusieurs endroits, il n&#8217;y a qu&#8217;un seul endroit pour corriger les bugs des vérifications, et un seul pour faire une modification des vérifications.</li>
<li>Le code de la fonction redevient simple : elle fait une vérification (on s&#8217;en branle de comment ça marche, on sait que ça vérifie), et ensuite elle s&#8217;occupe de SON boulot. C&#8217;est la partie du code qui nous intéresse quand on va voir la fonction.</li>
</ul>
<p>On peut évidement imaginer autre chose qu&#8217;un print: lever une exception, faire un log, ou même carrément aussi passer une fonction en lieu et place du message d&#8217;erreur qui fait office de callback quand la vérification échoue (et qui par défaut print, le meilleur des deux mondes).</p>
<p>Si vos vérifications deviennent très courantes, alors, l&#8217;utilisation de décorateurs prend tout son sens. Je ne vais pas rentrer sur comment écrire son décorateur, il y a <a href="http://sametmax.com/comprendre-les-decorateurs-python-pas-a-pas-partie-1">un autre article pour ça</a>, mais on peut obtenir un résultat du genre :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> verif<span style="color: black;">&#40;</span>verification, message<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> decorateur<span style="color: black;">&#40;</span>func<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">def</span> wrapper<span style="color: black;">&#40;</span><span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> verification<span style="color: black;">&#40;</span><span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>:
                <span style="color: #ff7700;font-weight:bold;">print</span> message
            <span style="color: #ff7700;font-weight:bold;">return</span> func<span style="color: black;">&#40;</span><span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> wrapper
    <span style="color: #ff7700;font-weight:bold;">return</span> decorateur
&nbsp;
<span style="color: #808080; font-style: italic;"># si on utilise souvent une vérif, on peut l'avoir </span>
<span style="color: #808080; font-style: italic;"># tout le temps tout la main</span>
verif3 = verif<span style="color: black;">&#40;</span>verification3, <span style="color: #483d8b;">&quot;Erreur, la vérification 3 n'est pas passée&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># et ensuite il suffit d'appliquer autant de décorateur qu'on le souhaite</span>
@verif<span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> v: <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">bool</span><span style="color: black;">&#40;</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;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>, <span style="color: #483d8b;">&quot;Erreur, la vérification 4 n'est pas passée&quot;</span><span style="color: black;">&#41;</span>
@verif3
@verif<span style="color: black;">&#40;</span>verification2, <span style="color: #483d8b;">&quot;Erreur, la vérification 2 n'est pas passée&quot;</span><span style="color: black;">&#41;</span>
@verif<span style="color: black;">&#40;</span>verification1, <span style="color: #483d8b;">&quot;Erreur, la vérification 1 n'est pas passée&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> function<span style="color: black;">&#40;</span>valeur<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> valeur</pre></div></div>

<p>Les avantages ici sont :</p>
<ul>
<li>Corps de la fonction initial vide de toute vérification. Les vérifications sont purement déclaratives (comme par exemple la vérification de login dans Django).</li>
<li>Chaque vérif est très facilement réutilisable, il suffit de mettre le décorateur. Si on utilise une vérif très souvent, alors on peut même mettre le décorateur dans une variable et juste déclarer <code>@ma_verif</code>.</li>
<li>C&#8217;est très pythonique comme style.</li>
</ul>
<p>En résumé : si vous avez un petit code, ne vous prenez pas la tête. Une série de if est tout à fait valide, ça marche bien, c&#8217;est clair et lisible. Il faut savoir aller au plus simple. Mais si votre code devient touffu, utiliser une liste de fonction peut aider à faire le ménage. Si vous commencer carrément à avoir un gros projet ou que vous codez une lib réutilisable, les décorateurs seront de précieux alliés : ils permettent à celui qui passe derrière vous de se foutre complètement de savoir comment ça marche et de juste assembler son code comme un légo.</p>
<hr />
<p><a href="https://github.com/sametmax/codes-des-articles/blob/master/2013/juin/verification.py">Télécharger le code de l&#8217;article</a></p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6437&amp;md5=6d1f7a3e4f25de4f829e1a375c10a1b2" 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=6445
title: Github comme hébergeur gratuit de fichiers
uri: Github-comme-hébergeur-gratuit-de-fichiers
url: http://sametmax.com/github-comme-hebergeur-gratuit-de-fichiers/
content:
<p>J&#8217;inaugure une nouvelle technique de feignasse : copier / coller les mails que je réponds à un lecteur, tel quel.</p>
<p>Ici on me demandais (je crois ^^) comment faire pour donner un lien de téléchargement d&#8217;un code sous Gitub. Voici l&#8217;info, si ça vous intéresse.</p>
<blockquote><p>
Sur github, tu peux sans problème donner un zip à télécharger, tant que<br />
ton repository est publique.</p>
<p>Par exemple, notre lib batbelt est à l&#8217;URL github :</p>
<p>https://github.com/sametmax/Bat-belt/</p>
<p>Il suffit de rajouter :</p>
<p>archive/master.zip</p>
<p>Et c&#8217;est téléchargeable :</p>
<p>https://github.com/sametmax/Bat-belt/archive/master.zip</p>
<p>En plus ce sera toujours la dernière version. Ca marche pour toutes les<br />
branches et tous les tags, mais aussi n&#8217;importe quel commit :</p>
<p>https://github.com/sametmax/Bat-belt/archive/96ca096bb9eead0675186b36c576251935e96cf9.zip</p>
<p>Pour avoir un fichier en particulier, il faut prendre l&#8217;URL du fichier,<br />
et la préfixer de &#8220;raw&#8221; et retirer &#8220;blob&#8221;. Par exemple, le fichier :</p>
<p>https://github.com/sametmax/Bat-belt/blob/master/batbelt/structs.py</p>
<p>Est téléchargeable à :</p>
<p>https://raw.github.com/sametmax/Bat-belt/master/batbelt/structs.py</p>
<p>Là le fichier est accessible directement, et téléchargeable avec Ctrl + S.</p>
<p>@+</p></blockquote>
<p>Alala, qu&#8217;est-ce que ne ferais pas un blogger pour ajouter du contenu à son blog en en branlant le moins possible ?</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6445&amp;md5=80b4eca39cbb09b3116c8dff070b33c5" 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=3472
title: Vous pouvez mettre du code dans __init__.py
uri: Vous-pouvez-mettre-du-code-dans-__init__-py
url: http://sametmax.com/vous-pouvez-mettre-du-code-dans-__init__-py/
content:
<p>Le fichier <em>__init__.py</em> ne sert pas qu&#8217;à <a href="http://sametmax.com/les-imports-en-python/">déclarer un dossier comme un package importable</a>. C&#8217;est aussi le code exécuté automatiquement, une seule fois, quand on importe le module.</p>
<p>Du coup vous pouvez mettre dedans tout code Python que vous souhaitez lancer à l&#8217;import. On y voit souvent :</p>
<ul>
<li>Initialisation du cache.</li>
<li>Constantes comme <code>__version__</code>.</li>
<li>Import d&#8217;autres modules pour les mettre dans l&#8217;espace de nom courant.</li>
<li>Check de dépendances.</li>
<li>Aliasing.</li>
<li>Monkey patching and hacks tout moches qui sont là temporairement pour 6 ans.</li>
</ul>
<p>Je vous déconseille de mettre trop de code dans le fichier <em>__init__.py</em>, notamment du code métier. C&#8217;est une mauvaise habitude que l&#8217;on peut voir dans le code de Django par exemple. Car ça veut dire que l&#8217;import du package déclenche ce code, qui lui-même importe d&#8217;autres modules, qui déclenche d&#8217;autres codes, etc. Cela donne des effets de bord à l&#8217;import, alors que l&#8217;import d&#8217;un simple package est quelque chose que l&#8217;on veut généralement ne pas avoir beaucoup d&#8217;effets.</p>
<p>Dans Django par exemple, c&#8217;est ce qui fait que beaucoup de modules lèvent une exception à l&#8217;import :</p>
<p><code>django.core.exceptions.ImproperlyConfigured: Requested setting X but settings are not configured. </code></p>
<p>Alors qu&#8217;ils n&#8217;ont pas du tout besoin des settings pour fonctionner.</p>
<p>Si vous avez besoin que votre classe <code>Bidule</code> soit directement importable dans votre package <code>machin</code>, faites dans <em>machin/__init__.py</em> :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> .<span style="color: black;">module_qui_contient_bidule</span> <span style="color: #ff7700;font-weight:bold;">import</span> Bidule</pre></div></div>

<p>Du coup vous pourrez faire n&#8217;importe où ailleurs:</p>

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

<p>C&#8217;est bien plus propre que de mettre tout le code de <code>Bidule</code> dans le <em>__init__.py</em>.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=3472&amp;md5=2daf10a1153a39b9d0d97872a04a914d" 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=6485
title: Taille d’un dossier en bash
uri: Taille-d-un-dossier-en-bash
url: http://sametmax.com/taille-dun-dossier-en-bash/
content:
<p>Dans la série des &#8220;je le balance ici car je m&#8217;en souviens jamais&#8221;.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">du</span> <span style="color: #660033;">-sh</span> <span style="color: #000000; font-weight: bold;">/</span>chemin<span style="color: #000000; font-weight: bold;">/</span>vers<span style="color: #000000; font-weight: bold;">/</span>dossier</pre></div></div>

<p>C&#8217;est con mais quand on s&#8217;en sert pas souvent, on met 10 minutes pour retrouver un truc aussi simple.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6485&amp;md5=728309515c62c118dc7b90742c3a2567" 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=6489
title: Ajouter un nœud de sortie Tor sur son serveur Ubuntu
uri: Ajouter-un-nœud-de-sortie-Tor-sur-son-serveur-Ubuntu
url: http://sametmax.com/ajouter-un-noeud-de-sortie-tor-sur-son-serveur-ubuntu/
content:
<p>Installer un nœud de sortie Tor est un moyen de contribuer à son niveau à l&#8217;émancipation du Web. L&#8217;installer sur sa machine de bureau n&#8217;est pas très intéressant, mais on trouve des <a href="https://www.leaseweb.nl">serveurs à 7 euros par mois</a> de nos jours qui suffisent largement à cette tâche. </p>
<p>La procédure pour l&#8217;installation sur Ubuntu est beaucoup plus simple qu&#8217;au début du projet.</p>
<p>D&#8217;abord, il faut récupérer le nom de sa distrib :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">lsb_release <span style="color: #660033;">-c</span>
Codename: precise</pre></div></div>

<p>Ici pour pour moi &#8220;precise&#8221;.</p>
<p>Ensuite on rajoute <em>/etc/apt/sources.list</em> une ligne contenant <code>deb http://deb.torproject.org/torproject.org nom_distrib main</code>, dans mon cas :</p>
<p><code>deb http://deb.torproject.org/torproject.org precise main</code></p>
<p>On rajoute les clés du dépôt officiel de tor et on install tor (ntp pour synchroniser l&#8217;heure) :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">gpg <span style="color: #660033;">--keyserver</span> keys.gnupg.net <span style="color: #660033;">--recv</span> 886DDD89
gpg <span style="color: #660033;">--export</span> A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89 <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-key</span> add -
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> update
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> <span style="color: #c20cb9; font-weight: bold;">install</span> deb.torproject.org-keyring tor ntp</pre></div></div>

<p>A ce stade là vous avez un client Tor fonctionel, mais pas un nœd de sortie. Un petit <code>sudo vi /etc/tor/torrc</code> et on décommente la ligne :</p>
<p><code>#ORPort 9001</code></p>
<p>Il faut du coup ouvrir le port 9001 :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">iptables <span style="color: #660033;">-I</span> INPUT <span style="color: #660033;">-p</span> tcp <span style="color: #660033;">-m</span> tcp <span style="color: #660033;">--dport</span> <span style="color: #000000;">9001</span> <span style="color: #660033;">-j</span> ACCEPT
iptables <span style="color: #660033;">-I</span> OUTPUT <span style="color: #660033;">-p</span> tcp <span style="color: #660033;">-m</span> tcp <span style="color: #660033;">--dport</span> <span style="color: #000000;">9001</span> <span style="color: #660033;">-j</span> ACCEPT</pre></div></div>

<p>(Sauvegardez votre config iptables sinon au prochain reboot, votre port est à nouveau bloqué)</p>
<p>Et on relance le service.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> service tor reload</pre></div></div>

<p>Pour voir si ça a bien fonctionné :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>log<span style="color: #000000; font-weight: bold;">/</span>tor<span style="color: #000000; font-weight: bold;">/</span>log <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #7a0874; font-weight: bold;">test</span>
Self-testing indicates your ORPort is reachable from the outside. Excellent.</pre></div></div>

<p>Quelques avertissements tout de même :</p>
<ul>
<li>Tor est un projet utilisé massivement par des activistes politiques et personnes à la connexion internet et aux libertés bridées (c&#8217;est ceux qu&#8217;on cherche à aider), mais également des gens aux activités illégales (ventes de produits interdits dans leurs pays, ce qui va de la weed au GHB) voir carrément immorales (pédopornographie, terrorisme). En ouvrant un nœud Tor, vous n&#8217;avez aucun contrôle sur QUI utilise votre équipement, ou pour faire quoi.</li>
<li>Certains hébergeurs interdisent Tor. C&#8217;est le cas de <a href="http://www.cinfu.com/">cinfu</a>, un hébergeur qui accepte pourtant les <a href="sametmax.com/quest-ce-que-bitcoin/">Bitcoins</a> mais aussi, je viens de l&#8217;apprendre à mes dépends, de online.net et ses fameuses dédibox. Il m&#8217;ont donné 24 H pour fermer mon nœd Tor, et je vais donc devoir le migrer sur leaseweb ou OVH.</li>
<li>Le cadre légal autour de Tor est encore fluctuant. Je suis incapable de vous dire si vous pouvez être tenu pour responsable des activités illégales qui seraient perpétrées à travers votre équipement.</li>
<li>Ça va bouffer de la bande passante.</li>
</ul>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6489&amp;md5=cb9fce27070fb8c80062ea02c7f40bd4" 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=6496
title: Installer un nœud Bitcoin sur un serveur Ubuntu
uri: Installer-un-nœud-Bitcoin-sur-un-serveur-Ubuntu
url: http://sametmax.com/installer-un-noeud-bitcoin-sur-un-serveur-ubuntu/
content:
<p>Hier on a fait Tor, pourquoi ne pas faire Bitcoin aujourd&#8217;hui ? (j&#8217;ai essayé freenet, mais je me suis gaufré sur une erreur Java, c&#8217;est con).</p>
<p>Faire tourner <a href="http://bitcoin.org/en/download">bitcoinqt</a> sur son ordinateur personnel a plusieurs défauts :</p>
<ul>
<li>Il télécharge toute la blockchain, ce qui est long et prend des Go de place sur le disque.</li>
<li>Ca bouffe de la ressource pour rien.</li>
<li>On aide pas tellement le réseau car on ferme le client dès que l&#8217;opération financière est terminée.</li>
</ul>
<p>Bref, le client officiel Bitcoin n&#8217;est pas le plus ergonomique, et on lui préférera des alternatives légères comme <a href="http://electrum.org/">Electrum</a>.</p>
<p>Seulement puisque ces wallets &#8220;allégés&#8221; ne télécharge pas la blockchain, vous n&#8217;aidez pas le réseau. Or, personnellement, <a href="sametmax.com/quest-ce-que-bitcoin/">je participe à Bitcoin pour aider le mouvement</a>.</p>
<p>J&#8217;ai donc décidé d&#8217;installer un nœud Bitcoin sur un de mes serveur, comme ça j&#8217;ai le meilleur des deux mondes. Évidement je ne recommande pas à Mme Michu de faire ça, mais en même temps je ne recommande pas à la vieille d&#8217;utiliser Bitcoin non plus.</p>
<p>Sur Ubuntu Server, ce n&#8217;est pas une opération complexe.</p>
<h2>Créer un utilisateur nommé &#8220;bitcoin&#8221;</h2>
<p>Ca permet d&#8217;isoler les fichiers de config (le wallet sera vide de toute façon, je suis pas fou).</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> adduser bitcoin</pre></div></div>

<h2>Installer le daemon bitcoin</h2>
<p>Cool, c&#8217;est dans les dépôts !</p>

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

<h2>Faire un script de démarrage</h2>
<p>Alors là, je m&#8217;attendais à une galère sans nom, mais c&#8217;est sans compter qu&#8217;Ubuntu utilise maintenant <a href="http://newcome.wordpress.com/2012/02/26/running-programs-as-linux-daemons-using-upstart/">upstarts</a>, qui rend la création de scripts de démarrage super simple.</p>
<p>Créer un fichier <em>/etc/init/bitcoin.conf</em> et mettre dedans:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># bitcoind upstart script for Ubuntu</span>
&nbsp;
description <span style="color: #ff0000;">&quot;Bitcoin daemon&quot;</span>
&nbsp;
start on runlevel <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">2345</span><span style="color: #7a0874; font-weight: bold;">&#93;</span>
stop on runlevel <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000; font-weight: bold;">!</span><span style="color: #000000;">2345</span><span style="color: #7a0874; font-weight: bold;">&#93;</span>
&nbsp;
respawn
<span style="color: #7a0874; font-weight: bold;">exec</span> <span style="color: #c20cb9; font-weight: bold;">su</span> <span style="color: #660033;">-c</span> <span style="color: #ff0000;">&quot;bitcoind&quot;</span> - bitcoin</pre></div></div>

<p>Pouf pouf, on démarre le service :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">service bitcoin start</pre></div></div>

<p>Et voilà, bitcoind est maintenant un service de votre serveur, tournant vaillamment en tâche de fond, lancé à chaque reboot.</p>
<h2>Ouvrir le port 8333</h2>
<p>Sinon vous aurez un super service qui tourne pour lui tout seul.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> iptables <span style="color: #660033;">-I</span> OUTPUT <span style="color: #660033;">-p</span> tcp <span style="color: #660033;">-m</span> tcp <span style="color: #660033;">--dport</span> <span style="color: #000000;">8333</span> <span style="color: #660033;">-j</span> ACCEPT
<span style="color: #c20cb9; font-weight: bold;">sudo</span> iptables <span style="color: #660033;">-I</span> INPUT <span style="color: #660033;">-p</span> tcp <span style="color: #660033;">-m</span> tcp <span style="color: #660033;">--dport</span> <span style="color: #000000;">8333</span> <span style="color: #660033;">-j</span> ACCEPT</pre></div></div>

<p>Vérifier si ça marche :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">du</span> <span style="color: #660033;">-sH</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>bitcoin<span style="color: #000000; font-weight: bold;">/</span>.bitcoin</pre></div></div>

<p>La taille devrait grossir avec le temps</p>
<p>Prochaine étape, faire son propre serveur de blockchain, histoire de ne pas dépendre de ceux d&#8217;electrum.</p>
<p>PS: passer l&#8217;option &#8220;-gen&#8221; à <code>bitcoind</code> si vous voulez miner. Ça vous servira à rien, mais c&#8217;est psychologique ^^</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6496&amp;md5=b09c9635c9633211a2f20d747b6d2dee" 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=6507
title: 10 raisons pour lesquelles je suis toujours marié à Python
uri: 10-raisons-pour-lesquelles-je-suis-toujours-marié-à-Python
url: http://sametmax.com/10-raisons-pour-lesquelles-je-suis-toujours-marie-a-python/
content:
<p>C&#8217;est une chance d&#8217;avoir un métier qu&#8217;on aime. Et l&#8217;avantage, c&#8217;est qu&#8217;on se sent l&#8217;énergie d&#8217;essayer plein de choses. J&#8217;ai codé (à plus ou moins grande échelle) en de nombreux langages : VB, C, C#, Java, Ruby, PHP, Javascript, Lisp, Bash, Erlang, SQL et leurs dérivés (langages générateurs, surcouches, etc).</p>
<p>Et j&#8217;en ai apprécié beaucoup. Ils m&#8217;ont fait découvrir des choses, on fait de moi un meilleur professionnel. Et m&#8217;ont donné des tas de perspectives sur mon métier, sur la résolution de certains problèmes, sur la philosophie de dev&#8230;</p>
<p>Je continue à utiliser d&#8217;autres langages au quotidien pour divers tâches, j&#8217;ai remarqué qu&#8217;un marteau était beaucoup plus pratique qu&#8217;un tourne-vis pour enfoncer des clous, mais quand j&#8217;ai le choix, je reviens toujours à Python.</p>
<p>Et en voici les raisons.</p>
<h2>Python est installé par défaut presque partout.</h2>
<p>Que ce soit sur ma bécane Ubuntu, le Mac de Max ou un serveur CentOs, Python est installé par défaut dessus. Il n&#8217;y a rien à faire.</p>
<p>Bien entendu, il y a les traditionnels problèmes de version, d&#8217;installation de package, etc. Mais c&#8217;est vrai pour tous les langages.</p>
<p>De plus, quand Python n&#8217;est pas installé (Windows, Android&#8230;), il y a des <a href="http://www.python.org/getit/windows/">programmes tout prêts</a> pour le faire.</p>
<p>Et il tourne vraiment sur n&#8217;importe quoi, même sur des trucs <a href="http://www.python.org/getit/other/">super exotiques</a>.</p>
<h2>Python n&#8217;a pas besoin d&#8217;un IDE</h2>
<p>On peut programmer en Python avec un simple éditeur de texte à coloration syntaxique. Le langage est tellement épuré et léger qu&#8217;il se passe complètement d&#8217;outils complexes comme Eclipse ou VisualStudio, Komodo ou Bean, et l&#8217;expérience est déjà confortable.</p>
<p>Évidement, on peut utiliser un IDE, mais au final, je préfère même m&#8217;en passer et rester sur un éditeur de texte avancé comme Sublime Text.</p>
<h2>Python est là depuis longtemps, et pour longtemps</h2>
<p>Python est un langage très ancien (<a href="http://fr.wikipedia.org/wiki/Python_(langage)">1990</a>). En fait, contrairement à ce que l&#8217;on peut imaginer, il est apparu avant Java (<a href="http://fr.wikipedia.org/wiki/Java_(langage)">1995</a>). Il y a donc beaucoup d&#8217;expérience derrière ce langage et son environnement, et surtout, c&#8217;est la preuve qu&#8217;il est capable de tenir la longueur.</p>
<p>Comme Python est un des 3 seuls langages autorisés en production par Google (avec le C et le Java) mais aussi d&#8217;autres gros projets comme Dropbox ou Reddit, on peut être rassuré sur son avenir.</p>
<h2>Python vient avec piles incluses, et un vaste jeu de piles de rechange</h2>
<ul>
<li>vous voulez parser des arguments ? <a href="http://docs.python.org/2.7/library/argparse.html">Il y a un module pour ça</a>.</li>
<li>vous voulez faire de l&#8217;asynchrone ? <a href="http://docs.python.org/2.7/library/asyncore.html">Il y a un module pour ça</a>.</li>
<li>lire une base de données sqlite ? <a href="http://docs.python.org/2.7/library/sqlite3.html">Il y a module pour ça</a>.</li>
<li>Du logging ? <a href="http://docs.python.org/2.7/library/logging.html">Il y a un module pour ç</a>a.</li>
<li><a href="http://docs.python.org/2.7/library/csv.html">CSV</a>, <a href="http://docs.python.org/2.7/library/xml.etree.elementtree.html">XML</a>, <a href="http://docs.python.org/2.7/library/json.html">JSON</a>, <a href="http://docs.python.org/2.7/library/configparser.html">INI</a>, <a href="http://docs.python.org/2.7/library/plistlib.html">plist</a>, <a href="http://docs.python.org/2.7/library/zipfile.html">zip</a> ?</li>
</ul>
<p>En fait, avec l&#8217;installation de Python, par défaut, <a href="http://sametmax.com/tres-grand-listing-des-libs-standard-partie-les-plus-utiles-en-python/">il y a des modules pour tellement de choses</a> que je continue à en découvrir après 10 ans de pratique.</p>
<p>Et quand il n&#8217;y a pas de libs installées par défaut, bah, on a pypi, et ses <a href="https://pypi.python.org/pypi?%3Aaction=index">22 mother fucker milles libs</a> open source installables avec <a href="http://sametmax.com/votre-python-aime-les-pip/">pip</a>.</p>
<p>Et il a des perles.</p>
<p>Envie d&#8217;un serveur Web qui tienne la charge d&#8217;un site moyen sans rien installer (pas de Nginx, pas de compile, juste un fichier Python à poser) ? <a href="http://docs.cherrypy.org/stable/refman/process/servers.html">Cherrypy</a> est votre ami.</p>
<p>Besoin de faire des traitements scientifiques de haut niveau ? <a href="http://www.scipy.org/">Scypy</a> est là pour ça.</p>
<p>Manipuler des images ? <a href="https://pypi.python.org/pypi/Pillow/">Pillow</a> à la rescousse.</p>
<p>Mettre en place un serveur Web asynchrone ? <a href="http://www.tornadoweb.org/en/stable/">Tornado</a> ne demande même pas de compilation.</p>
<p><a href="http://www.secdev.org/projects/scapy/">Manipulation de packets</a>, <a href="http://docs.fabfile.org/en/1.5/">outils de déploiement</a>, <a href="https://pypi.python.org/pypi/supervisor">gestion de processus</a>, <a href="http://bleyer.org/pyusb/">contrôleur USB</a>, <a href="http://www.pygame.org/news.html">créer un jeu vidéo</a>, <a href="https://pypi.python.org/pypi/python-money/0.5">manipuler de l&#8217;argent</a>, <a href="http://www.reportlab.com/">utiliser le format PDF</a>, <a href="http://rg3.github.io/youtube-dl/">télécharger une vidéo de youtube</a>, <a href="https://pypi.python.org/pypi/twitter/">poster sur Twitter</a> ou même <a href="http://scrapy.org/">crawler un site entier</a>&#8230;</p>
<p>Python ne se limite pas à X ou Y, et particulièrement comparé à la plupart des langages de scripting, Python ne se limite certainement pas à faire des sites Web ou de l&#8217;admin système.</p>
<p>Python me limite très rarement (ça arrive, par exemple pour l&#8217;embarqué). Je ne me pose pas souvent la question de <a href="http://sametmax.com/quest-ce-quon-peut-faire-avec-python/">ce que je peux faire</a>, mais plutôt de ce que j&#8217;ai envie de faire.</p>
<h2>Python est fair play</h2>
<p>Les créateurs du langage n&#8217;avait en aucun cas envie de rentrer en compétition avec les langages existant. Pour cette raison, Python est très ouvert sur l&#8217;extérieur et travaille très bien avec les autres langages et technologies.</p>
<p>On peut intégrer l&#8217;interpréteur Python dans son propre programme, et carrément ajouter le langage comme système de scripting (ce que fait Blender) ou plugin (ce que fait Sublime Text).</p>
<p>On peut appeler du code <a href="http://sametmax.com/appeler-du-code-c-depuis-python-avec-ctypes/">C</a> ou <a href="http://cens.ioc.ee/projects/f2py2e/">Fortran</a> depuis Python ou du code Python depuis <a href="http://fr.wikipedia.org/wiki/Jython">Java</a> ou <a href="http://fr.wikipedia.org/wiki/IronPython">.net</a>.</p>
<p>Bref, Python n&#8217;est pas dans l&#8217;opposition, il est dans la collaboration. Ajouter Python à sa boîte à outil, c&#8217;est avoir un copain en plus.</p>
<h2>Python force la lisibilité</h2>
<p>Par sa syntaxe avec très peu de mots clés et l&#8217;absence de blocs anonymes (les lambdas sont inlines), il est bien plus difficile (mais pas impossible ^^) de faire du code obfusqué en Python.</p>
<p>Écrire du Python sale et bien entendu toujours possible &#8211; et pratiqué &#8211; mais même du Python crade est plus lisible que beaucoup de code propre dans d&#8217;autres langages.</p>
<p>En forçant l&#8217;indentation, feature parfois détestée mais que je considère comme une des plus grandes forces du langage, Python limite la casse et permet de très facilement naviguer dans le code d’autrui et de s&#8217;y retrouver. Le logiciel libre en Python, c&#8217;est beaucoup plus facile.</p>
<p>La communauté Python possède une forte culture de la lisibilité (PEP8 \o/) et cela se sent dès qu&#8217;on veut travailler avec quelqu&#8217;un d&#8217;autre.</p>
<h2>Python me fait gagner du temps</h2>
<p>Pas compilation, un typage dynamique, une syntaxe succincte, un debugger intégré, un shell de tests et des stack traces très verbeuses. Le langage a été inventé pour la productivité.</p>
<p>C&#8217;est très simple, quand je code dans un langage qui ne possède pas certaines de ces fonctionnalités, j&#8217;ai l&#8217;impression de faire une randonnée avec un boulet au pied.</p>
<p>Ayant expérimenté des langages avec et sans typage statique, je le dis tout haut, le temps que ça fait gagner en debugging ne rentabilise pas les contraintes que ça apporte (par contre niveau perf c&#8217;est sûr, c&#8217;est cool).</p>
<p>Mais même le design de Python a été pensé pour aller plus vite : design patterns intégrés (iterateurs, decorateurs), duck typing, unpacking, <a href="http://sametmax.com/operateur-splat-ou-etoile-en-python/">paramétrage dynamique</a>, <a href="http://sametmax.com/python-love-les-listes-en-intention-partie/">listes en intention</a>, <a href="http://sametmax.com/comment-utiliser-yield-et-les-generateurs-en-python/">générateurs</a>&#8230; Toutes ces petites choses qui cumulées vous font gagner des minutes, qui deviennent des heures.</p>
<h2>Il y a de la doc</h2>
<p>Je n&#8217;ai jamais rencontré de langages avec des docs parfaites (même si PHP a une excellente doc par rapport à la plupart des autres), en revanche j&#8217;en ai rencontré beaucoup avec de docs pourries, pas à jours, incomplètes voire fausses.</p>
<p>En moyenne Python a <a href="http://docs.python.org/3/tutorial/index.html">une bonne doc</a>, et en <a href="http://docs.python.org/3/library/index.html">bonne quantité</a>. Certes, il y des centaines de choses que je pourrai pointer du doigt, mais la documentation n&#8217;est pas un frein contrairement à de nombreuses technos hypes que je vois passer dans mon flux RSS.</p>
<p>C&#8217;est un corollaire des points précédents : Python est là depuis longtemps, et la communauté valorise le gain de temps. On le retrouve aussi dans la doc des projets tierce partie, qui sont souvent de bonnes surprises : celles de <a href="https://docs.djangoproject.com/en/1.5/">Django</a>, <a href="http://doc.scrapy.org/en/latest/intro/tutorial.html">scrappy</a>, <a href="http://docs.python-requests.org/en/latest/">requests</a> ou ont littéralement des milliers d&#8217;heures de travail.</p>
<p>On trouve même des <a href="http://python.developpez.com/cours/TutoSwinnen/">livres gratuits</a>, et en français pour apprendre Python. C&#8217;est assez incroyable de voir toute ce boulot mis à la disposition d&#8217;autrui.</p>
<p>Le fait que le langage soit autodocumenté et le code source facilement lisible rend aussi l&#8217;exploration très facile, et je vais très souvent voir sous le capot des libs que j&#8217;utilise.</p>
<h2>Python est hackable</h2>
<p>La nature dynamique de Python et son absence totale de mécanisme de sécurité énervent souvent des gens venant de langages plus stricts. Personnellement j&#8217;adopte la philosophie Unix autour de cela : ce n&#8217;est pas le rôle du langage de s&#8217;occuper de la sécurité, c&#8217;est celui de l&#8217;environnement.</p>
<p>Cela veut dire que si une lib que vous utilisez ne se comporte pas comme prévue, vous n&#8217;êtes pas forcément bloqué. Vous pouvez trouver une solution de contournement, très souvent sans toucher au code d&#8217;origine, afin de sortir la tête de l&#8217;eau le temps qu&#8217;un patch plus propre soit proposé et accepté.</p>
<p>Ça veut dire aussi que Python s&#8217;inscrit formidablement bien dans le cadre d&#8217;un développement agile : pas besoin de faire des plans sur la comètes, vous pourrez changer facilement d&#8217;avis en cours de route.</p>
<h2>Python me rend heureux</h2>
<p>C&#8217;est très subjectif, évidement. Mais quand je code dans certains langages, j&#8217;ai mal au cul. Chaque ligne est taillée, extraite d&#8217;un bloc de granite et roulé jusqu&#8217;à sa place dans le fichier.</p>
<p>Quand je code en Python, certaines solutions me font sourire. Les problèmes sont résolus élégamment, les algos tiennent en quelques lignes claires, et je peux les changer facilement en cours de route.</p>
<p>Python n&#8217;est pas parfait, loin de là, il y a eu, et il y aura encore, ces fameuses nuits glaciales ou l&#8217;épuisement n&#8217;est tenu éloigné que par le délire de la confusion mentale, à la recherche de la raison de ce putain de bug, sur le déchiffrage de ce message d&#8217;erreur cryptique ou en train de préparer l&#8217;assassinat violent de l&#8217;auteur d&#8217;une lib qui a fait de la merde.</p>
<p>Mais globalement, Python, c&#8217;est comme le cochon.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6507&amp;md5=aca431d3feb7c40e891c362698625f72" 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=6518
title: Notre programme “Envoyez nous les scripts que vous ne pigez pas” est toujours d’actu
uri: Notre-programme-Envoyez-nous-les-scripts-que-vous-ne-pigez-pas-e
url:
http://sametmax.com/notre-programme-envoyez-nous-les-scripts-que-vous-ne-pigez-pas-est-toujours-dactu/

content:
<p>Bon, je me traîne comme une limace hémiplégique pour les pondre mais comme on dit, &#8220;qui vol un cheval donné qu&#8217;à la fin l&#8217;étincelle se casse&#8221;.</p>
<blockquote><p>Salut,</p>
<p>je viens de lire votre article &#8220;Envoyez nous les scripts que vous ne pigez pas&#8221;.<br />
L&#8217;article date un peu, ptêt j&#8217;arrive trop tard.<br />
Dans le cas contraire.. read on..</p>
<p>Voilà: je me ronge le cerveau sur un script python depuis un moment déjà, mais il reste aujourd&#8217;hui une lamentable énigme.</p>
<p>La situation:</p>
<p>On m&#8217;offre l&#8217;intégrale (26Go!) des cartes IGN, tombées du cyber-camion, accompagné de quelques lignes de python permettant de soit-disant trouver la carte qui nous intéresse par ses coordonnées GPS et de, une fois qu&#8217;on a une carte, trouver celles qui viennent se placer au Nord/Sud/Est/Ouest.</p>
<p>D&#8217;la balle, que j&#8217;me dis. J&#8217;y connais rien au python, mais le code est lisible, commenté, easy quoi.<br />
Après quelques heures de lecture, le monde sera à moi.. C&#8217;était il y a deux mois.<br />
Échec total de communication entre mes synapses et le serpent.<br />
Jamais plus je ne toucherai à du Python me suis-dis alors.<br />
Jusqu&#8217;à ce que l&#8217;espoir renaisse à lecture de votre billet qui-fut-pour-moi-comme-un-arc-en-ciel (et hop, léchage de cul qui fera, à n&#8217;en point douter, toute la différence).</p>
<p>Je m&#8217;en remets donc à vous, nobles aventuriers, et vous remets votre carte au trésor ci-dessous:</p>
<p>* find_map_by_coordinate.py</p>
<p>http://0bin.net/paste/8a658d3a8f3149ee3af36b7f9abb0e291d00d3f1#OYNAOG9Bhuk/cdC6SgsgVxoW+s5eADhCwjUGACNI4wk=</p>
<p>* find_close_maps.py</p>
<p>http://0bin.net/paste/5a1a9236cddfbea5abbc4c21459856acfd21fd17#MncBXtbHcQFaKW8l3aEVmyNc+0gqe4/iTU6aIatAK4w=</p>
<p>* ign25.py</p>
<p>http://0bin.net/paste/f50e61ad54b9e53d6dd99a655d9cf564eb7a5ad7#QWa6Fz9GejLNK5+niZNqc6/fTm0Pwvl2fBjtPGL8I5Y=</p>
<p>Et pour répondre à votre question, oui, je peux vous envoyer les précieuses cartes.<br />
Reste simplement à trouver un moyen de vous faire passer 26Go de données..</p>
<p>Bon décodage!</p>
<p>Bien à vous,</p>
<p>(pour partouze c&#8217;est toujours OK ?)</p></blockquote>
<p>Bon, d&#8217;accord, j&#8217;ai rajouté la dernière ligne.</p>
<p>Donc, j&#8217;ai lu les scripts, et je les ai commenté au fil de l&#8217;eau. Vous allez voir, ça se sent, c&#8217;est assez organique et on sent bien se développer mes réactions au fur et à mesure face à ce script.</p>
<p>Spoiler : cher ami lecteur, tes synapses ne sont pas en cause, l&#8217;auteur du script n&#8217;est pas un Dieu de la prog, et en fait je ne suis même pas sûr que son code marche. Même un petit peu. Auteur anonyme si tu nous lis, toutes mes condoléances.</p>
<p>Comme ça va être long, et conforme à la tradition :</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="420" height="315" src="//www.youtube.com/embed/g6ICYbiLIsg" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<h1>find_map_by_coordinate.py</h1>
<p>Là je découvre, c&#8217;est l&#8217;aventure, on sent l&#8217;enthousiasme.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python</span>
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;"># Ceci est un script de recherche de coordonnées, il trouve une carte qui</span>
<span style="color: #808080; font-style: italic;"># contient ces coordonnées dans la base de données des cartes. Le but est donc</span>
<span style="color: #808080; font-style: italic;"># de prendre en entrée des coordonnées sous forme de latitudes et longitudes</span>
<span style="color: #808080; font-style: italic;"># saisies par l'utilisateur et d'afficher le nom des cartes sur son terminal.</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># Ex:</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># $ python ./find_map_by_coordinate.py (5, 32) (3, 44)</span>
<span style="color: #808080; font-style: italic;"># Trying to open database...</span>
<span style="color: #808080; font-style: italic;"># ...OK</span>
<span style="color: #808080; font-style: italic;"># Searching for (104, 32),  (201, 44)...</span>
<span style="color: #808080; font-style: italic;"># ...found.</span>
<span style="color: #808080; font-style: italic;"># ['/chemin/vers/carte1', '/chemin/vers/carte2']</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Comme d'habitude on a les imports en premier, ici l'auteur a choisi</span>
<span style="color: #808080; font-style: italic;"># de mettre les imports de ses propres modules avant ceux de la lib</span>
<span style="color: #808080; font-style: italic;"># standard, je recommande l'inverse.</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> ign25 <span style="color: #ff7700;font-weight:bold;">import</span> load_db, find
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> ast
&nbsp;
<span style="color: #808080; font-style: italic;"># Plutôt que de uniquement des prints, l'auteur choisit d'utiliser</span>
<span style="color: #808080; font-style: italic;"># le module de logging, mais l'utilise au final pour faire des prints.</span>
<span style="color: #808080; font-style: italic;"># Du coup je ne suis pas certains de l'interêt de la chose, peut être</span>
<span style="color: #808080; font-style: italic;"># que l'intention est de le faire plus plus tard.</span>
<span style="color: #808080; font-style: italic;"># Dans tous les cas il met le niveau de logging sur DEBUG, ce qui fait</span>
<span style="color: #808080; font-style: italic;"># que tous les messages seront affichés.</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">logging</span>
<span style="color: #dc143c;">logging</span>.<span style="color: black;">basicConfig</span><span style="color: black;">&#40;</span>level=<span style="color: #dc143c;">logging</span>.<span style="color: black;">DEBUG</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On a ici l'idiome connu qui permet de n'exécuter le bloc que si</span>
<span style="color: #808080; font-style: italic;"># le script et lancé directement (et pas importé). Dans ce cas c'est inutile,</span>
<span style="color: #808080; font-style: italic;"># en effet il n'y a rien dans ce script qu'on puisse vouloir importer, c'est</span>
<span style="color: #808080; font-style: italic;"># donc un script qui est TOUJOURS destiné à être lancé. Encore une fois</span>
<span style="color: #808080; font-style: italic;"># c'est peut être un indice d'une intention future de l'auteur.</span>
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;"># Le parsing des arguments est fait à la main. Pour un petit script</span>
    <span style="color: #808080; font-style: italic;"># comme ça ça a du sens (on a pas toujours envie de sortir l'artillerie</span>
    <span style="color: #808080; font-style: italic;"># lourde avec argparse)</span>
    <span style="color: #808080; font-style: italic;"># En gros, si il y a les deux arguments nécessaires (sys.argv contient</span>
    <span style="color: #808080; font-style: italic;"># le nom du script et chaque argument passé au script), on les traite,</span>
    <span style="color: #808080; font-style: italic;"># sinon on affiche un message indiquant comment utiliser le script.</span>
    <span style="color: #808080; font-style: italic;"># Le traitement des arguments est une évaluation du code comme si c'était</span>
    <span style="color: #808080; font-style: italic;"># du Python. Encore une fois je ne recommande pas cela, demander les</span>
    <span style="color: #808080; font-style: italic;"># degrés et les minutes sous la forme naturelle (34°27') et le parser</span>
    <span style="color: #808080; font-style: italic;"># avec des regex est plus propre ou de passer des longitudes et latitudes</span>
    <span style="color: #808080; font-style: italic;"># via 4 paramètres au lieu de deux ici.</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: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&gt;</span>= <span style="color: #ff4500;">3</span>:
        x = ast.<span style="color: black;">literal_eval</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        y = ast.<span style="color: black;">literal_eval</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><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: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;find map for given coordiantes&quot;</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;&quot;</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;usage: %s [lat] [lon]&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;       with [lat,lon] in degrees or in (degrees, minutes)&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Ici on fait appel à la fonction load_db() qui se connecte à la</span>
    <span style="color: #808080; font-style: italic;"># base de données</span>
    db = load_db<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># On lance la recherche dans la base de données avec la fonction find()</span>
    <span style="color: #808080; font-style: italic;"># qui est aussi issue du module ign25, et on affiche les résultats.</span>
    <span style="color: #dc143c;">logging</span>.<span style="color: black;">info</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Searching for %s, %s...&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>x, y<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    r = find<span style="color: black;">&#40;</span>db, x, y<span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">logging</span>.<span style="color: black;">info</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;...found.&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>r<span style="color: black;">&#41;</span></pre></div></div>

<h2>find_close_maps.py</h2>
<p>Je tique un peu. Il y a des trucs bizarres. Mais bon, c&#8217;est peut être moi.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Même principe, mais pour les cartes proche d'une autre carte. Je ne vais</span>
<span style="color: #808080; font-style: italic;"># donc que commenter les différences.</span>
<span style="color: #808080; font-style: italic;"># Il attend un fichier .map en paramètre et va lister toutes les cartes de</span>
<span style="color: #808080; font-style: italic;"># la base de données qui sont à 10km de la carte dont le fichier a été passé</span>
<span style="color: #808080; font-style: italic;"># en paramètres.</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">math</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">logging</span>
<span style="color: #dc143c;">logging</span>.<span style="color: black;">basicConfig</span><span style="color: black;">&#40;</span>level=<span style="color: #dc143c;">logging</span>.<span style="color: black;">DEBUG</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> ign25 <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&lt;</span> <span style="color: #ff4500;">2</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;find maps around a given map&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;usage: %s [reference map]&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
        <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
&nbsp;
    db = load_db<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># On ouvre le fichier de carte, et on récupère les coordonnées des 4</span>
    <span style="color: #808080; font-style: italic;"># extrémités du carré que forme la carte sous le forme d'un objet de type</span>
    <span style="color: #808080; font-style: italic;"># MapInfo qui contiendra les attributs nw, ne, se, sw (Nord-Ouest, Nord-Est,</span>
    <span style="color: #808080; font-style: italic;"># Sud-Est, Sud-Est)</span>
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        reference = get_info<span style="color: black;">&#40;</span><span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span> + <span style="color: #483d8b;">&quot;.map&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;map %s not found&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
    maxDistance = <span style="color: #ff4500;">10</span> <span style="color: #808080; font-style: italic;">#in km</span>
    <span style="color: #808080; font-style: italic;"># la distance maximale est écrite en dure, on pourrait la passer en paramètre</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Ensuite la recherche se fait avec encore une fois une fonction de</span>
    <span style="color: #808080; font-style: italic;"># ign25, donc la logique de ce script est assez simple puisque la</span>
    <span style="color: #808080; font-style: italic;"># complexité est dans ign25.py. On récupère une liste de carte.</span>
    closemaps = gen_closemaps<span style="color: black;">&#40;</span>db, reference, maxDistance<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># La liste est affichée mais on remplace la carte par une image de la carte</span>
    <span style="color: #808080; font-style: italic;"># au format PNG (qui je suppose est fournie avec la carte ?)</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> closemaps:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">abspath</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;../png/&quot;</span> + i.<span style="color: black;">filename</span> + <span style="color: #483d8b;">&quot;.png&quot;</span><span style="color: black;">&#41;</span></pre></div></div>

<h2>ign25.py</h2>
<div id="attachment_6519" class="wp-caption aligncenter" style="width: 476px"><a href="media/f654a46b.86399470.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/86399470.jpg"><img class="size-full wp-image-6519" title="... yet so far" src="media/f654a46b.86399470.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/07/86399470.jpg" alt="Photo d'un arbre planté à côté de son pot" width="466" height="600" /></a><p class="wp-caption-text">... yet so far</p></div>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot;Module to work with my set of IGN TOP25 maps
&nbsp;
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Toute la logique des scripts précédents est définie ici.</span>
<span style="color: #808080; font-style: italic;"># Encore une fois la docstring est un peu légère et des commentaires</span>
<span style="color: #808080; font-style: italic;"># en plus ne serait pas de refus car du coup pour comprendre ce que fais</span>
<span style="color: #808080; font-style: italic;"># le script juste en les recevant par email, c'est moins facile, forcément ^^</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Encore une fois, je vous invite à ne pas faire plein d'imports sur une ligne</span>
<span style="color: #808080; font-style: italic;"># si ils ne sont pas du même module. D'autant qu'ici les modules shutils et</span>
<span style="color: #808080; font-style: italic;"># math ne sont pas utilisé dans le script, et os.path est importé deux fois.</span>
<span style="color: #808080; font-style: italic;"># Cher auteur de script, loin de moi l'idée d'insulter ton travail, j'ai</span>
<span style="color: #808080; font-style: italic;"># conscience que tu es sans aucun doute un géographe et non un développeur,</span>
<span style="color: #808080; font-style: italic;"># ne m'en veut donc pas, je ne fais que commenter le script à des fins</span>
<span style="color: #808080; font-style: italic;"># pédagogiques et pas du tout pour te descendre. </span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>, <span style="color: #dc143c;">re</span>, <span style="color: #dc143c;">math</span>, <span style="color: #dc143c;">shutil</span>, <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>, <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> ast
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">logging</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">math</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Déclaration de constantes. Mettez les constantes en majuscules car la notion</span>
<span style="color: #808080; font-style: italic;"># de constante n'existe pas en Python et seule cette convention permet</span>
<span style="color: #808080; font-style: italic;"># de savoir qu'il ne faut pas y toucher.</span>
&nbsp;
easting2km = <span style="color: #ff4500;">0.73847</span>
northing2km = <span style="color: #ff4500;">0.53848</span>
northAdjust = easting2km / northing2km
&nbsp;
<span style="color: #808080; font-style: italic;"># Une classe vide qui va servir de conteneur. Je comprends que si l'on vient</span>
<span style="color: #808080; font-style: italic;"># d'un langage avec des structs, c'est une tendance naturelle. Néanmoins,</span>
<span style="color: #808080; font-style: italic;"># si il n'y a aucune logique associée à vos données, préférez un dictionnaire</span>
<span style="color: #808080; font-style: italic;"># ou un namedtuple.</span>
<span style="color: #ff7700;font-weight:bold;">class</span> MapInfo:
    <span style="color: #483d8b;">&quot;&quot;&quot;Store map information&quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Ah, un peu de doc, ça fait plaisir :-)</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Routines to read .map files</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> get_coordinates<span style="color: black;">&#40;</span>line<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Read the coordiantes of a point
&nbsp;
    line:       line describing the point
    returns:    a tuple of tuples ((xdeg, xmin), (ydeg, ymin))&quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        <span style="color: #808080; font-style: italic;"># La fonction analyse une ligne de texte formattée ainsi:</span>
        <span style="color: #808080; font-style: italic;"># champ1,    champ2    , champ3    ,    champ4...</span>
        <span style="color: #808080; font-style: italic;"># et en extrait les degrés et les minutes avec un split sur</span>
        <span style="color: #808080; font-style: italic;"># le caractère virgule entouré par un nombre indéterminé de caractères</span>
        <span style="color: #808080; font-style: italic;"># non imprimables (espaces, tabulations...)</span>
        fields = <span style="color: #dc143c;">re</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span> <span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\s</span>*,<span style="color: #000099; font-weight: bold;">\s</span>*&quot;</span>, line <span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># adjust for East, West. We are always in the northern hemisphere.</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Detecte si on est dans l'hémisphèse Nord (je suppose que le onzième</span>
        <span style="color: #808080; font-style: italic;"># champ est égale à &quot;W&quot; dans ce cas, et &quot;E&quot; dans l'autre cas mais</span>
        <span style="color: #808080; font-style: italic;"># je n'ai pas le format sous les yeux pour le vérifier).</span>
        <span style="color: #808080; font-style: italic;"># Bref, si on est dans l'hémisphère Nord, on donne aux champs une valeur</span>
        <span style="color: #808080; font-style: italic;"># négative. Je suppose que ça parle aux amateurs de GIS, comme je</span>
        <span style="color: #808080; font-style: italic;"># suis incompétent dans le domaine, je ne vais pas faire mon malin</span>
        <span style="color: #808080; font-style: italic;"># et tenter d'expliquer pourquoi.</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> fields<span style="color: black;">&#91;</span><span style="color: #ff4500;">11</span><span style="color: black;">&#93;</span> == <span style="color: #483d8b;">&quot;W&quot;</span>:
            fields<span style="color: black;">&#91;</span><span style="color: #ff4500;">9</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">&quot;-&quot;</span> + fields<span style="color: black;">&#91;</span><span style="color: #ff4500;">9</span><span style="color: black;">&#93;</span>
            fields<span style="color: black;">&#91;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">&quot;-&quot;</span> + fields<span style="color: black;">&#91;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#93;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># La fonction retourne ensuite un tuple de deux tuples avec les valeurs</span>
        <span style="color: #808080; font-style: italic;"># ou None si il a eu une erreur.</span>
        <span style="color: #808080; font-style: italic;"># Je ne sais pas où il peu y avoir une ValueError là dedans, donc</span>
        <span style="color: #808080; font-style: italic;"># difficile de dire quelle erreur l'auteur cherche à gérer.</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #008000;">int</span><span style="color: black;">&#40;</span>fields<span style="color: black;">&#91;</span><span style="color: #ff4500;">6</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">float</span><span style="color: black;">&#40;</span>fields<span style="color: black;">&#91;</span><span style="color: #ff4500;">7</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>, <span style="color: black;">&#40;</span><span style="color: #008000;">int</span><span style="color: black;">&#40;</span>fields<span style="color: black;">&#91;</span><span style="color: #ff4500;">9</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">float</span><span style="color: black;">&#40;</span>fields<span style="color: black;">&#91;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><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;">ValueError</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">None</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># La fonction utilisée dans find_close_maps.py, qui lit un fichier carte</span>
<span style="color: #808080; font-style: italic;"># (attend un file like object en paramètre) et retourne un objet MapInfo().</span>
<span style="color: #808080; font-style: italic;"># Comme je vous l'ai dis dans ce cas il vaudrait mieux retourner un dictionnaire</span>
<span style="color: #808080; font-style: italic;"># ou un namedtuple.</span>
<span style="color: #ff7700;font-weight:bold;">def</span> get_info<span style="color: black;">&#40;</span><span style="color: #008000;">file</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Read map information in `file`
&nbsp;
    file:       file object to read
    returns:    MapInfo&quot;&quot;&quot;</span>
    i = MapInfo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># Je pense que le but recherche est d'extraire le nom du fichier sans</span>
    <span style="color: #808080; font-style: italic;"># extention. os.path.splitext(file.name)[0] aurait été préférable</span>
    i.<span style="color: black;">filename</span> = <span style="color: #008000;">file</span>.<span style="color: black;">name</span><span style="color: black;">&#91;</span>:-<span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span>
    <span style="color: #808080; font-style: italic;"># Pour chaque ligne du fichier carte, on va vérifier si la ligne</span>
    <span style="color: #808080; font-style: italic;"># contient la chaîne Point0x, extraire les coordonnées de la ligne</span>
    <span style="color: #808080; font-style: italic;"># et les stocker dans un attribut représentant un des coins de la carte</span>
    <span style="color: #808080; font-style: italic;"># de l'objet MapInfo().</span>
    <span style="color: #808080; font-style: italic;">#</span>
    <span style="color: #808080; font-style: italic;"># Pour les améliorations possibles :</span>
    <span style="color: #808080; font-style: italic;"># - mettre le return dans la boucle for</span>
    <span style="color: #808080; font-style: italic;"># - re.match(r'regex', line) suffit</span>
    <span style="color: #808080; font-style: italic;"># - retourner None plutôt que False</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> line <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">file</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'Point03'</span><span style="color: black;">&#41;</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span>line<span style="color: black;">&#41;</span>:
            i.<span style="color: black;">nw</span> = get_coordinates<span style="color: black;">&#40;</span>line<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">elif</span> <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'Point02'</span><span style="color: black;">&#41;</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span>line<span style="color: black;">&#41;</span>:
            i.<span style="color: black;">ne</span> = get_coordinates<span style="color: black;">&#40;</span>line<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">elif</span> <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'Point04'</span><span style="color: black;">&#41;</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span>line<span style="color: black;">&#41;</span>:
            i.<span style="color: black;">sw</span> = get_coordinates<span style="color: black;">&#40;</span>line<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">elif</span> <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'Point01'</span><span style="color: black;">&#41;</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span>line<span style="color: black;">&#41;</span>:
            i.<span style="color: black;">se</span> = get_coordinates<span style="color: black;">&#40;</span>line<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">hasattr</span><span style="color: black;">&#40;</span>i, <span style="color: #483d8b;">'nw'</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> i
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">False</span>
<span style="color: #808080; font-style: italic;"># Une manière concise d'écrire la même fonction aurait pu être:</span>
<span style="color: #808080; font-style: italic;"># data = {'type': os.path.splitext(file.name)[0]}</span>
<span style="color: #808080; font-style: italic;"># for line in file:</span>
<span style="color: #808080; font-style: italic;">#     res = re.search('Point0(?P&lt;se&gt;1)?(?P&lt;ne&gt;2)?(?P&lt;nw&gt;3)?(?P&lt;sw&gt;3)?', line)</span>
<span style="color: #808080; font-style: italic;">#     if res:</span>
<span style="color: #808080; font-style: italic;">#         res = (name for name, val in res.groupdict().items() if val).next()</span>
<span style="color: #808080; font-style: italic;">#         data[name] = get_coordinates(line)</span>
<span style="color: #808080; font-style: italic;">#         if len(data) == 4</span>
<span style="color: #808080; font-style: italic;">#             return data</span>
<span style="color: #808080; font-style: italic;"># return None</span>
<span style="color: #808080; font-style: italic;"># Mais bon, la c'est de l'enculage de mouche, l'important c'est que ça marche.</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Cette fonction n'est pas appelée dans les autres scripts.</span>
<span style="color: #808080; font-style: italic;"># Elle retourne un générateur qui retourne, pour chaque fichier passé</span>
<span style="color: #808080; font-style: italic;"># dans l'itérable en paramètre (par exemple une liste de chemins de fichier)</span>
<span style="color: #808080; font-style: italic;"># un générateur donc chaque élément est un objet MapInfo contenant les</span>
<span style="color: #808080; font-style: italic;"># infos de la carte correspondant à chaque nom de fichier</span>
<span style="color: #ff7700;font-weight:bold;">def</span> gen_info<span style="color: black;">&#40;</span>filenames<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">for</span> filename <span style="color: #ff7700;font-weight:bold;">in</span> filenames:
        <span style="color: #ff7700;font-weight:bold;">try</span>:
            <span style="color: #dc143c;">logging</span>.<span style="color: black;">info</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Reading %s&quot;</span> <span style="color: #66cc66;">%</span> filename<span style="color: black;">&#41;</span>
            f = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>filename<span style="color: black;">&#41;</span>
            info = get_info<span style="color: black;">&#40;</span>f<span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> info:
                <span style="color: #ff7700;font-weight:bold;">yield</span> info
        <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">IOError</span>:
            <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Pareil, pas utilisé. Ca fabrique une liste en listant les fichiers d'un</span>
<span style="color: #808080; font-style: italic;"># dossier nomme &quot;map&quot; (on va supposé qu'il est déjà là ?), on passant</span>
<span style="color: #808080; font-style: italic;"># cette liste à gen_info() qu'on vient de voir plus haut, et en transformant</span>
<span style="color: #808080; font-style: italic;"># le générateur obtenu en liste.</span>
<span style="color: #ff7700;font-weight:bold;">def</span> generate_database<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">isdir</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'map'</span><span style="color: black;">&#41;</span>:
        mapdir = <span style="color: #483d8b;">'map'</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        mapdir = <span style="color: #483d8b;">'.'</span>
    fnames = <span style="color: #dc143c;">os</span>.<span style="color: black;">listdir</span> <span style="color: black;">&#40;</span>mapdir<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>gen_info<span style="color: black;">&#40;</span>fnames<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Routine to print db</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Idem, pas utilisé. On passe une base de données en paramètres</span>
<span style="color: #808080; font-style: italic;"># Et on print un listing de tous les fichiers de cartes de la BDD et</span>
<span style="color: #808080; font-style: italic;"># leurs coordonnées.</span>
<span style="color: #ff7700;font-weight:bold;">def</span> print_database<span style="color: black;">&#40;</span>db<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'filename,'</span>, <span style="color: #483d8b;">'nw,'</span>, <span style="color: #483d8b;">'ne,'</span>, <span style="color: #483d8b;">'sw,'</span>, <span style="color: #483d8b;">'se,'</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> db:
        <span style="color: #808080; font-style: italic;"># La seule partie compliquée : on définie une fonction</span>
        <span style="color: #808080; font-style: italic;"># dans le corps de la boucle for et on l'utilise cash pistache.</span>
        <span style="color: #808080; font-style: italic;"># Une manière plus propre aurait été :</span>
        <span style="color: #808080; font-style: italic;"># vals = (i.filename, i.nw, i.ne, i.sw, i.se)</span>
        <span style="color: #808080; font-style: italic;"># print ' '.join(str(x).replace(' ','') for x in vals)</span>
        <span style="color: #808080; font-style: italic;"># Si on avait un namedtuple plutôt qu'un objet, une ligne aurait suffit</span>
        <span style="color: #ff7700;font-weight:bold;">def</span> rms<span style="color: black;">&#40;</span>s<span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>s<span style="color: black;">&#41;</span>.<span style="color: black;">replace</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">' '</span>,<span style="color: #483d8b;">''</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> i.<span style="color: black;">filename</span>, rms<span style="color: black;">&#40;</span>i.<span style="color: black;">nw</span><span style="color: black;">&#41;</span>, rms<span style="color: black;">&#40;</span>i.<span style="color: black;">ne</span><span style="color: black;">&#41;</span>, rms<span style="color: black;">&#40;</span>i.<span style="color: black;">sw</span><span style="color: black;">&#41;</span>, rms<span style="color: black;">&#40;</span>i.<span style="color: black;">se</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Itou, pas utilisé. On prend chaque carte dd'un dossier, et on écrit</span>
<span style="color: #808080; font-style: italic;"># toutes les infos obtenues avec les fonctions précédentes dans un fichier.</span>
<span style="color: #808080; font-style: italic;"># Encore une fois notez que si on avait utilisé un namedtupple, l'opération</span>
<span style="color: #808080; font-style: italic;"># aurait pris 4 lignes.</span>
<span style="color: #808080; font-style: italic;"># Il y a néanmoins 3 choses qui m'interpellent dans ce code :</span>
<span style="color: #808080; font-style: italic;"># - pourquoi appeler ça une base de données ? C'est juste un listing texte</span>
<span style="color: #808080; font-style: italic;"># - pourquoi ne pas avoir choisit le format CSV (il y a un module pour ça)</span>
<span style="color: #808080; font-style: italic;"># - pourquoi writelineS() et pas writeline() ? Est-ce un bug ?</span>
<span style="color: #ff7700;font-weight:bold;">def</span> save_database<span style="color: black;">&#40;</span>db, path<span style="color: black;">&#41;</span>:
    f = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>path, <span style="color: #483d8b;">'w'</span><span style="color: black;">&#41;</span>
    f.<span style="color: black;">writelines</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'filename '</span>, <span style="color: #483d8b;">'nw '</span>, <span style="color: #483d8b;">'ne '</span>, <span style="color: #483d8b;">'sw '</span>, <span style="color: #483d8b;">'se '</span>, <span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\n</span>'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> db:
        <span style="color: #ff7700;font-weight:bold;">def</span> rms<span style="color: black;">&#40;</span>s<span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>s<span style="color: black;">&#41;</span>.<span style="color: black;">replace</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">' '</span>,<span style="color: #483d8b;">''</span><span style="color: black;">&#41;</span>
        f.<span style="color: black;">writelines</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>i.<span style="color: black;">filename</span>, <span style="color: #483d8b;">' '</span>,
                      rms<span style="color: black;">&#40;</span>i.<span style="color: black;">nw</span><span style="color: black;">&#41;</span>, <span style="color: #483d8b;">' '</span>,
                      rms<span style="color: black;">&#40;</span>i.<span style="color: black;">ne</span><span style="color: black;">&#41;</span>, <span style="color: #483d8b;">' '</span>,
                      rms<span style="color: black;">&#40;</span>i.<span style="color: black;">sw</span><span style="color: black;">&#41;</span>, <span style="color: #483d8b;">' '</span>,
                      rms<span style="color: black;">&#40;</span>i.<span style="color: black;">se</span><span style="color: black;">&#41;</span>, <span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\n</span>'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Routine to import db L'inverse de la fonction précédente. Chaque tout le</span>
<span style="color: #808080; font-style: italic;"># fichier et retourne une liste d'objet MapInfos(). Je pense que l'auteur ne</span>
<span style="color: #808080; font-style: italic;"># connais pas la fonction float()</span>
<span style="color: #ff7700;font-weight:bold;">def</span> import_database<span style="color: black;">&#40;</span>path<span style="color: black;">&#41;</span>:
    db = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
    f = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>path<span style="color: black;">&#41;</span>
    f.<span style="color: #dc143c;">readline</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> line <span style="color: #ff7700;font-weight:bold;">in</span> f:
        fields = line.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        i = MapInfo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        i.<span style="color: black;">filename</span> = <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>fields<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        i.<span style="color: black;">nw</span> = ast.<span style="color: black;">literal_eval</span><span style="color: black;">&#40;</span>fields<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        i.<span style="color: black;">ne</span> = ast.<span style="color: black;">literal_eval</span><span style="color: black;">&#40;</span>fields<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        i.<span style="color: black;">sw</span> = ast.<span style="color: black;">literal_eval</span><span style="color: black;">&#40;</span>fields<span style="color: black;">&#91;</span><span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        i.<span style="color: black;">se</span> = ast.<span style="color: black;">literal_eval</span><span style="color: black;">&#40;</span>fields<span style="color: black;">&#91;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        db.<span style="color: black;">append</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> db
&nbsp;
<span style="color: #808080; font-style: italic;"># Ca appelle import_database et si ça ne marche pas, ça</span>
<span style="color: #808080; font-style: italic;"># génère une &quot;base de données&quot;.</span>
<span style="color: #ff7700;font-weight:bold;">def</span> load_db<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        <span style="color: #dc143c;">logging</span>.<span style="color: black;">info</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Trying to open database...&quot;</span><span style="color: black;">&#41;</span>
        db = import_database<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;map.db&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">logging</span>.<span style="color: black;">info</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;...OK.&quot;</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: #dc143c;">logging</span>.<span style="color: black;">info</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;...failed. Reading .map files...&quot;</span><span style="color: black;">&#41;</span>
        db = generate_database<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">logging</span>.<span style="color: black;">info</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Saving database...&quot;</span><span style="color: black;">&#41;</span>
        save_database<span style="color: black;">&#40;</span>db, <span style="color: #483d8b;">&quot;map.db&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> db
&nbsp;
<span style="color: #808080; font-style: italic;"># Lat/lon to filename</span>
<span style="color: #808080; font-style: italic;"># Une fonction pour te rendre bien deg.</span>
<span style="color: #808080; font-style: italic;"># Elle converti un tuple ou une liste Latitude / Longitude en une valeur</span>
<span style="color: #808080; font-style: italic;"># en degré. Malheureusement elle tue complètement le duck typing (elle pourrait</span>
<span style="color: #808080; font-style: italic;"># accepter n'importe quel iterable). Une version pythonique serait :</span>
<span style="color: #808080; font-style: italic;"># try:</span>
<span style="color: #808080; font-style: italic;">#   deg, min = x # marche avec TOUT itérable</span>
<span style="color: #808080; font-style: italic;"># except TypeError:</span>
<span style="color: #808080; font-style: italic;">#   deg, min = x, 0</span>
<span style="color: #808080; font-style: italic;"># return float(deg) + float(min)/60. # accepte tout ce qui est castable en float</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #ff7700;font-weight:bold;">def</span> to_deg<span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># isinstance est rarement une bonne idée en Python. Très rarement.</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>x, <span style="color: #008000;">tuple</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>x, <span style="color: #008000;">list</span><span style="color: black;">&#41;</span>:
        xdeg, xmin = x <span style="color: #808080; font-style: italic;"># un bon petit unpacking !</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        xdeg = x
        xmin = <span style="color: #ff4500;">0</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> xdeg + xmin/<span style="color: #ff4500;">60</span>.
&nbsp;
<span style="color: #808080; font-style: italic;"># Trouve une carte qui contienne ces coordonnées, retourne le filename</span>
<span style="color: #808080; font-style: italic;"># plutôt que l'objet MapInfo() (pourquoi ?).</span>
<span style="color: #ff7700;font-weight:bold;">def</span> find<span style="color: black;">&#40;</span>db, x, y<span style="color: black;">&#41;</span>:
    target_xdeg = to_deg<span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>
    target_ydeg = to_deg<span style="color: black;">&#40;</span>y<span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;">#print &quot;target&quot;, target_xdeg, target_ydeg</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> db:
        nw_x, nw_y = i.<span style="color: black;">nw</span>
        se_x, se_y = i.<span style="color: black;">se</span>
        nw_xdeg = to_deg<span style="color: black;">&#40;</span>nw_x<span style="color: black;">&#41;</span>
        nw_ydeg = to_deg<span style="color: black;">&#40;</span>nw_y<span style="color: black;">&#41;</span>
        se_xdeg = to_deg<span style="color: black;">&#40;</span>se_x<span style="color: black;">&#41;</span>
        se_ydeg = to_deg<span style="color: black;">&#40;</span>se_y<span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># est-ce que les bordures de la carte contiennent les coordonnées ?</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> nw_xdeg <span style="color: #66cc66;">&lt;</span>= target_xdeg <span style="color: #ff7700;font-weight:bold;">and</span> target_xdeg <span style="color: #66cc66;">&lt;</span>= se_xdeg:
            <span style="color: #808080; font-style: italic;">#print &quot;candidate x&quot;, nw_xdeg, se_xdeg</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> nw_ydeg <span style="color: #66cc66;">&gt;</span>= target_ydeg <span style="color: #ff7700;font-weight:bold;">and</span> target_ydeg <span style="color: #66cc66;">&gt;</span>= se_ydeg:
                <span style="color: #808080; font-style: italic;">#print &quot;candidate y&quot;, nw_ydeg, se_ydeg</span>
                <span style="color: #ff7700;font-weight:bold;">return</span> i.<span style="color: black;">filename</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Close maps</span>
<span style="color: #808080; font-style: italic;"># Vérifie qu'une carte est proche d'une autre carte. Le PEP8 recommanderait</span>
<span style="color: #808080; font-style: italic;"># de l'appeler is_close().</span>
<span style="color: #ff7700;font-weight:bold;">def</span> isclose<span style="color: black;">&#40;</span>candidate, reference, max_distance<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> candidate.<span style="color: black;">filename</span> == reference.<span style="color: black;">filename</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">False</span>
    <span style="color: #808080; font-style: italic;"># put everything in minutes</span>
    <span style="color: #808080; font-style: italic;"># On repasse toutes les coordonnées en minutes</span>
    infoEastings = to_deg<span style="color: black;">&#40;</span>candidate.<span style="color: black;">nw</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">*</span><span style="color: #ff4500;">60</span>
    infoNorthings = to_deg<span style="color: black;">&#40;</span>candidate.<span style="color: black;">nw</span><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;">*</span><span style="color: #ff4500;">60</span><span style="color: #66cc66;">*</span>northAdjust
    referenceEastings = to_deg<span style="color: black;">&#40;</span>reference.<span style="color: black;">nw</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">*</span><span style="color: #ff4500;">60</span>
    referenceNorthings = to_deg<span style="color: black;">&#40;</span>reference.<span style="color: black;">nw</span><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;">*</span><span style="color: #ff4500;">60</span><span style="color: #66cc66;">*</span>northAdjust
&nbsp;
    <span style="color: #808080; font-style: italic;"># Pythagore, les maths de 6eme, ça vous revient ?</span>
    distance = <span style="color: black;">&#40;</span> <span style="color: #dc143c;">math</span>.<span style="color: black;">sqrt</span><span style="color: black;">&#40;</span>
        <span style="color: black;">&#40;</span> infoEastings - referenceEastings <span style="color: black;">&#41;</span><span style="color: #66cc66;">**</span><span style="color: #ff4500;">2</span> + <span style="color: black;">&#40;</span> infoNorthings - referenceNorthings <span style="color: black;">&#41;</span><span style="color: #66cc66;">**</span><span style="color: #ff4500;">2</span> <span style="color: black;">&#41;</span>
          <span style="color: #66cc66;">*</span> easting2km <span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> distance <span style="color: #66cc66;">&lt;</span> max_distance:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">True</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">False</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># un générateur qui yield toutes les cartes proches d'une distance</span>
<span style="color: #ff7700;font-weight:bold;">def</span> gen_closemaps<span style="color: black;">&#40;</span>db, reference, max_distance<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> db:
        <span style="color: #ff7700;font-weight:bold;">if</span> isclose<span style="color: black;">&#40;</span>i, reference, max_distance<span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">yield</span> i
&nbsp;
<span style="color: #808080; font-style: italic;"># Tile</span>
<span style="color: #808080; font-style: italic;"># Une fonction pas utilisée qui convertie les degré en..., heu... lat / long ?</span>
<span style="color: #808080; font-style: italic;"># Merci le module math de Python qui permet de s'amuser avec la trigonométrie</span>
<span style="color: #ff7700;font-weight:bold;">def</span> deg2num<span style="color: black;">&#40;</span>zoom, lat_deg, lon_deg<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Lon./lat. to tile numbers&quot;&quot;&quot;</span>
    lat_rad = <span style="color: #dc143c;">math</span>.<span style="color: black;">radians</span><span style="color: black;">&#40;</span>lat_deg<span style="color: black;">&#41;</span>
    n = <span style="color: #ff4500;">2.0</span> <span style="color: #66cc66;">**</span> zoom
    xtile = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>lon_deg + <span style="color: #ff4500;">180.0</span><span style="color: black;">&#41;</span> / <span style="color: #ff4500;">360.0</span> <span style="color: #66cc66;">*</span> n<span style="color: black;">&#41;</span>
    ytile = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1.0</span> - <span style="color: #dc143c;">math</span>.<span style="color: black;">log</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">math</span>.<span style="color: black;">tan</span><span style="color: black;">&#40;</span>lat_rad<span style="color: black;">&#41;</span> + <span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span> / <span style="color: #dc143c;">math</span>.<span style="color: black;">cos</span><span style="color: black;">&#40;</span>lat_rad<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> / <span style="color: #dc143c;">math</span>.<span style="color: black;">pi</span><span style="color: black;">&#41;</span> / <span style="color: #ff4500;">2.0</span> <span style="color: #66cc66;">*</span> n<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#40;</span>xtile, ytile<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Pareil, pas utilisé. C'est la fête du slip. On fait des fonctions pour</span>
<span style="color: #808080; font-style: italic;"># le fun, si ça se trouve on les importera un jour dans le shell, un dimanche</span>
<span style="color: #808080; font-style: italic;"># de pluie</span>
<span style="color: #ff7700;font-weight:bold;">def</span> num2deg<span style="color: black;">&#40;</span>zoom, xtile, ytile<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Tile numbers to lon./lat.&quot;&quot;&quot;</span>
    n = <span style="color: #ff4500;">2.0</span> <span style="color: #66cc66;">**</span> zoom
    lon_deg = xtile / n <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">360.0</span> - <span style="color: #ff4500;">180.0</span>
    lat_rad = <span style="color: #dc143c;">math</span>.<span style="color: black;">atan</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">math</span>.<span style="color: black;">sinh</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">math</span>.<span style="color: black;">pi</span> <span style="color: #66cc66;">*</span> <span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span> - <span style="color: #ff4500;">2</span> <span style="color: #66cc66;">*</span> ytile / n<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    lat_deg = <span style="color: #dc143c;">math</span>.<span style="color: black;">degrees</span><span style="color: black;">&#40;</span>lat_rad<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#40;</span>lat_deg, lon_deg<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># obtenir une les map qui contienne les coordonnées suivantes</span>
<span style="color: #808080; font-style: italic;"># Une tile est un morceau de carte qu'on compte utiliser pour faire une</span>
<span style="color: #808080; font-style: italic;"># carte plus grosse en assemblant les parties</span>
<span style="color: #ff7700;font-weight:bold;">def</span> get_tile<span style="color: black;">&#40;</span>z, x, y<span style="color: black;">&#41;</span>:
    lon_deg, lat_deg = num2deg<span style="color: black;">&#40;</span>z, x, y<span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">logging</span>.<span style="color: black;">debug</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;conv deg: %f, %f&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>lon_deg, lat_deg<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    db = load_db<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    filename = find<span style="color: black;">&#40;</span>db, lon_deg, lat_deg<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> filename
&nbsp;
<span style="color: #808080; font-style: italic;"># Une version plus simple de find_map_by_coordinate.py qui utilise</span>
<span style="color: #808080; font-style: italic;"># if __name__ == &quot;__main__&quot; à bon escient</span>
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&gt;</span>= <span style="color: #ff4500;">3</span>:
        x = ast.<span style="color: black;">literal_eval</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        y = ast.<span style="color: black;">literal_eval</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><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: #ff7700;font-weight:bold;">else</span>:
        x = <span style="color: black;">&#40;</span><span style="color: #ff4500;">48</span>, <span style="color: #ff4500;">41.29</span><span style="color: black;">&#41;</span>
        y = <span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">22</span><span style="color: black;">&#41;</span>
&nbsp;
    db = load_db<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #dc143c;">logging</span>.<span style="color: black;">info</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Searching %f, %f...&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>x, y<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    r = find<span style="color: black;">&#40;</span>db, x, y<span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">logging</span>.<span style="color: black;">info</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;...found: %s&quot;</span> <span style="color: #66cc66;">%</span> r<span style="color: black;">&#41;</span></pre></div></div>

<p>En conclusion, &#8220;tout est bien qui part à point sous les ponts&#8221;.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6518&amp;md5=5d5b8f2104135522e2b34ae9c890c634" 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>


