# articles

feed_id: http://sametmax.com/?p=7391
title: Si tôt revenu, si tôt repartu
uri: Si-tôt-revenu-si-tôt-repartu
url: http://sametmax.com/si-tot-revenu-si-tot-repartu/
content:
<p>Avec l&#8217;article goulu d&#8217;hier, certains ce sont dit, &#8220;chouette, enfin, les articles forts, beaux et puissants de Sam et Max&#8221; reviennent à la charge.</p>
<p>Mais je suis au regrès de vous annoncer que je me casse pour 4-5 jours pour aller courrir nu dans les bois. Ma bite ne captant pas la 3G, il n&#8217;y aura pas d&#8217;article pendant ce temps.</p>
<p>Donc je vous dis à la semaine&#8230;</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="420" height="315" src="//www.youtube.com/embed/6B5YK7kujPw#t=173" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<p>&#8230; prochaine !</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7391&amp;md5=794ebd7646c22efac6c07bdea44bdfed" 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=7435
title: Dites non aux animations 3D
uri: Dites-non-aux-animations-3D
url: http://sametmax.com/dites-non-aux-animations-3d/
content:
<p>Juste parce que vous pouvez ne veut pas dire que vous devez, et le fait que maintenant la plupart des navigateurs supportent des belles transitions 3D ne signifie certainement PAS que vous devriez les utiliser.</p>
<p>En ergonomie, une règle essentielle est de ne pas mettre ou faire de choses qui n&#8217;ont pas de valeur ajoutée pour l&#8217;utilisateur.</p>
<p>L&#8217;esthétique est certes, en soi, une valeur ajoutée. Mais il faut considérer deux choses :</p>
<ul>
<li>Cette technique apporte-t-elle une valeur esthétique qui n&#8217;est pas remplaçable par le bénéfice d&#8217;une autre technique ?</li>
<li>Le bénéfice que mon utilisateur en retire compense-t-il les inconvénients auxquels il est confronté ?</li>
</ul>
<p>Pour les animations 3D, la réponse est clairement NON, dans 99% des cas.</p>
<p>D&#8217;abord, généralement l&#8217;animation est lente, ne serait-ce que pour que le mec devant son écran puisse la voir. Vu le temps qu&#8217;on passe à se faire chier à rendre une app plus rapide et fluide à utiliser, pourquoi voulez-vous, VOLONTAIREMENT et ARTIFICIELLEMENT faire patienter votre utilisateur 400ms de plus devant le slide à cube rotatif pour voir la photo suivante ?</p>
<p>Ensuite, malgré l&#8217;énorme progrès de nos navigateurs, ça bouffe beaucoup de ressources. Bien sûr, quand vous testez sur votre machine quad core avec chrome et un tab ouvert, c&#8217;est parfaitement fluide. Mais il suffit de jouer sur seul de ces paramètres pour que ça ne le soit plus :</p>
<ul>
<li>20 tabs sont ouverts.</li>
<li>Un autre tab utilise Javascript comme un goret (Hello Twitter !).</li>
<li>Un autre tab utilise de la 3D.</li>
<li>Un autre tab charge beaucoup d&#8217;images.</li>
<li>Un autre tab utilise flash.</li>
<li>L&#8217;utilisateur a des logiciels récents sur une vieille machine.</li>
<li>L&#8217;utilisateur utilise d&#8217;autres logiciels que son navigateur qui sollicitent la carte graphique (quelle honte, il ose avoir une vie en dehors de facebook et votre site de merde!).</li>
</ul>
<p>Dans la vraie vie vivante, ce sont plusieurs de ces paramètres qui rentrent en compte, presque systématiquement. Et je ne vais même pas vous parler de ceux qui utilisent IE avec plein de toolbar sur une machine infectée jusqu&#8217;à la moelle. Qui sont, je le rappelle, la majorité des personnes dans le monde. Pas forcément la majorité de votre cible, mais tout de même&#8230;</p>
<p>&#8230;vous êtes une putain de page Web, vous ne pouvez pas pré-supposer de ce que l&#8217;utilisateur fait et dans quel contexte.</p>
<p>Bref, à moins d&#8217;avoir une app avec une connotation visuelle primordiale, par exemple un jeu vidéo, arrêtez avec ces foutues transitions 3D, ça rend votre app inutilisable. Les transitions 2D suffisent largement à améliorer l&#8217;ergonomie et l&#8217;esthétisme d&#8217;une page, et elles bouffent beaucoup moins.</p>
<p>Merci</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7435&amp;md5=ca53e86d6abbc9ce51ab8529089f5dd6" 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=7448
title: Les time zones en Python
uri: Les-time-zones-en-Python
url: http://sametmax.com/les-time-zones-en-python/
content:
<p>Si vous suivez un peu le blog, vous savez <a href="http://sametmax.com/manipuler-les-dates-et-les-durees-en-python/">comment manipuler les dates en Python</a>. Et c&#8217;est trop cool. Parce que le temps, c&#8217;est quelque chose de difficile en programmation, comme la gestion des monnaies ou la traduction d&#8217;une interface.</p>
<p>Mais notre article ne traite pas des time zones, c&#8217;est à dire de la gestion des fuseaux horaires. La raison est très simple, Sam est une grosse feignasse, et comme c&#8217;est un sujet <a href="http://lucumr.pocoo.org/2011/7/15/eppur-si-muove/">super galère</a>, il l&#8217;a soigneusement évité, vous renvoyant à l&#8217;usage de pytz. Démerdez vous.</p>
<p>Qu&#8217;est-ce qui a changé ? Le sujet est-il devenu plus simple ? Sam a-t-il un regain de motivation ? Le fait de parler de lui à la 3eme personne est-il signe de sénilité ?</p>
<p>Bien sûr que non, c&#8217;est simplement que je suis tombé sur <a href="http://crsmithdev.com/arrow/">arrow</a>, une lib Python qui résout le problème. Pour faire simple, c&#8217;est presque exactement la lib que j&#8217;avais commencé à coder pour la gestion du temps. Sauf que le mec, lui, il l&#8217;a terminé, alors que la mienne, elle est au fin fond d&#8217;un repo git poussiéreux depuis 8 mois.</p>
<p>Bref, laissez tout tomber, n&#8217;installez plus dateutil, pytz et autres libs que j&#8217;ai pu vous recommander par le passé (elle sont incluses et abstraites par arrow). Faites juste :</p>
<p><code>pip install arrow</code></p>
<h2>Tout commence par l&#8217;UTC</h2>
<p>Comme pour la gestion des encodings, la gestion des dates se fait en utilisant une base commune. Pour l&#8217;encoding, c&#8217;est unicode, pour les dates, c&#8217;est UTC.</p>
<p>Donc, si vous prévoyez de gérer différents fuseaux horaires dans votre programme, TOUT votre programme &#8211; j&#8217;ai dit TOUT &#8211; doit manipuler exclusivement des dates en UTC.</p>
<p>Comme avec l&#8217;encoding, l&#8217;idée est la suivante :</p>
<ul>
<li>A l&#8217;entrée de votre programme, vous acceptez des dates avec une timezone. Vous convertissez ces dates vers l&#8217;UTC.</li>
<li>Dans votre programme, vous manipuler uniquement de l&#8217;UTC.</li>
<li>A la sortie du programme, vous renvoyez des dates dans une timezone.</li>
</ul>
<p>Ceci suppose donc que :</p>
<ul>
<li>Vous savez ce qu&#8217;est une entrée et une sortie. Je vous fait un rappel : tout ce qui est pas dans votre programme (query base de données, socket, fichiers, print, input utilisateur, clic, affichage, etc.).</li>
<li>Vous DEVEZ savoir la timezone de ce qui rentre. <strong>Si vous ne le savez pas, vous ne pouvez absolument rien faire</strong> à part afficher à votre utilisateur que vous ne savez pas et le réglage par défaut . Pour la sortie, si vous ne savez pas, vous pouvez sortir de l&#8217;UTC par défaut, ça mange pas de pain. Mais pour l&#8217;entrée, il faut lire la spec, la doc, demandé au collègue, au fournisseur, au client, peut importe, il faut trouver l&#8217;info.</li>
</ul>
<h2>Avec arrow, c&#8217;est simplissime&#8230;</h2>
<p>Si vous créez une date vous même, il suffit de toujours le faire en UTC :</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> arrow
<span style="color: #66cc66;">&gt;&gt;&gt;</span> maintenant = arrow.<span style="color: black;">utcnow</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># heure et date actuelle en UTC</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>maintenant<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">2013</span>-<span style="color: #ff4500;">10</span>-15T17:<span style="color: #ff4500;">15</span>:<span style="color: #ff4500;">19.139000</span>+00:00
<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> date_de_sortie_des_goonies = arrow.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">datetime</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1985</span>, <span style="color: #ff4500;">12</span>, <span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>, <span style="color: #483d8b;">'US/Pacific'</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>date_de_sortie_des_goonies<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">1985</span>-<span style="color: #ff4500;">12</span>-04T00:00:00-08:00
<span style="color: #66cc66;">&gt;&gt;&gt;</span> date_de_sortie_des_goonies = date_de_sortie_des_goonies.<span style="color: black;">to</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'utc'</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>date_de_sortie_des_goonies<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">1985</span>-<span style="color: #ff4500;">12</span>-04T08:00:00+00:00
Là, on a des dates uniquements en UTC.</pre></div></div>

<p>Si vous importez une date, c&#8217;est très simple également :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> arrow.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1367900664</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># un timestamp marche..</span>
<span style="color: #66cc66;">&lt;</span>Arrow <span style="color: black;">&#91;</span><span style="color: #ff4500;">2013</span>-05-07T04:<span style="color: #ff4500;">24</span>:<span style="color: #ff4500;">24</span>+00:00<span style="color: black;">&#93;</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> arrow.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'1367900664'</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># ... même en string</span>
<span style="color: #66cc66;">&lt;</span>Arrow <span style="color: black;">&#91;</span><span style="color: #ff4500;">2013</span>-05-07T04:<span style="color: #ff4500;">24</span>:<span style="color: #ff4500;">24</span>+00:00<span style="color: black;">&#93;</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> arrow.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1367900664.152325</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># ... ou en float</span>
<span style="color: #66cc66;">&lt;</span>Arrow <span style="color: black;">&#91;</span><span style="color: #ff4500;">2013</span>-05-07T04:<span style="color: #ff4500;">24</span>:<span style="color: #ff4500;">24.152325</span>+00:00<span style="color: black;">&#93;</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> arrow.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'2013-09-30T15:34:00.000-07:00'</span><span style="color: black;">&#41;</span>.<span style="color: black;">to</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'utc'</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># parser une date standard...</span>
<span style="color: #66cc66;">&lt;</span>Arrow <span style="color: black;">&#91;</span><span style="color: #ff4500;">2013</span>-09-30T22:<span style="color: #ff4500;">34</span>:00+00:00<span style="color: black;">&#93;</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">from</span> dateutil <span style="color: #ff7700;font-weight:bold;">import</span> tz <span style="color: #808080; font-style: italic;"># pour parser une date custo</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> arrow.<span style="color: black;">Arrow</span>.<span style="color: black;">strptime</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'2013-05-05 12:30:45'</span>, <span style="color: #483d8b;">'%Y-%m-%d %H:%M:%S'</span>, tz.<span style="color: black;">gettz</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Paris/Europe'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>Arrow <span style="color: black;">&#91;</span><span style="color: #ff4500;">2013</span>-05-05T12:<span style="color: #ff4500;">30</span>:<span style="color: #ff4500;">45</span>+00:00<span style="color: black;">&#93;</span><span style="color: #66cc66;">&gt;</span></pre></div></div>

<p>Tout ça renvoie de l&#8217;UTC. </p>
<p>Et quand vous voulez afficher une date, vous pouvez tout simplement la reconvertir vers la timezone de votre choix avec la méthode <code>to()</code> et la formater comme avec <code>format()</code></p>
<h2>Stockage des dates</h2>
<p>Quand on stocke une date (dans une base de données, un fichier, etc), il faut se demander quel est le but du stockage. Si le but est de stocker la date d&#8217;un événement, mettez la date en UTC. Un timestamp suffit, ou alors la représentation YYYY-MM-DD hh:mm:ss. Par contre, si vous voulez stocker une date liée à un événement et un lieu (par exemple un rendez-vous d&#8217;affaire ou le décollage d&#8217;un avion), stockez la date en UTC avec sa timezone dans un champ à côté, sinon vous serez bien baisé quand vous voudrez la ressortir.</p>
<p>Ah oui, et réglez toujours tous vos serveurs sur UTC. Toujours.</p>
<h2>En bonus</h2>
<p>On peut obtenir toutes les infos utiles sans tourner autour du pot :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> a = arrow.<span style="color: black;">utcnow</span><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>a.<span style="color: #dc143c;">datetime</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">2013</span>-<span style="color: #ff4500;">10</span>-<span style="color: #ff4500;">15</span> <span style="color: #ff4500;">17</span>:<span style="color: #ff4500;">48</span>:<span style="color: #ff4500;">28.335000</span>+00:00
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>a.<span style="color: black;">timestamp</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">1381859308</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">repr</span><span style="color: black;">&#40;</span>a.<span style="color: black;">naive</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># on accès à l'objet datetime au cas où...</span>
<span style="color: #dc143c;">datetime</span>.<span style="color: #dc143c;">datetime</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2013</span>, <span style="color: #ff4500;">10</span>, <span style="color: #ff4500;">15</span>, <span style="color: #ff4500;">17</span>, <span style="color: #ff4500;">49</span>, <span style="color: #ff4500;">25</span>, <span style="color: #ff4500;">515000</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>a.<span style="color: black;">tzinfo</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># ... et à l'objet tzinfo</span>
tzutc<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>a.<span style="color: black;">year</span>, a.<span style="color: black;">hour</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#40;</span><span style="color: #ff4500;">2013</span>, <span style="color: #ff4500;">17</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Et on peut faire des replacements et des calculs flous, comme avec dateutil :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> a = arrow.<span style="color: black;">utcnow</span><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>a.<span style="color: black;">format</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'DD, MMMM'</span>, <span style="color: #dc143c;">locale</span>=<span style="color: #483d8b;">'fr_FR'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">15</span>, Octobre
<span style="color: #66cc66;">&gt;&gt;&gt;</span> a = a.<span style="color: black;">replace</span><span style="color: black;">&#40;</span>day=<span style="color: #ff4500;">30</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>a.<span style="color: black;">format</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'DD, MMMM'</span>, <span style="color: #dc143c;">locale</span>=<span style="color: #483d8b;">'fr_FR'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">30</span>, Octobre
<span style="color: #66cc66;">&gt;&gt;&gt;</span> a = a.<span style="color: black;">replace</span><span style="color: black;">&#40;</span>days=+<span style="color: #ff4500;">1</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>a.<span style="color: black;">format</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'DD, MMMM'</span>, <span style="color: #dc143c;">locale</span>=<span style="color: #483d8b;">'fr_FR'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">31</span>, Octobre
<span style="color: #66cc66;">&gt;&gt;&gt;</span> a = a.<span style="color: black;">replace</span><span style="color: black;">&#40;</span>months=-<span style="color: #ff4500;">1</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>a.<span style="color: black;">format</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'DD, MMMM'</span>, <span style="color: #dc143c;">locale</span>=<span style="color: #483d8b;">'fr_FR'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">30</span>, Septembre</pre></div></div>

<p>Faire de l&#8217;affichage relatif :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> before = arrow.<span style="color: black;">utcnow</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">replace</span><span style="color: black;">&#40;</span>hours=-<span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> before.<span style="color: black;">humanize</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">locale</span>=<span style="color: #483d8b;">'Fr_fr'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'il y a 3 heures'</span></pre></div></div>

<p>Bref, arrow, c&#8217;est de la bombe baby !</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7448&amp;md5=8544577e57bf6731aa84ee26834f36c2" 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=7458
title: 10 excellents films peu connus
uri: 10-excellents-films-peu-connus
url: http://sametmax.com/10-excellents-films-peu-connus/
content:
<p>Après <a href="http://sametmax.com/10-excellentes-series-peu-connues/">la thématique des séries</a>, petite aparté pour parler de 10 films qui méritent de votre temps, en cette époque où tellement de bouses essayent de vous le faire perdre en vous faisant payer pour ça.</p>
<h2>Dogma</h2>
<p><a href="http://www.imdb.com/title/tt0120655/?ref_=fn_al_tt_1">Ce film</a> est l&#8217;archétype du bijou inconnu.</p>
<p>D&#8217;abord, un casting monstrueux : Matt Damon, Ben Affleck, Alan Rickman, Chris Rock et Alanis Morissette (qui joue Dieu, si si).</p>
<p>Ensuite, un scénario complètement barré : Dieu (qui est une femme), a disparu. Deux anges qui ont tendance à massacrer un peu tout ce qui passe vont tenter d&#8217;en profiter pour baiser le système, ce qui pourrait causer quelques souci dans la stabilité du monde. Du coup on envoie le 13eme prophète, un oublié de la Bible parce qu&#8217;il est noir, filer un coup de main à la petite-petite-petite descendante de Jésus pour rétablir tout ça.</p>
<p>Les dialogues sont fantastiques, les personnages sont tous uniques et hauts en couleurs. Ai-je mentionné que c&#8217;était drôle ?</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="560" height="315" src="//www.youtube.com/embed/6FigprdcBGA" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<h2>Le prestige</h2>
<p>Bien avant de faire the Dark Knight, Christopher Nolan était déjà un réalisateur de génie avec des films uniques comme <a href="http://www.imdb.com/title/tt0209144/?ref_=fn_al_tt_1">Memento</a>. Mais bien au dessus de tout ça, bien au dessus de tous ses films en fait, se trouve le <a href="http://www.imdb.com/title/tt0482571/?ref_=fn_al_tt_1">Prestige</a>.</p>
<p>Déjà vous avez Wolverine et Batman dedans, et ça, ça claque. Et surtout, vous allez être embarqués dans une histoire que vous ne pourrez prédire à aucun moment. Aucun cliché, aucune manière de prédire ce qui va arriver. Vous allez vous enrichir, apprendre, et plonger dans les méandres de ce scénarios pourtant très simple, mais intensément mis en scène. Un duel entre deux prestidigitateurs s&#8217;étale sur plusieurs années, et vous allez découvrir, pas à pas, le prix du prestige.</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="560" height="315" src="//www.youtube.com/embed/qhGULSvtDO4" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<h2>Chat noir, chat blanc</h2>
<p><a href="http://www.imdb.com/title/tt0118843/?ref_=fn_al_tt_1">C&#8217;est Serbes</a>, c&#8217;est barré, c&#8217;est joyeux, c&#8217;est hyper dynamique et ça vous prend complètement au dépourvu. Attaque de trains d&#8217;essence, mariage forcé, jongle avec des grenades, suicide et résurrection. Les rebondissements ne s&#8217;arrêtent jamais, le tout dans une bande son qui va vous faire danser la Mouchkivtche Blévédienne.</p>
<p>Si vous avez besoin d&#8217;un dépaysement, c&#8217;est le moment.</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="420" height="315" src="//www.youtube.com/embed/CkoQcLgquWI" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<h2>La cité des enfants perdus</h2>
<p>Les gens connaissent Jeunet pour Amélie Poulain, et parfois, pour <a href="http://www.imdb.com/title/tt0101700/?ref_=fn_al_tt_1">Delicatessen</a>. Beaucoup plus rarement pour le étonnement bon Alien 4. Et quasiment jamais pour <a href="http://www.imdb.com/title/tt0112682/?ref_=fn_al_tt_1">la cité des enfants perdus</a>.</p>
<p>Chef d’œuvre visuel, je ne vous le recommanderais néanmoins pas durant les phases de déprime, car c&#8217;est un film très glauque, une marrais cinématographique psychologiquement violent, parfois dur à encaisser : un vieux scientifique vivant sur une plateforme pétrolière entourée de mines marines et de ses clones plus ou moins ratés, n&#8217;arrive pas à rêver. Pour y pallier, il kidnappe des nouveaux nés et tente de leur voler leurs rêves, n&#8217;obtenant que des cauchemar. Une frêle fille maline et un géant un peu bête trouvent une cause commune pour aller s&#8217;y aventurer&#8230;</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="560" height="315" src="//www.youtube.com/embed/FOJ6UGp8dj4" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<h2>Les Looney Tunes passent à l&#8217;action</h2>
<p>Je m&#8217;attendais à un Space Jam, et <a href="http://www.imdb.com/title/tt0318155/?ref_=fn_al_tt_3">je suis tombé</a> sur un Qui veut la peau de Roger Rabbit. Comme quoi il reste parfois un soupçon de créativité chez les majors. Mais vraiment au fond de l&#8217;assiette, hein.</p>
<p>Bref, c&#8217;est du dessin animé incrusté dans du film, à la Mary Poppins / l&#8217;Apprentie sorcière / Peter et Eliot le dragon. Les bons trucs à l&#8217;ancienne quoi. Mais modernisé. C&#8217;est cartoonesque dans l&#8217;hum(o|e)ur, avec pas mal d&#8217;auto-dérision sur Warner Bros, les grosses compagnies en général et les block busters en particulier.</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="560" height="315" src="//www.youtube.com/embed/3uuNGbMsb1A" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<h2>Jusqu&#8217;en enfer</h2>
<p>J&#8217;ai hésité à mettre <a href="http://www.imdb.com/title/tt0450385/?ref_=fn_al_tt_1">Chambre 1408</a>, mais ce dernier (comme beaucoup de bons films avec Cusack genre <a href="http://www.imdb.com/title/tt0884224/?ref_=fn_al_tt_1">War, inc</a>&#8230;), n&#8217;est pas un film qui fait peur. Or je voulais faire un top 10 un peu diversifié. Mais franchement, combien de films d&#8217;horreur font peur ? Presque aucun. En fait, la scène de Dumbo bourré (si, si, regardez à nouveau le film&#8230;) m&#8217;a bien plus effrayé que les merdes d&#8217;Insidious ou Paranormal activity. Et certes, Chucky, Jason, L&#8217;exorciste ou Freddy sont des classiques géniaux. Mais ils ne font pas vraiment peur. Même les bonnes surprises récentes (hello la cabanes dans les bois !) sont divertissantes, pas effrayantes.</p>
<p><a href="http://www.imdb.com/title/tt1127180/?ref_=fn_al_tt_1">Jusqu&#8217;en enfer</a> m&#8217;a fait sursauté bien des fois. J&#8217;ai vraiment senti l&#8217;angoisse s&#8217;installer, j&#8217;ai senti la panique des personnages, j&#8217;ai été trainé dans la spirale maléfique de ce film là où Dark Water m&#8217;a vainement tiré un bâillement.</p>
<p>Le scénario a en fait peu d&#8217;importance. Ce qui est génial, c&#8217;est le rythme. La descente. La progression lugubre bien maîtrisé, avec une subtilité que les productions américaines ont rarement. Et des acteurs qui soutiennent chaque plan, car il n&#8217;y a rien de plus facile à raté qu&#8217;une scène où l&#8217;on joue la terreur. Ce film est brillant de par sa progression : il commence tranquillement, et vous prend par derrière au plus mauvais moment. Même quand vous vous y attendez, il n&#8217;y a rien à faire.</p>
<p>Et hop, le film est en entier sur Tutube :</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="560" height="315" src="//www.youtube.com/embed/chsF8xwVTmE" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<h2>Explorers</h2>
<p>A cheval entre les Goonies et Jumanji, ce film qui a un poil vieilli va vous servir de madeleine des années 80. Souvenez-vous : retour vers le future, ghostbuster, gremlins, et des réalisateurs qui ne violaient pas encore les symboles de la jeunesse de leur public avec des Super 8 et Indiana Jones 4.</p>
<p><a href="http://www.imdb.com/title/tt0089114/?ref_=fn_al_tt_1">Explorers</a>, ce sont des gamins qui rêvent d&#8217;un plan de circuit electronique, et qui le construisent, pour s&#8217;apercevoir qu&#8217;il peut générer une bulle dans laquelle ont ne ressent aucune inertie, et qui peut traverser toute matière, se déplaçant avec peu d&#8217;énergie, transportant un fort poids. Et là commence une bonne aventure old school, avec des gosses bordéliques (franchement, vous avez vu les chambres bien rangés qu&#8217;ils ont dans les films actuels les gamins ?) avec des réactions de gosses et des préoccupations de gosses. Pas d&#8217;ados, pas de faux adultes. De gosses. Et des costumes ridicules.</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="420" height="315" src="//www.youtube.com/embed/3X3VxBJzH68" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<h2>Atomik Circus</h2>
<p>Si je ne peux pas vraiment vous décrire ce qu&#8217;est <a href="http://www.imdb.com/title/tt0362084/?ref_=fn_al_tt_1">Atomik Circus</a>, c&#8217;est parce que je m&#8217;en sens incapable. Ce film n&#8217;appartient à aucun genre, ne suis pas vraiment de logique, et n&#8217;a pas le goût de quoique ce soit de testé auparavant.</p>
<p>Dire pourquoi j&#8217;aime ce film me semble relever tout autant de impossibilité rédactionnelle : l&#8217;ambiance unique ? L&#8217;humour (très) noir ? Le côté imprévisible ? Les personnages tarés ?</p>
<p>Attendez, je vous traduis le résumé de IMDB, vous allez comprendre ce que je veux dire :</p>
<blockquote><p>James Bataille s&#8217;échappe de prison pour retrouver sa fiancée Concia. Mais à son retour des poulpes aliens viennent jouer un jeu de massacre. Après une bataille bien chanceuse, James et Concia s&#8217;échappent dans un monde parallèle.</p></blockquote>
<p>Et bien sachez mes amis, que ceci, bien que somme toute correcte, ne vous apprend RIEN sur le film. Et j&#8217;en veux pour preuve cet extrait :</p>
<p><iframe width="420" height="315" src="//www.youtube.com/embed/BkhplpjWHXk" frameborder="0" allowfullscreen></iframe></p>
<p>Tentez le coup. Avec des amis ouverts d&#8217;esprit :-)</p>
<h2>Heathers</h2>
<p>Ah, les teen movies. Ça ne peut pas être bon pas vrai ? Je veux dire, on en a bouffé du vampire, du loup garou, des demi-machin et des abrutis complets. A croire que le genre est maudis !</p>
<p>Mais pas du tout ! Le péril jeune, <a href="http://www.imdb.com/title/tt0088847/?ref_=fn_al_tt_1">The Breakfast club</a> et <a href="http://www.imdb.com/title/tt0091042/?ref_=fn_al_tt_4">Ferris Bueller&#8217;s Day Off</a> prouvent au contraire qu&#8217;on peut taper dans l&#8217;ado ET être intéressant. L&#8217;astuce, c&#8217;est de considérer les mineurs comme des être humains, comme les femmes, les juifs et les autistes.</p>
<p>Et la palme des répliques les plus trash revient à&#8230;.</p>
<blockquote><p>Fuck me gently with a chain saw</p></blockquote>
<p><iframe width="560" height="315" src="//www.youtube.com/embed/LQ-3rikUQ34" frameborder="0" allowfullscreen></iframe></p>
<h2>La peur au ventre</h2>
<p>Comment trouver un comparatif pour <a href="http://www.imdb.com/title/tt0404390/?ref_=fn_al_tt_1">La peur au ventre</a>. Pour le rythme, je pourrais invoquer les merveilleux Arnaque, crime, et botanique, Slevin ou Snatch. Clairement, il y aussi une inspiration d&#8217;Alice au pays des merveilles (restez pour le générique de fin, ça vaut le coup) pour le côté fuite dans un monde délirant. Et pour le côté transgressif et dépaysant, peut être un peu du surprenant <a href="http://www.imdb.com/title/tt0364569/?ref_=fn_al_tt_1">Old Boy</a>.</p>
<p>Je ne m&#8217;attendais pas du tout, mais alors, pas du tout, à ce que la peur au ventre me plaise. Mon pote me l&#8217;avait très mal vendu, et le synopsis est à chier.</p>
<p>Mais voilà, encore un scénariste qui a travaillé ses rebondissements et ses personnages. Encore des acteurs qui prennent leurs rôles très à cœur. Et une petit touche de magie qui donne à ce thriller une atmosphère bien à lui, de la personnalité et de la force.</p>
<p>Allez, finissons ce billet avec un peu de pédophilie, sinon on ne serait pas sur Sam et Max :</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="560" height="315" src="//www.youtube.com/embed/Nrz-h8sU85A" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<p>Par contre les commentaires les plus populaires sur youtube sont vraiment flippant.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7458&amp;md5=7fae130403802209514c3c3d16731caf" 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=7469
title: Ouvrir un fichier avec le bon programme en Python
uri: Ouvrir-un-fichier-avec-le-bon-programme-en-Python
url: http://sametmax.com/ouvrir-un-fichier-avec-le-bon-programme-en-python/
content:
<p>Votre logiciel doit permettre d&#8217;ouvrir un fichier avec un programme externe. Oui mais lequel ?</p>
<p>Les OS ont des réglages par défaut pour chaque type de fichier, et on peut demander &#8220;ouvrir le prog pour ce type de fichier par défaut&#8221;. Par exemple, moi, si je demande d&#8217;ouvrir un fichier vidéo, je m&#8217;attend à ce que VLC soit lancé.</p>
<p>Voilà comment faire ça en Python :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">subprocess</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;">os</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> run_file<span style="color: black;">&#40;</span>path<span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;"># Pas de EAFP cette fois puisqu'on est dans un process externe,</span>
    <span style="color: #808080; font-style: italic;"># on ne peut pas gérer l'exception aussi facilement, donc on fait</span>
    <span style="color: #808080; font-style: italic;"># des checks essentiels avant.</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Vérifier que le fichier existe</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">exists</span><span style="color: black;">&#40;</span>path<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #008000;">IOError</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'No such file: %s'</span> <span style="color: #66cc66;">%</span> path<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># On a accès en lecture ?</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">hasattr</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>, <span style="color: #483d8b;">'access'</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">access</span><span style="color: black;">&#40;</span>path, <span style="color: #dc143c;">os</span>.<span style="color: black;">R_OK</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #008000;">IOError</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Cannot access file: %s'</span> <span style="color: #66cc66;">%</span> path<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Lancer le bon programme pour le bon OS :</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">hasattr</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>, <span style="color: #483d8b;">'startfile'</span><span style="color: black;">&#41;</span>: <span style="color: #808080; font-style: italic;"># Windows</span>
        <span style="color: #808080; font-style: italic;"># Startfile est très limité sous Windows, on ne pourra pas savoir</span>
        <span style="color: #808080; font-style: italic;"># si il y a eu une erreu</span>
        proc = <span style="color: #dc143c;">os</span>.<span style="color: black;">startfile</span><span style="color: black;">&#40;</span>path<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">elif</span> <span style="color: #dc143c;">sys</span>.<span style="color: #dc143c;">platform</span>.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'linux'</span><span style="color: black;">&#41;</span>: <span style="color: #808080; font-style: italic;"># Linux:</span>
        proc = <span style="color: #dc143c;">subprocess</span>.<span style="color: black;">Popen</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'xdg-open'</span>, path<span style="color: black;">&#93;</span>, 
                                 <span style="color: #808080; font-style: italic;"># on capture stdin et out pour rendre le </span>
                                 <span style="color: #808080; font-style: italic;"># tout non bloquant</span>
                                 stdout=<span style="color: #dc143c;">subprocess</span>.<span style="color: black;">PIPE</span>, stderr=<span style="color: #dc143c;">subprocess</span>.<span style="color: black;">PIPE</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">elif</span> <span style="color: #dc143c;">sys</span>.<span style="color: #dc143c;">platform</span> == <span style="color: #483d8b;">'darwin'</span>: <span style="color: #808080; font-style: italic;"># Mac:</span>
        proc = <span style="color: #dc143c;">subprocess</span>.<span style="color: black;">Popen</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'open'</span>, <span style="color: #483d8b;">'--'</span>, path<span style="color: black;">&#93;</span>, 
                                stdout=<span style="color: #dc143c;">subprocess</span>.<span style="color: black;">PIPE</span>, stderr=<span style="color: #dc143c;">subprocess</span>.<span style="color: black;">PIPE</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #008000;">NotImplementedError</span><span style="color: black;">&#40;</span>
            <span style="color: #483d8b;">&quot;Your `%s` isn't a supported operatin system`.&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #dc143c;">sys</span>.<span style="color: #dc143c;">platform</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Proc sera toujours None sous Windows. Sous les autres OS, il permet de</span>
    <span style="color: #808080; font-style: italic;"># récupérer le status code du programme, and lire / ecrire sur stdin et out</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> proc</pre></div></div>

<p>C&#8217;était le petit snippet sympas du jour !</p>
<p>P.S : si quelqu&#8217;un utilise <del>BDSM</del> BSD ou Solaris, je veux bien qu&#8217;il complète le snippet.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7469&amp;md5=805b865a7efd4cc59774fee70bfd710e" 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=7473
title: Locked out from twitter
uri: Locked-out-from-twitter
url: http://sametmax.com/locked-out-from-twitter/
content:
<p>Hier, on a été accueilli par ça :</p>
<pre>
Sapristi ! Attendez un peu avant d'essayer de vous connecter de nouveau.

Pour éviter les abus, nous limitons le nombre de tentatives de connexion par heure.

Si le mot de passe de votre compte a été changé récemment, assurez-vous que toutes les applications tierces et tous les clients Twitter soient fermés avant de tenter de vous connecter à nouveau. Pour plus d'informations, veuillez consulter cet article d'aide.

Veuillez réessayer dans 60 minutes.
</pre>
<p>Donc je suppose que qu&#8217;un service quelconque s&#8217;est fait hacké, avec notre email dedans, et qu&#8217;un bot a défoncé notre compte twitté en tentant le bruteforce avec des variations du mot de passe du compte précédent. Bref, une bonne raison de plus d&#8217;utiliser lastpass pour générer des mots de passe pour chaque servie.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7473&amp;md5=48c6746180695cfae192ccaffcb0a85e" 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=7442
title: Dans les règles du lard
uri: Dans-les-règles-du-lard
url: http://sametmax.com/dans-les-regles-du-lard/
content:
<p>Il y a une scène que j&#8217;adore dans Californation, c&#8217;est au premier épisode, quand le principal protagoniste est (pour changer) au lit avec une donzelle, qui lui dit qu&#8217;aujourdhui elle ne peut pas. Ca donne :</p>
<ul>
<li>We can&#8217;t it&#8217;s dirty, dit la jeune effarouchée avec un air déçu.</li>
<li>Yes, it&#8217;s dirty&#8230; rétorque Hank, avec un air de satyre en lui sautant dessus.</li>
</ul>
<p>Pour moi c&#8217;est un peu pareil, je trouve les proverbes du genre &#8220;quand coule la rivière du sang emprunte le petit chemin boueux&#8221; complètement inutiles. </p>
<p>D&#8217;abord, si une meuf veut pas s&#8217;envoyer en l&#8217;air pendant ses règles, y a peu de chance qu&#8217;elle accepte la sodo. Ensuite, si vous ne voulez pas mettre votre bite devant quand ça saigne pour des pseudos raison d&#8217;hygiène, qu&#8217;est-ce que vous allez la carrer dans un trou un caca ?</p>
<p>La période des règles, c&#8217;est tip top. D&#8217;abord, elle peut pas tomber enceinte si on couche aux premiers jours des règles. Ensuite, c&#8217;est auto-lubrifié. Enfin, beaucoup de femmes sont particulièrement chaudes pendant la période des règles, don&#8217;t on s&#8217;amuse vachement.</p>
<p>Autant je ne recommande pas le cuni, autant on aurait tort de se priver d&#8217;une partie de jambe en l&#8217;air durant cette période. Pun intented.</p>
<p>Evidement laissez lui le temps de <a href="http://sametmax.com/le-travail-decriture-dans-le-domaine-du-cul/">tout retirer, y compris le tampax</a>.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7442&amp;md5=55688442bb8e73c8f26283e53bb2465d" 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=7423
title: Calcul décimaux avec norme IEEE 754/854 en Python
uri: Calcul-décimaux-avec-norme-IEEE-754-854-en-Python
url: http://sametmax.com/calcul-decimaux-avec-norme-ieee-754854-en-python/
content:
<p>Peut-on faire titre plus chiant que celui-là, je vous le demande ?</p>
<p>Toujours est-il que cet article n&#8217;interessera que des gens parfaitement chiants, à savoir des scientifiques tatillons, mais je sais qu&#8217;il y en a dans notre lectorat alors on va leur jeter un os.</p>
<p>Bref, vous savez que la division par zéro en Python, ça lève une exception :</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: #ff4500;">0</span>
---------------------------------------------------------------------------
<span style="color: #008000;">ZeroDivisionError</span>                         Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>ipython-input-<span style="color: #ff4500;">1</span>-b710d87c980c<span style="color: #66cc66;">&gt;</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #66cc66;">&lt;</span>module<span style="color: #66cc66;">&gt;</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
----<span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">1</span> <span style="color: #ff4500;">1</span> / <span style="color: #ff4500;">0</span>
&nbsp;
<span style="color: #008000;">ZeroDivisionError</span>: integer division <span style="color: #ff7700;font-weight:bold;">or</span> modulo by zero</pre></div></div>

<p>Certains esprits chagrins n&#8217;aiment pas ce comportement, et voudraient, par exemple, que cela retourne l&#8217;infini. Après tout, pourquoi pas.</p>
<p>N&#8217;y a-t-il rien qu&#8217;on puisse faire pour calmer la rétention anale qui se prépare à cette déconvenue ?</p>
<p>Bien sûr que si, on parle de Python voyons !</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;">decimal</span> <span style="color: #ff7700;font-weight:bold;">import</span> setcontext,ExtendedContext, Decimal 
<span style="color: #66cc66;">&gt;&gt;&gt;</span> setcontext<span style="color: black;">&#40;</span>ExtendedContext<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff4500;">1</span> / Decimal<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
Infinity
<span style="color: #66cc66;">&gt;&gt;&gt;</span> -<span style="color: #ff4500;">1</span> / Decimal<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
-Infinity</pre></div></div>

<p>Voilà. Si vous êtes une personne normale et manipulez des objets concrets comme des sous, des joujoux, des choux non additionnés avec des carottes ou des hashtags, les réglages par défaut sont parfaits. Mais si vous êtes un fan de scipy, traitant des matrices par bottes de douze, ça peut servir.</p>
<p>Spéciale dédicace à mes amis au CNRS. Bisoux partout !</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7423&amp;md5=267e78ed8905332a2ea979aa760cf1a8" 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=7494
title: Minibelt, la petite soeur de batbelt
uri: Minibelt-la-petite-soeur-de-batbelt
url: http://sametmax.com/minibelt-la-petite-soeur-de-batbelt/
content:
<p>Quand j&#8217;ai créé batbelt, j&#8217;ai voulu en faire une boîte à outils pour des trucs pratiques qu&#8217;on ne trouve pas dans la lib standard, et qui n&#8217;ont pas de thèmes particuliers. Une genre de collection de snippets que j&#8217;utiliserais pour tous mes gros projets.</p>
<p>Mais voilà, il y a des choses qu&#8217;on utilise souvent, et d&#8217;autres moins. Et <a href="http://sametmax.com/mon-premier-projet-python3/">certaines personnes</a> ne veulent pas installer un package complet avec plusieurs modules juste pour quelques fonctions. Surtout que tous les projets ne sont pas des gros projets.</p>
<p>C&#8217;est pourquoi j&#8217;ai créé <a href="https://github.com/sametmax/minibelt">minibelt</a>.</p>
<p>C&#8217;est un subset de batbelt <strong>qui tient dans UN fichier</strong>, et qui contient uniquement les fonctions qu&#8217;on utilise le plus souvent. Vous pouvez bien sûr l&#8217;installer avec <a href="http://sametmax.com/votre-python-aime-les-pip/">pip</a>, mais le plus simple, c&#8217;est de juste copier / coller le fichier et le mettre à côté de votre code, puis de l&#8217;oublier.</p>
<p>L&#8217;autre bonne nouvelle, c&#8217;est que puisqu&#8217;il y a moins de code, je me suis bougé le cul pour rendre minibelt compatible Python 2 et Python 3 (enfin je crois :-)). Le README contient aussi l&#8217;ensemble de la documentation nécessaire.</p>
<p>Peut être même qu&#8217;un jour de pluie, j&#8217;ajouterai des tests unitaires, soyons fou.</p>
<p>Enjoy.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7494&amp;md5=8b8a1a57131bdddca3610c99d625b82a" 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=7501
title: Rapide test d’Ubuntu 13.10
uri: Rapide-test-d-Ubuntu-13-10
url: http://sametmax.com/rapide-test-dubuntu-13-10/
content:
<p>Ubuntu 13.10 vient de sortir et j&#8217;ai donc fait une micro partition pour le tester.</p>
<p>Installation sans histoire, un peu plus de config que d&#8217;hab car il faut virer toutes les merdes intrusives pour la vie privée (mais heureusement, y a des settings pour ça). Pas beaucoup de modifs, apparemment ils ont bossé la vitesse et la stabilité, ce qui est rare pour une non LTS. </p>
<p>Le résultat est qu&#8217;on a un OS qui est beaucoup plus stable que ce que Canonical avait l&#8217;habitude de donner les premiers jours de release. Et légèrement plus rapide.</p>
<p>En fait je suis tenté de migrer (mais pas con au point de le faire avant quelques mois), c&#8217;est globalement agréable à utiliser, épuré et fluide. On a pas encore Mir installé par défaut (OUF), donc ça reste un truc viable, qui tourne bien, avec des paquets plus récents à dispo. </p>
<p>Mon seul chagrin, c&#8217;est la nouveau Nautilus. La recherche est maintenant récursive par défaut, et impossible à changer. <del datetime="2013-10-22T13:07:50+00:00">En prime, plus d&#8217;extensions possibles, du coup &#8220;open terminal here&#8221; et &#8220;compare with meld&#8221; partent à la poubelle, et je les aimais beaucoup.</del></p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7501&amp;md5=9cd758cab49143f3b4b32e4f2b81f3c5" 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=7507
title: Profiter du notebook de IPython
uri: Profiter-du-notebook-de-Ipython
url: http://sametmax.com/profiter-du-notebook-de-ipython/
content:
<p><a href="http://ipython.org">IPython</a> est un des outils qui me font trouver la programmation Python plus agréable que dans tous les autres langages : un shell avec <a href="http://sametmax.com/tag/ipython/">tellement d&#8217;astuces intégrées</a> que ça donne envie de vomir des arc-en-ciel.</p>
<p>Aujourd&#8217;hui je vais vous parler d&#8217;une fonctionnalité fantastique est très peu connue de IPython : <a href="http://ipython.org/notebook.html">le notebook</a>.</p>
<p>Si vous êtes scientifique ou manipulez pas mal de graphiques et de données numériques, <a href="http://www.randalolson.com/2012/05/12/a-short-demo-on-how-to-use-ipython-notebook-as-a-research-notebook/">c&#8217;est un must have</a>. Mais personnellement je trouve que c&#8217;est aussi un fantastique outil d&#8217;éducation, c&#8217;est génial pour les cours, les démos, et expérimenter avec du code inconnu.</p>
<p>Ça se présente sous la forme d&#8217;un shell IPython intégré dans une page Web, mais que l&#8217;on peut avoir sur son desktop, pas besoin d&#8217;avoir un serveur distant. Si vous avez un peu de temps, voici une vidéo de démo (avec un musique horrible) :</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="420" height="315" src="//www.youtube.com/embed/H6dLGQw9yFQ" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<p>L&#8217;installation sous Ubuntu, c&#8217;est juste :</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> ipython-notebook</pre></div></div>

<p>Pour Windows, il me semble, de mémoire, que c&#8217;est intégré dans l&#8217;exe. Pour Mac, je ne sais pas.</p>
<p>Et derrière il suffit de lancer la commande :</p>

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

<p>Et il va vous ouvrir votre navigateur avec un onglet sur votre notebook.</p>
<p>L’intérêt principal du notebook est que TOUT le code est coloré et est modifiable comme sur dans fichier mais TOUT le code est exécutable (et affiche son résultat juste après chaque ligne) comme dans un shell iPython, avec completion du code. Le meilleur des deux mondes quoi.</p>
<p>En prime on peut embeder du <a href="http://daringfireball.net/projects/markdown/syntax">markdown</a> (et donc des liens, des images, etc) dans le même notebook, sauvegarder ça pour plus tard, le partager, etc.</p>
<p>Personnellement, j&#8217;ai ceci dans mon .bashrc :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">notebook <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
    <span style="color: #007800;">processes</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">ps</span> aux <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-i</span> <span style="color: #660033;">-P</span> <span style="color: #ff0000;">&quot;ipython notebook&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">wc</span> -l<span style="color: #7a0874; font-weight: bold;">&#41;</span>
    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$processes</span> <span style="color: #660033;">-lt</span> <span style="color: #000000;">2</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span>
    <span style="color: #000000; font-weight: bold;">then</span>
        <span style="color: #7a0874; font-weight: bold;">pushd</span> <span style="color: #000000; font-weight: bold;">/</span>tmp
        <span style="color: #c20cb9; font-weight: bold;">nohup</span> ipython notebook <span style="color: #660033;">--port</span> <span style="color: #000000;">8889</span> <span style="color: #007800;">$1</span> <span style="color: #000000; font-weight: bold;">&amp;</span>
        <span style="color: #7a0874; font-weight: bold;">popd</span>
    <span style="color: #000000; font-weight: bold;">else</span>
        firefox http:<span style="color: #000000; font-weight: bold;">//</span>127.0.0.1:<span style="color: #000000;">8889</span>
    <span style="color: #000000; font-weight: bold;">fi</span>
<span style="color: #7a0874; font-weight: bold;">&#125;</span></pre></div></div>

<p>Comme ça en une commande je lance le serveur du notebook sur le port que je veux si il ne tourne pas, et si il tourne, j&#8217;ouvre firefox et ouvre un onglet dessus.</p>
<p>Quelques autres options très utiles :</p>
<p><strong>&#8211;pylab </strong>: Charger plein de libs pour transformer IPython en un matlab killer.<br />
<strong>&#8211;gui=lib </strong> : permet d&#8217;intégrer l&#8217;event loop de QT, wx, gtk, etc.<br />
<strong>&#8211;ip=0.0.0.0</strong> : si on veut que d&#8217;autres puisse accéder à notre notebook.</p>
<p>Il existe un <a href="http://nbviewer.ipython.org/">espèce de pastebin</a> spécialement fait pour le notebook, qui permet de partager ses expérimentations.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7507&amp;md5=e3d5a0aacc62ee0e8ac80d4d60319d9e" 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=7499
title: Installer SSH Plus sur Ubuntu
uri: Installer-SSH-Plus-sur-Ubuntu
url: http://sametmax.com/installer-ssh-plus-sur-ubuntu/
content:
<p><a href="http://sametmax.com/mon-environnement-de-travail/">Je vous avais parlé</a> de <a href="http://www.gulecha.org/2011/07/29/sshplus-a-sshmenu-compatible-appindicator/">SSH Plus</a>, mais sans mentionner son process d&#8217;install, un peu chiant.</p>
<p>Pour rappel, c&#8217;est un petit indicateur qui vous permet de lancer une commande arbitraire. Son usage principal est d&#8217;ouvrir un terminal qui se connecte immédiatement en SSH à un serveur distant, mais on peut y mettre n&#8217;importe quoi.</p>
<p>Pour l&#8217;installer :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;"># on installe les dépendances</span>
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> <span style="color: #c20cb9; font-weight: bold;">install</span> python-appindicator
<span style="color: #666666; font-style: italic;"># on se calle dans le dossier temporaire</span>
<span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #000000; font-weight: bold;">/</span>tmp
<span style="color: #666666; font-style: italic;"># on download le script en Python</span>
<span style="color: #c20cb9; font-weight: bold;">wget</span> https:<span style="color: #000000; font-weight: bold;">//</span>raw.github.com<span style="color: #000000; font-weight: bold;">/</span>anilgulecha<span style="color: #000000; font-weight: bold;">/</span>misc<span style="color: #000000; font-weight: bold;">/</span>master<span style="color: #000000; font-weight: bold;">/</span>sshplus.py
<span style="color: #666666; font-style: italic;"># on le copie dans le dossier des exécutables</span>
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">mv</span> sshplus.py <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>sshplus
<span style="color: #666666; font-style: italic;"># on le rend exécutable</span>
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">chmod</span> +x <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>sshplus</pre></div></div>

<p>Pour le lancer, il n&#8217;y a plus qu&#8217;à faire :</p>

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

<p>Dans un terminal.</p>
<p>Moi, je le rajoute dans ma liste des programme automatiquement lancé au démarrage, comme ça je n&#8217;y pense plus (&#8220;Dash&#8221; > &#8220;Applications au démarrage&#8221;).</p>
<p>Après, vous pouvez lui faire lancer les commandes que vous voulez, en les mettant dans le fichier de config (~/.sshplus) en suivant la syntaxe  </p>
<pre>Nom à afficher|commande|options</pre>
<p>Par exemple :</p>
<pre>Server Prod 12|guake|-t -n "new" -e "ssh username@adresse_ip"
</pre>
<p>Ceci va rajouter une entrée dans le menu nommée &#8220;Server Prod 12&#8243;. Si on clique dessus, ça lance <code>guake -t -n "new" -e "ssh username@adresse_ip"</code>, ce qui m&#8217;ouvre un nouvel onglet dans mon terminal guake avec lance la commande <code>ssh username@adresse_ip</code> juste après.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7499&amp;md5=41cedb422864ba4c710122ece621c37b" 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=7525
title: Afficher l’IP d’un visiteur – Django vs Nginx
uri: Afficher-la-vraie-IP-d-un-visiteur-Django-vs-Nginx
url: http://sametmax.com/afficher-la-vrai-ip-dun-visiteur-django-vs-nginx/
content:
<p>Lorsque l&#8217;on veut connaitre son ip on fait souvent appel à des sites du genre: <a href="http://www.whatismyip.com/">whatismyip.com</a>, <a href="http://www.mon-ip.com/">mon-ip.com</a> ou on utilise un ifconfig en ssh.<br />
Des fois on a aussi besoin de connaître l&#8217;ip d&#8217;un visiteur sur son site, 2 petites méthodes pour le faire sous Django et Nginx.</p>
<p><strong>Sous Django:</strong> </p>
<p>Dans l&#8217;<a href="https://docs.djangoproject.com/en/dev/topics/http/urls/">Urlconf</a></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">urlpatterns = patterns<span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span>,
    <span style="color: #808080; font-style: italic;"># return client IP</span>
    url<span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^my_ip$'</span>, get_ip<span style="color: black;">&#41;</span>,
<span style="color: black;">&#41;</span></pre></div></div>

<p>Créez une <a href="https://docs.djangoproject.com/en/dev/topics/http/views/">vue</a> du nom de get_ip qui sera utilisée par l&#8217;urlconf</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: #ff7700;font-weight:bold;">import</span> http
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> get_ip<span style="color: black;">&#40;</span>request<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
        Vue qui retourne l'IP du client
    &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">try</span>:
&nbsp;
    	<span style="color: #808080; font-style: italic;"># récupère l'ip du client</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> http.<span style="color: black;">HttpResponse</span><span style="color: black;">&#40;</span>request.<span style="color: black;">META</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;REMOTE_ADDR&quot;</span><span style="color: black;">&#93;</span> <span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">Exception</span>, e:
        <span style="color: #ff7700;font-weight:bold;">return</span> http.<span style="color: black;">HttpResponse</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'error %s'</span> <span style="color: #66cc66;">%</span> e<span style="color: black;">&#41;</span></pre></div></div>

<p>Le code ci-dessus peut retourner l&#8217;adresse locale (127.0.0.1) dans ce cas il faut tester l&#8217;existence de la variable <strong>HTTP_X_REAL_IP</strong>, certains serveurs web ont besoin d&#8217;être <a href="http://rtcamp.com/tutorials/nginx/forwarding-visitors-real-ip/">configuré</a>. </p>
<p><strong>Sous Nginx:</strong></p>
<p>Dans le fichier de configuration de nginx on écrit une nouvelle <a href="http://wiki.nginx.org/HttpCoreModule#location">location</a></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># return client ip</span>
location /my_ip <span style="color: black;">&#123;</span>
    default_type <span style="color: #483d8b;">'text/plain'</span><span style="color: #66cc66;">;</span>
    content_by_lua <span style="color: #483d8b;">'ngx.print(ngx.var.remote_addr)'</span><span style="color: #66cc66;">;</span>
<span style="color: black;">&#125;</span></pre></div></div>

<p>il suffit de se rendre à l&#8217;url http://monsite.com/my_ip pour voir s&#8217;afficher son ip. Cependant il faut avoir nginx compilé avec le module <a href="http://wiki.nginx.org/HttpLuaModule">Lua</a> ce qui peut être délicat si l&#8217;on a jamais compilé d&#8217;application.</p>
<p><strong><br />
Conclusion:</strong></p>
<p>Si l&#8217;on s&#8217;en réfère aux deux exemples ci dessus on serait tenté d&#8217;utiliser Nginx car en une seule ligne tout le bazar est réglé.<br />
Le hic c&#8217;est qu&#8217;il faut que Nginx soit compilé avec le module Lua pour afficher l&#8217;ip (sauf si quelqu&#8217;un connaît une autre façon d&#8217;afficher un message de sortie).<br />
La version Django n&#8217;est pas fiable à 100% car suivant comment est configuré votre serveur web il se peut que vous vous retrouviez avec une ip du genre 127.0.0.1.<br />
Il y a aussi la possibilité de parser le résultat des sites web cités en tout début d&#8217;article, certains proposent des Api je crois mais vous dépendez d&#8217;un autre service (on faisait ça au début) qui peuvent vous lâcher à tout moment (ce qui nous est arrivé).<br />
Personnellement je compile toujours nginx avec Lua et quelques autres modules, ça permet de s&#8217;affranchir de plus en plus du backend.</p>
<p>PS: j&#8217;ai mis à jour le titre car il laissait sous-entendre autre chose (merci à Sébastien)</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7525&amp;md5=5db442cb353a28e02057726c4e826969" 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=7541
title: WARNING: File not found. Did you forget to save?
uri: WARNING-File-not-found-Did-you-forget-to-save
url: http://sametmax.com/warning-file-not-found-did-you-forget-to-save/
content:
<p>Un lecteur nous a <a href="http://sametmax.com/profiter-du-notebook-de-ipython/#comment-15166">rapporté ce problème</a> quand il utilisait la commande magique <code>%edit</code> dans IPython avec Sublime Text.</p>
<p>Magie d&#8217;internet, un autre lecteur lui a répondu en comment, mais je me dis que donner un peu de visibilité à la réponse peut pas faire de mal, vu que je n&#8217;ai pas trouvé facilement la solution via <del datetime="2013-10-25T12:40:42+00:00">Google</del> DuckDuckGo.</p>
<p>L&#8217;idée est tout simplement d&#8217;utiliser l&#8217;option <code>-w</code> dans la ligne de commande pour appeler l&#8217;éditeur. En effet, sans cela l&#8217;appel à ST est non bloquant, et IPython perd la référence au processus sans avoir de valeur de retour.</p>
<p>Par exemple, dans votre <em>ipython_config.py</em> :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">c.<span style="color: black;">TerminalInteractiveShell</span>.<span style="color: black;">editor</span> = <span style="color: #483d8b;">&quot;sublime_text -w&quot;</span></pre></div></div>

 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7541&amp;md5=efc6c9f7dc228a171ec901c5c3d892ef" 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=7549
title: Évitez A TOUT PRIX le site airbnb
uri: Évitez-A-TOUT-PRIX-le-site-airbnb
url: http://sametmax.com/evitez-a-tout-prix-le-site-airbnb/
content:
<p>On m&#8217;avait dit beaucoup de bien de ce site, qui permet de trouver des logements pas chers chez l&#8217;habitant dans tous les pays du monde.</p>
<p>Effectivement, c&#8217;est bien foutu, c&#8217;est propre et lisible, et il y a du choix. Alors, partant quelques jours avec une copine en voyage, je me suis dis que ça se tentait.</p>
<p>A l&#8217;inscription, à la réservation, un long form à remplir, avec la carte à rentrer, la caution de 70 euros dans les dents, les frais que prend airbnb qui se rajoutent en dernière minute à la facture, etc. Bon, c&#8217;est du classique, pas de quoi en faire un fromage.</p>
<p>Là où ça se corse, c&#8217;est qu&#8217;APRES tout ce merdier habituel, je reçois une notification me signalant que <strong>ma réservation n&#8217;était pas envoyée.</strong></p>
<p>WHAT ?</p>
<p>Et non ! Il faut maintenant passer par un stade de &#8220;vérification&#8221;, pour votre sécurité, messieurs-dames.</p>
<p>A chaque fois que je lis &#8220;pour votre sécurité&#8221; (sur les panneaux signalant les caméras, les radars, sur les formulaires, sur les contrats, etc), j&#8217;ai des envies de meurtre. Je voudrais trouver le mec qui a écrit ces lignes et lui faire bouffer sa connerie pour voir si elle a un goût de sécurité.</p>
<p>D’abord, uploader un document d&#8217;identité.</p>
<p>Arg.</p>
<p>Bon, admettons, le mec va t’accueillir chez lui, tout ça, ils veulent rassurer le chaland. Ça fait grincer les dents du voyageur que je suis ce lissage des pratiques, mais je me soumet à l&#8217;exercice. C&#8217;est comme ça qu&#8217;on appâte le main stream et qu&#8217;on a plus de choix, moins cher.</p>
<p>Next page, demande de photo de profile obligatoire, publique.</p>
<p>Mais fuck !</p>
<p>J&#8217;ai pas envie que mon nom, mon prénom (qu&#8217;ils m&#8217;ont demandé, et affichent sans me prévenir dans mon profile) et ma photo soient sur le net, bordel.</p>
<p>Je mets un avatar de merde en espérant que les modos le voient pas.</p>
<p>Mais attention, il y a encore deux étapes !!!</p>
<p>Étape 3, pour des raisons de sécurité de mes couilles, il faut lier un compte en ligne. Mais tu te fous de ma gueule ???</p>
<p>Je lies un compte de test qui me sert à rien, un compte gmail de spam. Ils demandent évidement la permission de gérer mes contacts, parce que bien sûr, c&#8217;est indispensable&#8230; Toujours effectuer une sodomie après un prélèvement sanguin. C&#8217;est pour votre sécurité.</p>
<p>Et pour finir, faire une vidéo de 10 secondes avec ma cam, me présentant.</p>
<p>VAS TE FAIRE FOUTRE !</p>
<p>(en plus leur applet flash ne marche sous aucun nav sous Linux)</p>
<p>La seule bonne nouvelle, c&#8217;est que la fonction &#8220;supprimer le compte&#8221; est facile à trouver.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7549&amp;md5=b190ff94f4b320efb9b76c27cf48fbfe" 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=7557
title: Encore une pause
uri: Encore-une-pause
url: http://sametmax.com/encore-une-pause/
content:
<p>En ce moment c&#8217;est de la publication en pointillés, pas mal de déplacement, etc.</p>
<p>Bref, tout ça pour dire qu&#8217;on se retrouve le 5 ou le 6. Là, je me casse.</p>
<p>Mais Max m&#8217;a parlé d&#8217;un petit article sympa&#8230;</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7557&amp;md5=81acd127e138b3c3905027f4c18b36cc" 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=7563
title: Test de la JAMBOX de JAWBONE – Petit mais costaud !
uri: Test-de-la-JAMBOX-de-JAWBONE-Petit-mais-costaud
url: http://sametmax.com/test-de-la-jambox-de-jawbone-petit-mais-costaud/
content:
<p>Je suis quelqu&#8217;un qui voyage pas mal &#8211; pour ceux qui ont suivi le blog je suis actuellement à l&#8217;étranger (à l&#8217;hotel) et je suis amené à me déplacer dans divers pays &#8211; et j&#8217;aime avoir un fond sonore quand je code, quand je ramène une petite aussi, quand je me détends, quand je regarde un bon Ghostbusters, bref un peu tout le temps.</p>
<p>Les ordis portables valent pas grand chose en son, de ce que j&#8217;ai pu entendre ça manque de basses à mon goût, de profondeur dans les mediums, c&#8217;est plutot nasillard.<br />
Mon petit Mac Book Air toussote dès que je pousse un peu le son sur de la musique rock pour aller danser le Jerk, celui de Sam fait pas mieux et j&#8217;ai pas envie de me balader avec une chaine Hifi quand je veux mettre un peu de son à l&#8217;heure du Ricard.</p>
<p>Il y a de cela quelques mois Sam a acheté une JAMBOX de chez <a href="https://jawbone.com/speakers/jambox">Jawbone</a>, une petite boite rouge toute laide qui ressemble à une brique. Très septique et prêt à lui lancer une de mes fameuses phrases Coféenne &#8220;c&#8217;est de la merde&#8221; je suis resté asser surpris lorsque la petite brique s&#8217;est mise en action.</p>
<p>Avec les semaines l&#8217;idée de m&#8217;en procurer une me turlupina jusqu&#8217;à ce que je la trouve dans un &#8220;apple store&#8221; local pour seulement 95€ (140€ chez Amazon France, c&#8217;était une promo). J&#8217;ai sauté sur l&#8217;occas et je dois dire que je ne suis pas déçu du résultat. C&#8217;est parti pour un ptit test !</p>
<p><strong>Le tout en musique!</strong><br />
<iframe width="560" height="315" src="//www.youtube.com/embed/kkLTxsAhURw" frameborder="0" allowfullscreen></iframe></p>
<p><strong> Ouverturage de la boite:</strong></p>
<div id="attachment_7565" class="wp-caption aligncenter" style="width: 660px"><img src="media/c1fe3c1e.unbox.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/10/unbox.jpg" alt="" title="Jambox unboxed - aux côtés de notre étalon maison" width="650" height="462" class="size-full wp-image-7565" /><p class="wp-caption-text">Jambox unboxed - aux côtés de notre étalon maison</p></div>
<p>L&#8217;ensemble se compose de la jambox, d&#8217;un cordon mini jack et d&#8217;une alimentation bien foutue avec cordon usb/micro usb. Un peu trop d&#8217;emballage à mon goût mais c&#8217;est la mode à la &#8220;Aiepeulle&#8221;.<br />
J&#8217;ai pris soin d&#8217;y joindre un objet très courant afin de vous donner une idée de la taille. </p>
<div id="attachment_7569" class="wp-caption aligncenter" style="width: 660px"><img src="media/41b58c73.side.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/10/side.jpg" alt="" title="Jambox de profil" width="650" height="577" class="size-full wp-image-7569" /><p class="wp-caption-text">Bouton on/off, mini jack pour y brancher son smartphone old school ainsi que la prise micro usb de recharge</p></div>
<div id="attachment_7575" class="wp-caption aligncenter" style="width: 660px"><img src="media/0635f9f8.top_button.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/10/top_button.jpg" alt="" title="Tu me dis de le faire moins fort, je le fait moins fort..." width="650" height="492" class="size-full wp-image-7575" /><p class="wp-caption-text">Pratique les gros boutons de volume pour quand on est cuit...</p></div>
<p>Sur le côté on a 3 boutons, le bouton on/off et pairing pour la connexion bluetooth, un mini jack pour y brancher un casque, la prise micro usb pour recharger la bête. Sur le dessus le volume avec de gros boutons pour pas se louper quand on est cuit lors de l&#8217;apéro.<br />
La Jambox pèse quelques 300 grammes, pas très lourd au final pour le son qui en sort. Pour ce qui est de l&#8217;autonomie j&#8217;ai pu regarder un film sans problème et elle est donnée pour 10h (ce que je doute quand même, ça reste à tester)</p>
<div id="attachment_7571" class="wp-caption aligncenter" style="width: 660px"><img src="media/9cf44994.plug_telescopic.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/10/plug_telescopic.jpg" alt="" title="Prise rabatable" width="650" height="867" class="size-full wp-image-7571" /><p class="wp-caption-text">Prise rabatable, pratique pour quand on voyage avec sortie USB</p></div>
<p>Le chargeur est pas mal car sa prise est rabatable, ceux qui voyages apprécieront, de l&#8217;autre côté c&#8217;est une sortie USB sur laquelle le cordon d&#8217;alimentation USB/Micro USB se branche, là aussi c&#8217;est pas mal si on le casse on rachète juste le cordon.</p>
<p><strong>Branchagationnement:</strong></p>
<p>La Jambox peut se brancher soit par la prise mini jack soit par Bluetooth, pour le Bluetooth il suffit de jumeler les deux appareils en suivant la notice :p<br />
Attention! Sous Mac il se peut que le son grésille, j&#8217;ai eu ce problème et il faut modifier un fichier de config:</p>
<p>SOUS MAC<br />
Il faut changer le bitrate de la connexion Bluetooth. Dans un terminal:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">defaults <span style="color: #c20cb9; font-weight: bold;">write</span> com.apple.BluetoothAudioAgent <span style="color: #ff0000;">&quot;Apple Bitpool Min (editable)&quot;</span> <span style="color: #660033;">-integer</span> <span style="color: #000000;">48</span></pre></div></div>

<p>Redémarrez l&#8217;ordi, éteignez la lumière du salon, fermez le frigo, plantez un avocat pas trop mûr dans un bol à choucroute. Le problème devrait être résolu (en tous cas &#8220;chez moi ça marche&#8221;)</p>
<p><strong>Test en conditions sismiques:</strong></p>
<div id="attachment_7572" class="wp-caption aligncenter" style="width: 660px"><img src="media/550530e0.jambox_ass.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/10/jambox_ass.jpg" alt="" title="Houuuuu attention à la chute!" width="650" height="493" class="size-full wp-image-7572" /><p class="wp-caption-text">Parfaite tenue de route dans les mediums et les basses ! ça craque les Watts!</p></div>
<div id="attachment_7573" class="wp-caption aligncenter" style="width: 660px"><img src="media/28864f28.jambox_ass2.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/10/jambox_ass2.jpg" alt="" title="Regardes plus haut..." width="650" height="867" class="size-full wp-image-7573" /><p class="wp-caption-text">La pureté du son n&#039;a d&#039;égal que celle des lignes. Pointu, précis !</p></div>
<p>Une fois la bestiole connectée je lui ai imposé quelques tests sismo-sismiques qu&#8217;elle a remportée haut la main comme vous pouvez le constater sur ces photos.<br />
La première chose qui m&#8217;a surpris c&#8217;est les basses ! Profondes et moelleuses, à la fois dures et vigoureuses, non y a pas à dire ça vous rendrait un curé hétéro. Moi qui aime bien la deep house et la musique electro en général, je suis resté bluffé, j&#8217;ai testé aussi un peu de &#8220;<a href="http://www.youtube.com/watch?v=DRVvFYppU0w">classique</a>&#8220;, du <a href="http://www.youtube.com/watch?v=E49Z2L3yAZE">rock chrétien</a>, du <a href="http://www.youtube.com/watch?v=oXRjJdsljIQ">hallal</a>, ça pète bien.</p>
<p><strong>Conclusions:</strong><br />
Un pote est venu un soir et s&#8217;est connecté via son smartphone à la Jambox pour lancer sa playlist, c&#8217;était plutôt sympa car rapide sans se prendre la tête à trouver un câble, etc. C&#8217;est le côté cool du Bluettoth.<br />
Pour le moment je ne vois pas de bémol, même le prix est raisonnable (compter 150€ neuf) et le son est très bon, la bestiole se transporte partout (plage, hotels, pique-nique, etc) et l&#8217;autonomie est (sur le papier) très acceptable.</p>
<p>Aller une dernière&#8230;</p>
<div id="attachment_7580" class="wp-caption aligncenter" style="width: 310px"><img src="media/b16df295.jambxo_standup1.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/10/jambxo_standup1.jpg" alt="" title="C&#039;est pas un Layboy" width="300" height="969" class="size-full wp-image-7580" /><p class="wp-caption-text">la pureté des lignes...</p></div>
<p>A vous cognac Jay!</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7563&amp;md5=5f976825ac135949cfdf350111964767" 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=7602
title: Les annotations en Python 3
uri: Les-annotations-en-Python-3
url: http://sametmax.com/les-annotations-en-python-3/
content:
<p>Mais oui, on va parler un peu plus de Python 3 à partir de maintenant \o/</p>
<p>C&#8217;est qu&#8217;avec la prochaine version 3.4 qui <a href="http://docs.python.org/3.4/whatsnew/3.4.html">apporte tellement de bonnes choses</a>, <a href="https://docs.djangoproject.com/en/dev/releases/1.6/">Django 1.6</a>  pleinement compatible et des libs comme <a href="http://pillow.readthedocs.org/en/latest/">Pillow</a> et <a href="https://pypi.python.org/pypi/six/1.1.0">six</a> pour combler les trous, ça y est, on peut enfin s&#8217;y mettre.</p>
<p>Commençons donc par les <a href="http://www.python.org/dev/peps/pep-3107/">annotations</a>, feature simple, et qu&#8217;on ne retrouve pas backportée en 2.7.</p>
<h2>D&#8217;abord, à quoi servent les annotations ?</h2>
<p>A rien !</p>
<p>Non, non, je ne déconne pas. Non seulement les annotations sont parfaitement optionnelles, mais en plus elles n&#8217;ont aucun effet.</p>
<p>Je répète pour que ça rentre : vous n&#8217;avez pas à utiliser les annotations. Aucun programme Python n&#8217;a besoin d&#8217;utiliser les annotations. Vous pouvez programmer votre vie entière en Python sans avoir jamais à utiliser les annotations. Et si vous les utilisez, elles ne changeront rien à votre programme.</p>
<p>Point.</p>
<h2>Non, mais sérieux, ça sert à quoi ?</h2>
<p>Python est un langage très souple, et une raison de sa souplesse c&#8217;est que la nature des données que vous traitez est dynamiquement découverte à l’exécution. Particulièrement, le type des variables est dynamique. La portée des variable est dynamique.</p>
<p>Avantages :</p>
<ul>
<li>Le code est court et clair.</li>
<li>Le langage est très facile à apprendre.</li>
<li>On peut utiliser le duck typing.</li>
</ul>
<p>Inconvénients :</p>
<ul>
<li>Il faut écrire des informations en plus dans la doc.</li>
<li>Le code est plus lent car la VM ne peut optimiser le code pour les types.</li>
<li>Les IDE ont moins d&#8217;outils pour aider à la rédaction du code.</li>
</ul>
<p>C&#8217;est la nature de Python. Pour certains cas, c&#8217;est ce qu&#8217;on veut. Dans d&#8217;autres cas où ce n&#8217;est pas adapté, il faut choisir un autre langage.</p>
<p>Les annotations sont là pour corriger ce point : on va permettre de fournir des informations en plus, <strong>si, et seulement, si, on le souhaite</strong>.</p>
<p>Ces informations n&#8217;auront aucun impact sur l&#8217;exécution du code. La VM Python va les ignorer. Mais un outil extérieur pourra potentiellement les utiliser pour en faire quelque chose.</p>
<h2>Show me the code !</h2>
<p>Faites chauffer votre interpréteur de Python 3&#8230;</p>
<p>On peut annoter <strong>uniquement</strong> les paramètres d&#8217;une fonction (ou méthode) :</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> ma_fonction<span style="color: black;">&#40;</span>param1: <span style="color: #483d8b;">&quot;Une annotation&quot;</span>, param2: <span style="color: #ff4500;">1</span> + <span style="color: #ff4500;">1</span>, param3: <span style="color: #008000;">int</span><span style="color: black;">&#41;</span>:
...     <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>param1, param2, param3<span style="color: black;">&#41;</span>
...
<span style="color: #66cc66;">&gt;&gt;&gt;</span> ma_fonction<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>,<span style="color: #ff4500;">2</span>,<span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>  <span style="color: #808080; font-style: italic;"># une annotation ne change absolument RIEN</span>
<span style="color: #ff4500;">1</span> <span style="color: #ff4500;">2</span> <span style="color: #ff4500;">3</span></pre></div></div>

<p>L&#8217;annotation se note donc ainsi : nom du paramètre: annotation.</p>
<p>L&#8217;annotation PEUT être n&#8217;importe quelle expression Python valide. En fait l&#8217;annotation DOIT être une expression valide. Et <strong>cette expression sera exécutée</strong> une, et une seule fois, à l&#8217;initialisation du module. Le résultat sera stocké et accessible, via l&#8217;attribut <code>__annotations__</code> :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> ma_fonction.__annotations__
<span style="color: black;">&#123;</span><span style="color: #483d8b;">'param1'</span>: <span style="color: #483d8b;">'Une annotation'</span>, <span style="color: #483d8b;">'param2'</span>: <span style="color: #ff4500;">2</span>, <span style="color: #483d8b;">'param3'</span>: <span style="color: #66cc66;">&lt;</span>class <span style="color: #483d8b;">'int'</span><span style="color: #66cc66;">&gt;</span><span style="color: black;">&#125;</span></pre></div></div>

<p>Évidément, les annotations se mélangent sans problème avec les cas avancés de paramétrage :</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> ma_fonction<span style="color: black;">&#40;</span>param1 : <span style="color: #483d8b;">&quot;Une annotation&quot;</span> = <span style="color: #483d8b;">&quot;valeur par défaut&quot;</span>, <span style="color: #66cc66;">*</span>param2: <span style="color: #483d8b;">&quot;Autre annotation&quot;</span><span style="color: black;">&#41;</span>:
... <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>param1, param2<span style="color: black;">&#41;</span>
...
<span style="color: #66cc66;">&gt;&gt;&gt;</span> ma_fonction<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
valeur par défaut <span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>On peut également spécifier une annotation pour la valeur de retour :</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> ma_fonction<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> -<span style="color: #66cc66;">&gt;</span> <span style="color: #008000;">None</span>: <span style="color: #808080; font-style: italic;"># un petit goût de coffeescript</span>
...     <span style="color: #ff7700;font-weight:bold;">pass</span>
...
<span style="color: #66cc66;">&gt;&gt;&gt;</span> ma_fonction.__annotations__
<span style="color: black;">&#123;</span><span style="color: #483d8b;">'return'</span>: <span style="color: #008000;">None</span><span style="color: black;">&#125;</span></pre></div></div>

<p>Et combiner tout ce bordel pour faire des trucs bien compliqués qui vous garantissent la sécurité d&#8217;emploi, ce qui manque cruellement en Python (les trucs compliqués, pas la sécurité d&#8217;emploi&#8230;):</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">def</span> ma_fonction<span style="color: black;">&#40;</span>param1: <span style="color: #ff7700;font-weight:bold;">lambda</span> x: x <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">2</span>,
...                 <span style="color: black;">param2</span>: <span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> x: x <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span> = <span style="color: #ff4500;">5</span>,
...                 <span style="color: #66cc66;">**</span>params : <span style="color: #483d8b;">&quot;Keywords parameters rocks&quot;</span><span style="color: black;">&#41;</span> -<span style="color: #66cc66;">&gt;</span> <span style="color: #008000;">list</span>:
...     <span style="color: black;">res</span> = <span style="color: black;">&#91;</span>param1, param2<span style="color: black;">&#93;</span>
...     <span style="color: black;">res</span>.<span style="color: black;">extend</span><span style="color: black;">&#40;</span>params<span style="color: black;">&#41;</span>
...     <span style="color: #ff7700;font-weight:bold;">return</span> res
...
<span style="color: #66cc66;">&gt;&gt;&gt;</span> ma_fonction<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, param3=<span style="color: #ff4500;">3</span>, param4=<span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #483d8b;">'param4'</span>, <span style="color: #483d8b;">'param3'</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> ma_fonction.__annotations__
<span style="color: black;">&#123;</span><span style="color: #483d8b;">'return'</span>: <span style="color: #66cc66;">&lt;</span>class <span style="color: #483d8b;">'list'</span><span style="color: #66cc66;">&gt;</span>, <span style="color: #483d8b;">'param1'</span>: <span style="color: #66cc66;">&lt;</span>function <span style="color: #66cc66;">&lt;</span>lambda<span style="color: #66cc66;">&gt;</span> at 0x7f77a2982e60<span style="color: #66cc66;">&gt;</span>, <span style="color: #483d8b;">'param2'</span>: <span style="color: #ff4500;">4</span>, <span style="color: #483d8b;">'params'</span>: <span style="color: #483d8b;">'Keywords parameters rocks'</span><span style="color: black;">&#125;</span></pre></div></div>

<p>Les lambdas ne peuvent pas être annotées par contre.</p>
<h2>Le potentiel des annotations</h2>
<p>Les annotations sont le cas typique d&#8217;une fonctionnalité bac à sable. En clair, sur la mailling list il y a eu de nombreuses requêtes pour permettre de la vérification de type, de l&#8217;auto documentation, de la translittération et autres joyeusetés.</p>
<p>Ne sachant pas comment répondre de manière propre à ces demandes, ni lesquelles étaient les plus prioritaires, les annotations ont été créées. Le but et de laisser maintenant la communauté fabriquer les outils, et ainsi :</p>
<ul>
<li>Ceux pour les fonctionnalités les plus utilisées seront naturellement priorisées.</li>
<li>Les standards pour les annotations vont émerger par l&#8217;usage, et pas parce que Guido l&#8217;a décidé depuis son bureau au doigt mouillé.</li>
<li>Les fonctionnalités du genre &#8220;je veux un poney&#8221; seront tout simplement ignorées puisque personne ne travaillera suffisamment dessus (quand quelque chose est un caprice, le capricieux se sort rarement les extrémités manuelles de la cavité rectale.)</li>
</ul>
<p>Des outils comme <a href="http://www.fightingquaker.com/pyanno/">pyanno</a> donnaient déjà un exemple de ce que la communauté pouvait désirer. Reste à savoir si ce sera vraiment utilisé. Les gens qui font du Python sont rarement fan du Java. Mais le caractère optionnel de la chose pourrait bien ajouter un vrai plus au langage sans l&#8217;alourdir.</p>
<p>Voici donc ce qu&#8217;on peut attendre des outils tierces parties qui utiliseront les annotations dans le futur :</p>
<h3>Amélioration des performances</h3>
<p>L&#8217;utilisation de <a href="https://rpython.readthedocs.org/en/improve-docs/">RPython</a> pour coder <a href="http://pypy.org/">Pypy</a> a montré que les perfs de Python pouvaient être fantastiques, si on rajoutait quelques annotations. RPython, est, je le rappelle, un subset de Python (donc tout code RPython tourne dans l&#8217;interpréteur Python normal), mais avec des annotations de type, sous forme de commentaires.</p>
<p>On peut donc imaginer que dans le futur, les codes en fort besoin de perfs comme pour l&#8217;embarqué ou le traitement scientifique, pourront ajouter dans les parties clés de l&#8217;algo des annotations pour booster la vitesse ou diminuer la mémoire consommée. On parlerait ici alors d&#8217;annotation de type. <code>int</code>, <code>list</code>, <code>UneClasse</code> sont en effet des expressions Python valides&#8230;</p>
<p>L&#8217;avantage de l&#8217;annotation, c&#8217;est son caractère purement optionnel, qu&#8217;on peut ajouter seulement à certains codes, ou à une partie du code.</p>
<h3>Aide à la saisie</h3>
<p>Les IDE ont du mal avec Python. La complétion du code, l&#8217;aide en popup, la refactorisation automatique et toutes ces joyeusetés sont rarement bien implémentées.</p>
<p>Dans ma vie de tous les jours, je m&#8217;en branle. Je code tellement vite en Python, je ne m&#8217;en aperçois même pas. Mais quand j&#8217;utilise une nouvelle lib, ça peut être utile.</p>
<p>Typiquement, pour un code comme celui de <a href="https://github.com/sametmax/0bin/">0bin</a>, je ne me servirais pas des annotations. Mais pour une lib comme <a href="https://github.com/sametmax/minibelt">minibelt</a>, je prendrais peut être le temps de mettre des annotations de type, pour aider ceux qui vont l&#8217;utiliser. Ou une annotation pour signaler les exceptions que certaines fonctions peuvent lever.</p>
<h3>Génération de documentation</h3>
<p>Certains voient les annotations comme un complément aux docstrings. Ce n&#8217;est pas mon cas, mais je vous le note, au cas où ça devienne une tendance.</p>
<h3>Vérification de Type</h3>
<p>Dans la même lignée de l&#8217;aide à la saisie, pour certaines fonctions (c&#8217;est rare, mais ça arrive), on veut éviter le duck typing et forcer l&#8217;utilisateur à passer un type en particulier. Avoir cette possibilité via les annotations pourraient être utile.</p>
<p>Je suis septique sur cet usage, en effet des libs existent depuis des années pour faire cela, et plus, via des décorateurs, et ça n&#8217;est pas très utilisé. La différence est qu&#8217;un mécanisme standard pourra être détecté par les IDE.</p>
<p>Après on risque d&#8217;avoir des abus pour ce genre de fonctionnalités. Je vois d&#8217;ici arriver les codeurs d&#8217;autres langages caféinés, essayant de pousser l&#8217;usage d&#8217;une annotation rendant des attributs <code>private</code> :-)</p>
<p>Heureusement, les annotations seront normalement pour toujours optionnelles.</p>
<h3>Translittération de code</h3>
<p>Vous avez un code Python et vous voulez le transformer en code Cobol ? Bon, le compilateur de Pypy a déjà le potentiel de le faire, mais avec les annotations, il est potentiellement possible de rajouter suffisamment d&#8217;informations pour qu&#8217;on puisse toujours transformer un code de Python vers un autre langage Turing complet.</p>
<p>J&#8217;ai dit potentiellement.</p>
<h2>Je répète une dernière fois&#8230;</h2>
<p>Les annotations ne font rien. Elles n&#8217;ont pas le but de faire quelque chose et de toute façon sont optionnelles.</p>
<p>Leur but est de permettre à la communauté de créer des nouveaux outils utilisant les annotations et voir lesquels seront les plus utilisés, matures et désirés.</p>
<p>Pour le moment, il n&#8217;y a pas grand chose de fait avec, mais jusqu&#8217;ici Python 3 n&#8217;a pas été très populaire. Cela risque de changer avec 2014 qui propulsera Python 3.4 dans la cour des grands.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7602&amp;md5=07b3f32d4f8ec8a3a4e4363f39dbfc9b" 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=7621
title: La chute de la presse : internet en cause, vraiment ?
uri: La-chute-de-la-presse-internet-en-cause-vraiment
url: http://sametmax.com/la-chute-de-la-presse-quelles-causes/
content:
<p>Les gens qui lisent la presse d&#8217;information généraliste font partie de ceux qui ont le désir &#8211; à défaut d&#8217;y arriver effectivement &#8211; de faire un peu plus marcher leur cerveau que la moyenne.</p>
<p>Or, il est difficile de ne pas s&#8217;adonner à un triste bilan sur la dernière décennie de ses performances : <a href="http://www.dailykos.com/story/2011/11/25/1039957/-STUNNING-Comparing-U-S-World-Covers-for-TIME-Magazine">désinformation</a>, <a href="http://www.wat.tv/video/crise-euro-micro-trottoir-3zd6d_2idg5_.html">infantilisation du message</a>, <a href="http://www.lemonde.fr/idees/chat/2013/04/17/tour-d-horizon-de-l-actualite-coree-du-nord-terrorisme-defense_3161050_3232.html">sensationnalisme</a>, <a href="http://www.liberation.fr/monde/2013/10/27/destruction-des-armes-chimiques-la-syrie-dans-dans-les-delais_942672">manque d&#8217;analyse</a>, <a href="http://www.agoravox.fr/tribune-libre/article/quand-le-figaro-censure-des-75763">censure</a>, <a href="https://twitter.com/reymondin/status/311206675275198464">hypocrisie</a>, <a href="https://www.youtube.com/watch?v=tv53M1xcK0w">abus de marronniers et de sujets creux</a>, formes et formats éculés (alors que franchement, <a href="http://webdocu.fr/web-documentaire/2012/12/18/equipe-downi-explique-le-datajournalisme/">le renouveau est juste sous votre nez</a>), <a href="http://www.pearltrees.com/#/N-f=1_1760572&#038;N-fa=1092232&#038;N-p=12512785&#038;N-play=0&#038;N-s=1_1760572&#038;N-u=1_100951">relation évidente avec le pouvoir</a> (alors qu&#8217;on en attend un contre pouvoir, justement), et globalement, un manque de couilles évident, castrées par l&#8217;objectif financier.</p>
<p>Bref, la presse ne nous informe plus.</p>
<p>Et elle tombe des nues quand soudain, une source d&#8217;information neuve apparaît via internet, et que son public se barre.</p>
<p>Alors on crache sur les vilains pirates, ceux qui volent l&#8217;information et la publient ailleurs.</p>
<p>Le copier / coller est pourtant une pratique journalistique qui a atteint le statut de discipline Olympique.</p>
<p>Alors on crache sur les incompétents blogueurs qui ne sont que des amateurs ne vérifiant pas leurs sources.</p>
<p>La répétition aveugle d&#8217;une information non maîtrisée est pourtant un constat que tout spécialiste fait quotidiennement : vous le savez pour l&#8217;IT, mais j&#8217;ai discuté avec des avocats, des médecins, des agriculteurs&#8230; Tous sont effarés.</p>
<p>Alors on crache sur le modèle économique ! Comment ? Fournir une information gratuite ? Ça ne peut pas marcher ça, ma petite dame ! Nous on est sérieux ! Nous on bosse ! Nous on doit être payé !</p>
<p>Et pourtant, payé pour quoi ? Pour nous servir une information, au mieux réchauffée, mal digérée, composée d&#8217;ingrédients faisandés issus d&#8217;un producteur véreux dans une assiette sale ?</p>
<p>Je suis prêt à payer. <strong>Je paye des tas de choses sur le net.</strong> Vous n&#8217;avez pas remarqué comme tout le monde semble se faire un max de pognon sur Internet depuis les années 2000 ? Vous croyez qu&#8217;ils l&#8217;impriment ? Les gens paient. Surprise !</p>
<p>Je ne paie pas CETTE MERDE, c&#8217;est tout. À tous viser une ménagère de moins de 50 ans stéréotypée et sur-sollicitée, vous en avez perdu le cœur de votre revenu. </p>
<p>Les gens ne paient que ce qu&#8217;ils estiment avoir besoin d&#8217;acheter. Aussi étonnant que cela paraisse, ils ont un budget limité. Si, si. Et ils le dépense en entier. Parfois ils sont même à découvert. Étonnamment ça amène à prioriser.</p>
<p>Quand sur une échelle de valeur, &#8220;acheter un journal&#8221; est sous le barreau &#8220;obtenir des vies à Candy Crush&#8221;, on la ferme, et on se lance dans un peu d&#8217;introspection.</p>
<p>Si ça ne se vend pas, ce n&#8217;est pas parce que les gens sont de vils voleurs à l&#8217;esprit étroit. C&#8217;est parce qu&#8217;ils ne voient aucune raison de payer pour ça.</p>
<p>C&#8217;était pareil avec la musique en CD. Et Apple à tout raflé parce que les dinosaures n&#8217;ont pas compris comment faire de la thune sur le net et se sont mis à chialer au lieu de se bouger leurs gros culs bien engraissés par les ayant droit.</p>
<p>C&#8217;était pareil avec les films. Et Netflix a prouvé au monde que le piratage n&#8217;empêchait personne de faire des millions de bénéfice si on faisait ne serait-ce que mettre un peu de chantilly sur l&#8217;étron des produits habituels.</p>
<p>La presse ne nous a pas informé. Et en plus nous a emballé ça dans du papier toilette.</p>
<p>Personne n&#8217;achète un couteau qui ne coupe pas. Alors si en plus il est rouillé&#8230;</p>
<p>On est donc allé voir ailleurs.</p>
<p>Parce qu&#8217;on le pouvait, enfin.</p>
<p>Quand free est arrivé, le reste du marché s&#8217;est réveillé. On pouvait soudainement quitter le statu quo.</p>
<p>Avant la presse bénéficiait d&#8217;un marché captif où tous les acteurs s&#8217;étaient mis d&#8217;accord pour fournir des produits de la même médiocre qualité.</p>
<p>Et Internet est arrivé avec les blogueurs, les objecteurs de conscience, les journaux alternatifs, les wiki, les agrégateurs de news, les curateurs, les réseaux sociaux. Et une plate-forme sur laquelle le public pouvait répondre. S’exprimer. Juger. S’inscrire en faux. Les aborder, et les tutoyer. On pouvait soudainement quitter le statu quo.</p>
<p>Alors on l&#8217;a fait.</p>
<p>Un article comme celui-ci, vous ne le trouverez dans aucun journal. Or c&#8217;est exactement ce que je veux lire. Et devinez quoi ? Je n&#8217;ai pas été payé pour l&#8217;écrire. Et vous n&#8217;aurez pas à payer pour le lire. Il n&#8217;y a même pas de pub.</p>
<p>Si la presse veut de nouveau faire de l&#8217;argent, il va falloir qu&#8217;elle donne envie d&#8217;acheter. Il va falloir qu&#8217;elle fasse mieux que <a href="http://reflets.info">reflets</a>, <a href="http://sebsauvage.net">sebsauvage</a>, l&#8217;<a href="http://odieuxconnard.wordpress.com/">odieux connard</a>, <a href="http://www.maitre-eolas.fr">maitre eolas</a>, <a href="http://www.info-libre.fr/">info-libre</a> et l&#8217;ensemble des outils d&#8217;agrégation qui permettent de synthétiser, trier, filtrer et consulter exactement ce dont on a besoin, au meilleur moment.</p>
<p>Car clairement, je ne vais pas payer pour moins bien. Et actuellement, c&#8217;est exécrable.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7621&amp;md5=e9a964927c147042711d58e54ae88e0b" 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=7706
title: Parlez-nous de vous !
uri: Parlez-nous-de-vous
url: http://sametmax.com/parlez-nous-de-vous/
content:
<p>Depuis le temps qu&#8217;on pond des articles vous devez avoir cerné les personnages que sont Sam &#038; Max.<br />
Mais au fait nous on en sait pas beaucoup sur vous!<br />
ça serait sympa de nous raconter un peu votre vie, vos passions, vos fantasmes, ce qui vous passe par la tête.</p>
<p>Soyez pas timides, inutile de poster nom et prénom bien sur, mais en gros dans quelle région vous vous situez, votre jeunesse, pourquoi l&#8217;info et/ou la sodo, un bon ptit resto dans votre coin, ce qui vous fait bander, ce qui vous fait chier, bref votre vie quoi.</p>
<p><strong>Allez-y les cas soces, parlez-nous un peu de vous :)</strong></p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7706&amp;md5=4429c1cb9377d57f865cb6d671b6a258" 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=7660
title: Apprendre le python en 10 ans…
uri: Apprendre-le-python-en-10-ans
url: http://sametmax.com/apprendre-le-python-en-10-ans/
content:
<p style="text-align: center;"><em><small>Ceci est un post invité de <a href="http://sametmax.com/author/01ivier/">01ivier</a> posté sous licence <a href="http://creativecommons.org/licenses/by/3.0/">creative common 3.0 unported</a>.</small></em></p>
<p>Il y a quelques années, esseulé devant 1 millions de pixels noctures, j&#8217;ai tapé <em>&#8220;Comment devenir un hacker ?&#8221;</em> dans un monopolisant moteur de recherche&#8230;<br />
Comme ça&#8230;<br />
Pour déconner&#8230;</p>
<p>Je suis alors tombé sur le texte &#8220;<a href="media/3822024c.devenir_hacker.pdf" data-original-source="http://www.tice.ac-versailles.fr/logicielslibres/IMG/devenir_hacker.pdf">Comment devenir un hacker ?</a>&#8221; d&#8217;Eric Steven Raymond.</p>
<p>Après quelques instants dubitatifs où j&#8217;ai pris conscience que si j&#8217;avais écrit <em>&#8220;Comment planter des choux ?&#8221;</em> ou autres <em>&#8220;Comment dessiner un poulet en contre-plongée ?&#8221;</em> je serai certainement tombé sur un document du même nom, j&#8217;ai commencé à lire le texte en question.<br />
Mais ce n&#8217;est que plusieurs mois après que j&#8217;en suis venu à bout.</p>
<p>En effet, arrivé à la partie <em>&#8220;Apprenez à programmer&#8221;</em>, j&#8217;ai non seulement réalisé que je ne savais pas vraiment programmer mais surtout que je pouvais dès à présent mettre à l&#8217;épreuve ma théorie sur les choux et les poulets.<br />
J&#8217;ai donc cherché <em>&#8220;Comment apprendre à programmer ?&#8221;</em> et j&#8217;ai fini par tomber sur l&#8217;article &#8220;<a href="http://www.vizmatic.com/apprenez-a-programmer-en-dix-ans/lang/fr">Apprendre à programmer en 10 ans ?</a>&#8221;</p>
<p>Celui-là, je l&#8217;ai lu en entier et d&#8217;une seule traite.<br />
Mais le titre seulement avait suffit à me décomplexer pour deux ou trois vies.</p>
<h2>Comment acquérir une compétence en 10 ans?</h2>
<p>Quelle évidence !<br />
Tout me paraissait bien plus envisageable en me donnant 10 ans pour y arriver&#8230;<br />
Je veux apprendre l&#8217;espagnol ? Et bien je ferai le bilan dans 10 ans&#8230;<br />
Pas besoin de culpabiliser parce que je n&#8217;ai pas fait la page du jour de la méthode à Mimile&#8230;</p>
<p>Il devait être 1h du matin et je me suis dit :<br />
<em>&#8220;Et si j&#8217;apprenais le Python&#8230;&#8221;</em><br />
J&#8217;avais 10 ans devant moi, mais ce n&#8217;était pas une raison pour perdre du temps.</p>
<p>À 6h, j&#8217;avais donc bouclé la première partie du tuto &#8220;<a href="http://www.siteduzero.com/tutoriel-3-223267-apprendre-python.html">Apprendre le Python</a>&#8221; du site du zéro et entamé la seconde&#8230;</p>
<p>Maintenant, vous vous demandez peut-être, si, trois an plus tard, je connais le Python&#8230;<br />
Et bien je vous dirais ça dans sept ans&#8230; :-)</p>
<h2>Hello world !</h2>
<p>En attendant, j&#8217;ai proposé à Sam et Max de poster quelques articles de temps en temps&#8230;<br />
Je ne suis pas du tout developpeur, mais je n&#8217;ai aucun scrupule à écrire des lignes de code&#8230; encore moins à publier ma prose de cochon&#8230;</p>
<p>Sachant qu&#8217;il est tout à fait possible d&#8217;obtenir des résultats enthousiasmants avec du code bancal, je me propose donc de décomplexer les débutants en publiant des articles de mauvais élève&#8230;<br />
Nulle doute que les lecteurs avertis de S&#038;M sauront, par leurs commentaires avisés, réhausser le niveau technique de mes posts afin de les rendre aussi instructifs que ceux déjà disponibles sur ce blog&#8230;</p>
<p>À bientôt&#8230;</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7660&amp;md5=9c30d5e7fe68b9db86cf98f5cecc9980" 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=7716
title: Mise à jour de Django-quicky pour supporter django 1.6
uri: Mise-à-jour-de-Django-quicky-pour-supporter-django-1-6
url: http://sametmax.com/mise-a-jour-de-django-quicky-pour-supporter-django-1-6/
content:
<p>Avec Django 1.6 qui vient de sortir hier, j&#8217;ai pu m’apercevoir que <a href="http://sametmax.com/django-quicky-labolition-des-preliminaires-par-sam-et-max/">django-quicky</a> ne marchait plus sur cette nouvelle version. Un sombre histoire de <code>setup_environ</code> qui est deprecated. Comme je l&#8217;utilise (ce qui est mieux avec les outils qu&#8217;on code ^^), j&#8217;ai fait un petit correctif vite-fait.</p>
<p>J&#8217;en ai profité aussi pour ajouter deux fichiers de requirements avec des apps Python que j&#8217;installe très très souvent pour mes projets.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7716&amp;md5=be71a871dc7dfb8dc4e81752048c781e" 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=7698
uri: Preprocesser-ses-fichiers-statiques-et-recharger-son-navigateur-automa
title:
Preprocesser ses fichiers statiques et recharger son navigateur automatiquement avec Python livereload

url:
http://sametmax.com/preprocesser-ses-fichiers-statiques-et-recharger-son-navigateur-automatiquement-avec-python-livereload/

content:
<p>Livereload est une extension multi-navigateur qui permet de recharger tout ou partie d&#8217;une page quand un fichier a changé sur le disque. </p>
<p>C&#8217;est très pratique pour développer un site Web puisque si vous modifiez un template, un fichier JavaScript, une image ou un fichier CSS, vous n&#8217;avez pas besoin de cliquer sur la fenêtre du navigateur et appuyez sur F5 pour voir le résultat. Si vous avez un double écran (et si vous faites du dev Web, vous devriez), vous ne quittez pas votre éditeur de code.</p>
<p>L&#8217;extension est gratuite, mais le serveur existe en plusieurs version. Il y a une version graphique pour Windows et Mac qui est payante. Si vous avez un peu de budget et pas envie de vous prendre la tête, <a href="http://livereload.com/">achetez là</a> et arrêtez la lecture de l&#8217;article, c&#8217;est beaucoup plus facile.</p>
<p>Sinon, suivez le guide pour la version gratos en ligne de commande.</p>
<h2>Installation</h2>
<p>Il existe une version Python en ligne de commande du serveur : <a href="http://livereload.readthedocs.org/en/latest/install.html">Python livereload</a>. Il y a aussi <a href="https://github.com/guard/guard-livereload">une version pour les rubistes</a>.</p>
<p>Je vous invite donc à l&#8217;installer avec <a href="http://sametmax.com/votre-python-aime-les-pip/">pip</a>:</p>

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

<p>Il vous faudra aussi l&#8217;<a href="http://feedback.livereload.com/knowledgebase/articles/86242-how-do-i-install-and-use-the-browser-extensions-">extension de navigateur</a>.</p>
<p>Après, depuis votre terminal, mettez vous dans le dossier que vous voulez surveiller (par exemple le dossier contenant vos fichiers CSS), et lancez le serveur :</p>

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

<p>Et activez l&#8217;extension pour la page que vous voulez recharger automatiquement. Normalement, c&#8217;est juste un clic sur un bouton.</p>
<p>C&#8217;est bon, votre page devrait recharger automatiquement.</p>
<h2>Rechargement à la carte</h2>
<p>On peut choisir ce qu&#8217;on va recharger plus précisément en créant un fichier de configuration.</p>
<p>Créez un fichier de code Python nommé &#8220;Guardfile&#8221;, sans l&#8217;extension &#8220;.py&#8221;. Il va ressembler à 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>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> livereload.<span style="color: black;">task</span> <span style="color: #ff7700;font-weight:bold;">import</span> Task
&nbsp;
<span style="color: #808080; font-style: italic;"># watcher les js ou les css</span>
Task.<span style="color: black;">add</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'chemin/relatif/vers/fichier/a/surveiller.css'</span><span style="color: black;">&#41;</span>
Task.<span style="color: black;">add</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'chemin/relatif/vers/fichier/a/surveiller.js'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># watcher les images ou les templates</span>
Task.<span style="color: black;">add</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'chemin/relatif/vers/dossier/a/surveiller'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Et lancez la commande <code>livereload</code> <strong>en étant dans le même dossier que ce fichier</strong>. Notez que le serveur ne parse ce fichier que quand l&#8217;extension est activée et que vous avez visité la page au moins une fois.</p>
<p>On peut même demander d&#8217;effectuer des tâches avant le rechargement de la page. Cela peut être des tâches complètement arbitraires, mais des raccourcis existent pour les tâches les plus courantes, telle que minifier du JS ou compiler un pre-processeur CSS.</p>
<p>Par exemple, j&#8217;utilise cette fonctionnalité pour compiler mes fichiers LESS CSS à chaque modification.</p>
<p>Pour cela, il faut installer le compilateur LESS. Sous Ubuntu, ça se fait en deux coups de cuillère à pot :</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> npm
<span style="color: #c20cb9; font-weight: bold;">sudo</span> npm <span style="color: #c20cb9; font-weight: bold;">install</span> <span style="color: #660033;">-g</span> <span style="color: #c20cb9; font-weight: bold;">less</span></pre></div></div>

<p>Et dans le Guardfile, il faut ajouter un code du style :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> livereload.<span style="color: black;">task</span> <span style="color: #ff7700;font-weight:bold;">import</span> Task
<span style="color: #ff7700;font-weight:bold;">from</span> livereload.<span style="color: #dc143c;">compiler</span> <span style="color: #ff7700;font-weight:bold;">import</span> lessc
&nbsp;
Task.<span style="color: black;">add</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'../apps/core/static/less/boostrap/boostrap.less'</span>,
         lessc<span style="color: black;">&#40;</span><span style="color: #483d8b;">'../apps/core/static/less/boostrap/boostrap.less'</span>,
               <span style="color: #483d8b;">'../apps/core/static/css/boostrap.css'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Il y a un a tas d&#8217;options donc checkez la doc, mais aussi le code source car la doc n&#8217;est pas exhaustive.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7698&amp;md5=ed86fc2e901610edc857027027b71659" 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=7648
title: La stack techno qu’on utilise pour faire un site Web, et pourquoi
uri: La-stack-techno-qu-on-utilise-pour-faire-un-site-Web-et-pourquoi
url: http://sametmax.com/la-stack-techno-quon-utilise-pour-faire-un-site-web-et-pourquoi/
content:
<p>Une stack techno n&#8217;est pas une référence. Il n&#8217;y a pas de combo absolu qui rox absolument tout, c&#8217;est une question de contexte technique, financier, humain&#8230;</p>
<p>Mais c&#8217;est vrai que ça aide bien d&#8217;avoir sous les yeux les pratiques des autres.</p>
<p>Je ne vais pas expliquer pourquoi Python, <a href="http://sametmax.com/10-raisons-pour-lesquelles-je-suis-toujours-marie-a-python/">je l&#8217;ai déjà fait</a>.</p>
<p>Commençons plutôt par la partie purement Web, pour laquelle on utilise Django, le framework Web Python.</p>
<p>Max et moi avons tout deux fait du PHP avant, j&#8217;ai tâté des frameworks internes, du Symfony et plus tard du Zope. J&#8217;ai regardé du côté de Pyramid et de ses prédécesseurs, et Django est celui qui me plaît le plus. J&#8217;ai juste un peu forcé la main à Max :-)</p>
<p>Car oui, le framework a été avant tout un choix de goût.</p>
<p>Ce n&#8217;est pas un choix de performances : le framework n&#8217;a aucun impact dessus. Aucun. Les architectures ont un impact. Le framework, non. Votre bottleneck sera sur les IO, pas sur le CPU. Le choix de technos asynchrones peut avoir un impact, mais ce n&#8217;est pas une question de framework. Tornado, Twisted ou NodeJS, on s&#8217;en fout. </p>
<p>Donc Django, essentiellement parce qu&#8217;il me plait. Et il me plaît pour ces raisons :</p>
<ul>
<li>Il y a un bon équilibre entre découplage et intégration. En général c&#8217;est soit très découplé et mal intégré, soit très bien intégré et très couplé.</li>
<li>C&#8217;est bien foutu et bien documenté. Et c&#8217;est stable. Vraiment très stable. Les core devs sont hyper sérieux.</li>
<li>C&#8217;est très versatile et ça peut faire plein de trucs out of the box, petits comme gros.</li>
<li>C&#8217;est assez facile à apprendre. Ça reste un framework, donc ce n&#8217;est pas la plus simple des démarches, mais dans le royaume des frameworks de cette taille, ça reste vraiment le plus simple.</li>
<li>La communauté est fantastique : il y a des centaines d&#8217;apps qui couvrent pratiquement tous les besoins.</li>
<li>Et bien entendu, c&#8217;est en Python.</li>
</ul>
<p>En terme de base de données, on a fait du MySQL pendant longtemps. Ça a plutôt bien marché. Maintenant je commence mes nouveaux projets avec PostGres, qui est plus solide. Parfois je fais juste du Sqlite, parce que ça suffit.</p>
<p>Pas de NoSQL. Après plusieurs expériences avec MongoDB et CouchDB, je n&#8217;ai pas été convaincu que les bénéfices dépassaient le coût. Il faudrait un article complet là dessus (qu&#8217;on m&#8217;a d&#8217;ailleurs demandé).</p>
<p>Question OS. c&#8217;est du CentOS avec Max (il a plus l&#8217;habitude) ou du Ubuntu Server pour mes autres projets. Je reste sur les LTS. Ce n&#8217;est pas un choix très réfléchi, c&#8217;est surtout par habitude.</p>
<p>Pas de machine virtuelle. On a essayé, sans y trouver un grand intérêt :</p>
<ul>
<li>Il faut quand même faire des scripts de migration, donc autant s&#8217;en servir pour le déploiement.</li>
<li>On perd en perfs.</li>
<li>Les erreurs liées au mal-fonctionnement d&#8217;une VM sont absolument indébuggable.</li>
<li>Si on ne fait pas la VM soit-même, il faut mettre ses couilles dans les mains d&#8217;un pestataire de service. J&#8217;ai horreur de ça.</li>
<li>Trouver des gens avec la compétence pour gérer une VM, c&#8217;est difficile. Un script de déploiement, c&#8217;est du code que tout dev saura déjà lire. Par extension ça veut dire que je m&#8217;y replonge facilement des semaines plus tard.</li>
</ul>
<p>Et donc pour le déploiement, j&#8217;utilise <a href="http://sametmax.com/travailler-moins-pour-gagner-plus-en-15-minutes-avec-python-fabric/">fabric</a>, avec <a href="https://github.com/ronnix/fabtools/">fabtools</a>.</p>
<p>Ce n&#8217;est pas la solution la plus efficace, d&#8217;autant que ça limite à Python 2.7, mais c&#8217;est la plus simple. C&#8217;est juste du code Python. N&#8217;importe qui peut comprendre le déploiement en 15 minutes. Ça se modifie vite, s&#8217;adapte facilement. </p>
<p>Il faut comprendre qu&#8217;on a jamais plus d&#8217;une dizaine de serveurs pour un projet, ces choix sont donc fait en fonction de cela. Il va sans dire que si vous gérez un parc de centaines de machines, ça ne sera pas du tout le même choix technique. Peut être que Chef ou des VM seront alors carrément plus interressant. Peut être que le NoSQL et sa capacité au scalling sera bien plus rentable.</p>
<p>Il ne s&#8217;agit pas de décrier les technos que nous n&#8217;utilisons pas. Il s&#8217;agit juste de dire, voilà les choix que nous avons fait, dans tel contexte, pour telles (bonnes ou mauvaises) raisons.</p>
<p>Durant les dernières années, on a ajouté <a href="http://redis.io/">Redis</a> à notre stack. C&#8217;est un outil fantastique qui sert à tout : de la base de données pour les trucs simples (il y a des fois ou un schéma est overkill) à la solution de caching. C&#8217;est ce qu&#8217;on a de plus proche du NoSQL.</p>
<p>L&#8217;outil est tellement simple à installer (vraiment le degré zero de la maintenance, c&#8217;est beau) et à utiliser que ça ne vaut juste pas le coup de s&#8217;en priver. </p>
<p>Du coup, plus de memcache. Toutes les grosses requêtes sont sauvegardées dans Redis, dès qu&#8217;on fait un script qui a besoin de persistance temporaire, Redis, pour communiquer entre plusieurs process, Redis, pour toutes les opérations qui ont besoin de grosses perfs comme les stats, Redis. Vive Redis.</p>
<p>D&#8217;ailleurs on utilise Redis aussi comme broker pour notre gestionnaire de queues et de taches : <a href="sametmax.com/files-de-taches-et-taches-recurrentes-avec-celery/">celery</a>. Si vous pythonez, je vous recommande chaudement celery pour toutes les tâches en background, les crawlers, les chaînes de process, etc.</p>
<p>On a aussi du moteur de recherche. Là on tappe dans du <a href="http://lucene.apache.org/solr/">Solr</a> (avec <a href="http://haystacksearch.org/">haystack</a>). C&#8217;est très puissant, en tout cas syntaxiquement car ça ne fait pas de sémantique. Ne vous attendez-donc pas à rattraper Google. Mais c&#8217;est aussi méga chiant à configurer et très lourd. Je pense qu&#8217;un jour on va migrer sur <a href="http://www.elasticsearch.org/">ElasticSearch</a>, mais c&#8217;est pas la priorité. Don&#8217;t fix what ain&#8217;t broken.</p>
<p>Devant tout ça on a <a href="http://nginx.org/">Nginx</a>. Comme beaucoup on a fait Apache => Cherokee => lighttp => nginx. Et franchement, je ne reviendrais jamais en arrière : plus léger, plus rapide, plus facile à installer et à configurer, plus versatile. Nginx fait tout, et mieux. </p>
<p>En proxy on a du <a href="http://gunicorn.org/">gunicorn</a>. Parce qu&#8217;on avait la flemme de configurer uwsgi et qu&#8217;on a pris l&#8217;habitude.</p>
<p>Après on utilise plein de libs, de petits outils, etc. Mais ça c&#8217;est le gros de notre archi.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7648&amp;md5=a3c473ad94a4298f30d5296cdd292afc" 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=7645
title: Rooter son lecteur MP3 avec rockbox
uri: Rooter-son-lecteur-MP3-avec-rockbox
url: http://sametmax.com/rooter-son-lecteur-mp3-avec-rockbox/
content:
<p>J&#8217;ai acheté un <a href="http://www.sandisk.com/products/music-video-players/clip-plus-mp3-player/">Sansa Clip</a> car je cherchais un lecteur mp3 cheap, léger, avec pas mal de batterie et solide, ayant, comme Max, laissé tombé les smartphones.</p>
<p>Globalement j&#8217;en étais content : le joujou n&#8217;a pas besoin d&#8217;un imachin pour tourner, c&#8217;est reconnu comme clé USB. Ça lit les formats audio exotiques, ça ne pèse rien et il est déjà tombé 50 fois par terre sans broncher. Je n&#8217;ai par ailleurs toujours pas eu à le recharger.</p>
<p>Seulement un matin, en plein footing, monsieurs s&#8217;est mis à rebooter à chaque fois qu&#8217;il lisait une chanson de Katy Perry. Certains argueront qu&#8217;il a bon goût, mais personnellement j&#8217;aime l&#8217;avoir pour les pointes de vitesse moyennes, Dragon Force étant utilisé pour les sprints.</p>
<p>Bref, soft reset, hard reset, formatage de la mémoire, utilisation de SD, rien n&#8217;y fait.</p>
<p>Alors je me souviens de <a href="http://www.rockbox.org/">RockBox</a>, un OS libre pour lecteur mp3. Je me dis que pour le prix, je risque pas grand chose à le flasher, une vraie brique coûterait plus cher.</p>
<p>Je télécharge l&#8217;<a href="http://www.rockbox.org/download/">installeur automatique</a> (qui existe sous Win/Mac/Linux \o/), je branche le bousin en USB, et je root le lecteur en un clic.</p>
<p>Ah ! Je m&#8217;attendais à ce que ça foire moi&#8230; A devoir chercher un peu&#8230; Je sais pas, quelque chose !</p>
<p>Mais non, ça marche, c&#8217;est tout.</p>
<p>J&#8217;ai maintenant un dual boot avec l&#8217;ancien OS et Rockbox (qui se lance par défaut). Mon lecteur ne reboot plus pour rien, toutes les features d&#8217;origine sont prises en charge, avec en prime la lecture du son des vidéos (je podcast donc maintenant <a href="http://www.ted.com">TED</a>) et un son que je peux monter beaucoup plus fort.</p>
<p>Merveilleux.</p>
<p>Rien à redire.</p>
<p>Rien à ajouter.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7645&amp;md5=03004dca3065433e9e5efcd76105bc24" 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=7780
title: Postez votre espace de travail !
uri: Postez-votre-espace-de-travail
url: http://sametmax.com/postez-votre-bureau/
content:
<p>Oui je sais vous l&#8217;avez vu 3 milliards de fois sur les forums, c&#8217;est ringard, c&#8217;est pas un article constructif mais bon tout à l&#8217;heure j&#8217;ai pris mon bureau en photo et je me suis dis que ça pouvais être marrant de voir dans quelle porcherie travaille les lecteurs de ce blog :)<br />
D&#8217;ailleurs ça serait bien de justifier le choix de votre matos, pas juste une photo, pourquoi 8 écrans à fusion plasma ou un iCore32 à double arbre à cames, etc.</p>
<p>N&#8217;oubliez pas de vérifier les données <a href="http://www.verexif.com/en/">EXIF</a> de votre photo avant de poster des fois qu&#8217;il s&#8217;y trouve votre location géographique / taille d&#8217;anus / empreinte digitale fourni par aippeule et Cie ^^</p>
<p>Aller je me lance, Mongeois! Saint-Denis !</p>
<div id="attachment_7781" class="wp-caption aligncenter" style="width: 610px"><img src="media/0ec2ee70.home.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/11/home.jpg" alt="" title="" width="600" height="428" class="size-full wp-image-7781" /><p class="wp-caption-text">La téloche c&#039;est pour LoL...</p></div>
<p>- Un ptit Mac Book Air double coeur avec 2GB de RAM et SSD. Je l&#8217;ai pris car il est vraiment compact, pour les voyages c&#8217;est top, et puis pour l&#8217;OS, y a pas à chier cet OS est formidabuleux.<br />
- La téloche je viens de la piquer à l&#8217;hotel, résolution moyenne mais ça suffit pour les lignes de code ou y mettre les shells (et puis pour LoL que je viens de réinstaller, j&#8217;avoue&#8230;). Un peu grosse cependant je sais pas si je vais supporter.<br />
- Souris Raser pas mal mais un peu grosse avec tapis spécial pour douleur au poignet, jamais su si c&#8217;était l&#8217;abus de souris ou de branlette.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7780&amp;md5=abb4ceb52963602f63109832c3551d0a" 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=7791
title: map(), filter() et reduce () ?
uri: map()-filter-et-reduce-()
url: http://sametmax.com/map-filter-et-reduce/
content:
<p><code>map()</code>, <code>filter()</code> et <code>reduce()</code> sont des fonctions de traitement d&#8217;itérables typiques de la programmation fonctionnelle, qui <a href="http://www.artima.com/weblogs/viewpost.jsp?thread=98196">ont été marquées comme à retirer des builtins</a> pour Python 3. Finalement, seule <code>reduce()</code> sera déplacée dans le module <code>functools</code> pour Python 3.</p>
<p>Les opérations que font ces fonctions sont typiquement quelque chose que l&#8217;ont peut faire sans elles, et nous allons les passer en revue pour voir dans quels cas elles sont pertinentes, dans quel cas une alternative est meilleure. L&#8217;alternative étant, dans 90% des cas, une <a href="http://sametmax.com/python-love-les-listes-en-intention-partie/">liste en intention</a>.</p>
<h2>filter()</h2>
<p><code>filter()</code> prend une fonction en paramètre, souvent une <a href="http://sametmax.com/fonctions-anonymes-en-python-ou-lambda/">lambda</a>, comme ses deux soeurs puisqu&#8217;on est dans le paradigme fonctionnel. Elle doit renvoyer <code>True</code> si on garde un élément, et <code>False</code> sinon.</p>
<p>L&#8217;usage typique est celui-ci :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">ages = <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">30</span><span style="color: black;">&#41;</span>
majeurs = <span style="color: #008000;">filter</span><span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> x: x <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">18</span>, ages<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>majeurs<span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]</span></pre></div></div>

<p>Typiquement, ce code peut être remplacé par une liste en intention dans le pur style Python :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">majeurs = <span style="color: black;">&#91;</span>a <span style="color: #ff7700;font-weight:bold;">for</span> a <span style="color: #ff7700;font-weight:bold;">in</span> ages <span style="color: #ff7700;font-weight:bold;">if</span> a <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">18</span><span style="color: black;">&#93;</span></pre></div></div>

<p>Le code est plus court, et fait usage d&#8217;une des fonctionalités les plus importantes du langage. On peut en plus ajouter une transformation à <code>a</code> facilement si on le désire, au lieu de devoir coller un <code>map()</code> derrière.</p>
<p><code>filter()</code> est vraiment la moins utile des 3, et sera une question de style, surtout pour les nostalgiques de Lisp. Je répète souvent que quand on code avec un autre langage, on doit essayer de se tenir au style du nouveau et pas faire un mix avec ses anciennes habitudes. Quand je code en Java, je fais des getter et setter, même si j&#8217;ai horreur de ça.</p>
<p>Mon conseil: oubliez <code>filter()</code>.</p>
<h2>map()</h2>
<p>Si <code>filter()</code> est l&#8217;équivalent de la partie de droite d&#8217;une liste en intention, <code>map()</code> est l&#8217;équivalent de la partie de gauche. La fonction passée retourne un résultat qui permet de transformer la liste.</p>
<p>Typiquement :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">memes = <span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;It's over 9000 !&quot;</span>, <span style="color: #483d8b;">&quot;All your base are belong to us.&quot;</span><span style="color: black;">&#93;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #008000;">map</span><span style="color: black;">&#40;</span><span style="color: #008000;">unicode</span>.<span style="color: black;">upper</span>, memes<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Ce qui peut se traduire par :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>s.<span style="color: black;">upper</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> s <span style="color: #ff7700;font-weight:bold;">in</span> memes<span style="color: black;">&#41;</span></pre></div></div>

<p><code>map()</code> est un peu plus utile, dans le sens où sa syntaxe peut être plus concise dans certains cas, comme le casting de types. Par exemple si je reçois une heure sous forme de string :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">h, m, s = <span style="color: #008000;">map</span><span style="color: black;">&#40;</span><span style="color: #008000;">int</span>, <span style="color: #483d8b;">'8:19:22'</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">':'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>sera plus court et plus concis, et plus clair que :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">h, m, s = <span style="color: black;">&#40;</span><span style="color: #008000;">int</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #483d8b;">'8:19:22'</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">':'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Mais bon, la différence n&#8217;est pas non plus incroyable au point d&#8217;en faire une fonctionnalitéé clé. Je l&#8217;utilise de temps à autre par soucis de brièveté, mais vraiment c&#8217;est tout.</p>
<h2>reduce()</h2>
<p><code>reduce()</code> est plus tordu. La fonction doit prendre deux paramètres en entrée, et retourner une valeur. Au  premier appel, les deux premiers éléments de l&#8217;itérable sont passés en paramètres. Ensuite, le résultat de cet appel et l&#8217;élément suivant sont passés en paramètre, et ainsi de suite.</p>
<p>Vous n&#8217;avez rien pigé ? C&#8217;est normal. <code>reduce()</code> est parfaitement cryptique. Voici ce que ça donne en pratique :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> afficher<span style="color: black;">&#40;</span>a, b<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;Entrée :&quot;</span>, a, b<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;Sortie :&quot;</span>, a + b<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> a + b
&nbsp;
res = <span style="color: #008000;">reduce</span><span style="color: black;">&#40;</span>afficher, <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Résultat final&quot;</span>, res<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">## Entrée : 0 1</span>
<span style="color: #808080; font-style: italic;">## Sortie : 1</span>
<span style="color: #808080; font-style: italic;">## Entrée : 1 2</span>
<span style="color: #808080; font-style: italic;">## Sortie : 3</span>
<span style="color: #808080; font-style: italic;">## Entrée : 3 3</span>
<span style="color: #808080; font-style: italic;">## Sortie : 6</span>
<span style="color: #808080; font-style: italic;">## Entrée : 6 4</span>
<span style="color: #808080; font-style: italic;">## Sortie : 10</span>
<span style="color: #808080; font-style: italic;">## Entrée : 10 5</span>
<span style="color: #808080; font-style: italic;">## Sortie : 15</span>
<span style="color: #808080; font-style: italic;">## Entrée : 15 6</span>
<span style="color: #808080; font-style: italic;">## Sortie : 21</span>
<span style="color: #808080; font-style: italic;">## Entrée : 21 7</span>
<span style="color: #808080; font-style: italic;">## Sortie : 28</span>
<span style="color: #808080; font-style: italic;">## Entrée : 28 8</span>
<span style="color: #808080; font-style: italic;">## Sortie : 36</span>
<span style="color: #808080; font-style: italic;">## Entrée : 36 9</span>
<span style="color: #808080; font-style: italic;">## Sortie : 45</span>
<span style="color: #808080; font-style: italic;">## Résultat final 45</span></pre></div></div>

<p>Vous allez me dire, à quoi ça sert ? Et bien par exemple à appliquer des opérateurs commutatifs, ici nous l&#8217;avons fait avec <code>+</code>, nous avons fait la somme de tous les éléments retournés par <code>range(10)</code>. La preuve :</p>

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

<p>Il n&#8217;y a pas, en Python, de fonction équivalent à <code>sum()</code> pour la multiplication. Donc on ferait :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #008000;">reduce</span><span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> a, b: a <span style="color: #66cc66;">*</span> b, <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">11</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## 3628800</span></pre></div></div>

<p>Ce qui multiplie tous les éléments entre eux. Comme l&#8217;ordre dans lequel les éléments sont multipliés n&#8217;a pas d&#8217;important (d&#8217;où le &#8216;commutatif&#8217;), ça fonctionne.</p>
<p><code>reduce()</code> peut prendre un troisième paramètre, <code>initial</code>, qui sera la valeur passée en premier au premier appel de la fonction. Cela permet de travailler sur des calculs en cascade qui ne fonctionneraient sinon pas. Revenons à notre exemple de temps :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">temps = <span style="color: #008000;">map</span><span style="color: black;">&#40;</span><span style="color: #008000;">int</span>, <span style="color: #483d8b;">'8:19:22'</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">':'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #008000;">reduce</span><span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> a, b: a <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">60</span> + b, temps, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## 29962</span></pre></div></div>

<p>Ce qui peut se traduire par :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">h, m, s = <span style="color: #008000;">map</span><span style="color: black;">&#40;</span><span style="color: #008000;">int</span>, <span style="color: #483d8b;">'8:19:22'</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">':'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>h <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">3600</span> + m <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">60</span> + s<span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## 29962</span></pre></div></div>

<p>Bien sûr, cette conversion ne fonctionnerait pas si le calcul était sur un itérable plus long. Mais une version itérative est facile à faire :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">res = <span style="color: #ff4500;">0</span>
<span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">map</span><span style="color: black;">&#40;</span><span style="color: #008000;">int</span>, <span style="color: #483d8b;">'8:19:22'</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">':'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
    res = res <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">60</span> + i
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>res<span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## 29962</span></pre></div></div>

<p>Maintenant, autant les deux dernières versions sont faciles à comprendre, autant la première prend quelques secondes. Et c&#8217;est la raison pour laquelle <code>reduce()</code> a été retirée des builtins, pour encourager l&#8217;usage des alternatives. En effet, cette fonction donne toujours un résultat très peu lisible. Je cite et approuve Guido là dessus:</p>
<blockquote><p>C&#8217;est en fait celle que je déteste le plus, car, à part pour quelques exemples impliquant + ou *, presque chaque fois que je vois un appel à reduce() avec une fonction non-triviale passée en argument, j&#8217;ai besoin de prendre un crayon et un papier pour faire le diagramme de ce qui est effectivement entrée dans la fonction avant que je comprenne ce qu&#8217;est supposé faire reduce(). Donc à mes yeux, l&#8217;application de reduce() est plutôt limitée à des opérateurs associatifs, et <strong>dans d&#8217;autres cas il est mieux d&#8217;écrire une boucle d&#8217;accumulation explicitement.</strong>
</p></blockquote>
<p>Graissage maison.</p>
<p>Bref, <code>reduce()</code> est dur à lire, et une boucle ne l&#8217;est pas. Écrivez 3 lignes de plus, ça ne va pas vous tuer. Relire votre one-liner dans un mois par contre&#8230;</p>
<p>Cette fonction a été beaucoup utilisée avec les opérateurs <code>or</code> et <code>and</code> pour savoir si tous les éléments étaient vrais au moins un élément vrai dans une liste :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">tout_est_vrai = <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
certains_sont_vrais = <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
tout_est_faux = <span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Retourne True si tout est vrai</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #008000;">bool</span><span style="color: black;">&#40;</span><span style="color: #008000;">reduce</span><span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> a, b: a <span style="color: #ff7700;font-weight:bold;">and</span> b, tout_est_vrai<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## True</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #008000;">bool</span><span style="color: black;">&#40;</span><span style="color: #008000;">reduce</span><span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> a, b: a <span style="color: #ff7700;font-weight:bold;">and</span> b, certains_sont_vrais<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## False</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #008000;">bool</span><span style="color: black;">&#40;</span><span style="color: #008000;">reduce</span><span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> a, b: a <span style="color: #ff7700;font-weight:bold;">and</span> b, tout_est_faux<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## False</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Retourne True si au moins un élément est vrai</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #008000;">bool</span><span style="color: black;">&#40;</span><span style="color: #008000;">reduce</span><span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> a, b: a <span style="color: #ff7700;font-weight:bold;">or</span> b, tout_est_vrai<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## True</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #008000;">bool</span><span style="color: black;">&#40;</span><span style="color: #008000;">reduce</span><span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> a, b: a <span style="color: #ff7700;font-weight:bold;">or</span> b, certains_sont_vrais<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## True</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #008000;">bool</span><span style="color: black;">&#40;</span><span style="color: #008000;">reduce</span><span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> a, b: a <span style="color: #ff7700;font-weight:bold;">or</span> b, tout_est_faux<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## False</span></pre></div></div>

<p>Mais aujourd&#8217;hui, c&#8217;est parfaitement inutile puisque nous avons les fonctions built-in <strong>all()</strong> et <strong>any()</strong>, qui font ça en plus court et plus rapide :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># Retourne True si tout est vrai</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #008000;">all</span><span style="color: black;">&#40;</span>tout_est_vrai<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## True</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #008000;">all</span><span style="color: black;">&#40;</span>certains_sont_vrais<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## False</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #008000;">all</span><span style="color: black;">&#40;</span>tout_est_faux<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## False</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Retourne True si au moins un élément est vrai</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #008000;">any</span><span style="color: black;">&#40;</span>tout_est_vrai<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## True</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #008000;">any</span><span style="color: black;">&#40;</span>certains_sont_vrais<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## True</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #008000;">any</span><span style="color: black;">&#40;</span>tout_est_faux<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## False</span></pre></div></div>

<h2>Petite astuce finale</h2>
<p>Souvenez-vous également que les fonctions Python peuvent être déclarées n&#8217;importe où à la volée, même dans une autre fonction, une classe, une méthode, un context manager, etc. Or une fonction peut retourner un générateur grâce à <a href="http://sametmax.com/comment-utiliser-yield-et-les-generateurs-en-python/">yield</a>, ce qui vous permet de déclarer des gros bouts de logique, et de les plugger dans votre process itérative a posteriori :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> traitement_complexe<span style="color: black;">&#40;</span>iterable<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> iterable:
        <span style="color: #ff7700;font-weight:bold;">if</span> x <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">3</span>, <span style="color: #ff4500;">7</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">and</span> x <span style="color: #66cc66;">%</span> <span style="color: #ff4500;">2</span> <span style="color: #66cc66;">!</span>= <span style="color: #ff4500;">0</span>:
            <span style="color: #ff7700;font-weight:bold;">if</span> x + x <span style="color: #66cc66;">&lt;</span> <span style="color: #ff4500;">13</span> :
                <span style="color: #ff7700;font-weight:bold;">yield</span> x
            <span style="color: #ff7700;font-weight:bold;">else</span>: 
                <span style="color: #ff7700;font-weight:bold;">yield</span> x - <span style="color: #ff4500;">2</span>
&nbsp;
<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;">join</span><span style="color: black;">&#40;</span><span style="color: #008000;">map</span><span style="color: black;">&#40;</span><span style="color: #008000;">str</span>, traitement_complexe<span style="color: black;">&#40;</span><span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">20</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## 5-7-9-11-13-15-17</span></pre></div></div>

 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7791&amp;md5=61c33ea6021ce5d5e2d0eb4d269ccc78" 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=7954
title: Changer la timezone sous Ubuntu Server en ligne de commande
uri: Changer-la-timezone-sous-Ubuntu-Server-en-ligne-de-commande
url: http://sametmax.com/changer-la-timezone-sous-ubuntu-server-en-ligne-de-commande/
content:
<p>Avoir tous ses serveur à la même heure, c&#8217;est primordial. Et cette même heure devrait <a href="http://sametmax.com/les-time-zones-en-python/">toujours être UTC</a>.</p>
<p>Du coup dans votre script de déploiement, n&#8217;oubliez pas de changer la timezone de la machine.</p>
<p>Sous Ubuntu server, ça se fait en deux lignes :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;UTC&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">tee</span> <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>timezone
<span style="color: #c20cb9; font-weight: bold;">sudo</span> dpkg-reconfigure  <span style="color: #660033;">--frontend</span> noninteractive  tzdata</pre></div></div>

<p>Si vous avez des cron, redémarrez le daemon sinon il sera toujours décalé :</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 cron restart</pre></div></div>

<p>Si vous êtes du genre à aimer la précision, vous pouvez installer un daemon NTP qui permet de synchroniser l&#8217;horloge du serveur régulièrement avec un serveur distant :</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: #660033;">-y</span> <span style="color: #c20cb9; font-weight: bold;">install</span> ntp</pre></div></div>

 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7954&amp;md5=5233124b2b79eb104b08969a1448f361" 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=7964
title: Comment tailler une pipe
uri: Comment-tailler-une-pipe
url: http://sametmax.com/comment-tailler-une-pipe/
content:
<p>Sur ce blog, l&#8217;article qui a le plus cartonné n&#8217;a évidement absolument rien à avec Python : c&#8217;est le <a href="http://sametmax.com/un-peu-de-theorie-sur-la-masturbation-feminine-en-video/">tuto video sur la masturbation féminine</a> (même <a href="http://sametmax.com/sol-do-mi-sol-do-mi-sol-do-mi/">celui sur la sodomie</a> n&#8217;a pas fait mieux)</a>. En l’occurrence qui s&#8217;adresse aux mecs qui veulent prendre en main leur nana, mais qui je suis sûr a intéressé quelques femmes également. Pour la culture (du point) G.</p>
<p>Malgré l&#8217;abondance du matériel pornographique sur le sujet, je suis certain que de nombreuses femmes se demandent comment faire une fellation. En effet, on le souligne rarement, mais il y a autant de mauvais coups femmes que hommes, la différence majeure étant que la plupart des hommes se satisfont de relations sexuelles de piètre qualité (pour des raisons pathétiques, mais ce n&#8217;est pas le sujet de l&#8217;article).</p>
<p>Et dans le lot il y en a forcément qui se demandent comment changer cela. Après tout personne n&#8217;est né pour mettre la bite de quelqu&#8217;un dans sa bouche, c&#8217;est forcément une connaissance artificielle. Et puis on a un lectorat gay également, même si je doute qu&#8217;on puisse leur apprendre quoique ce soit. Pro-tip : si vous avez des amis LGB extravertis, demandez leurs des conseils, ils sont simplement meilleurs que vous au pieu.</p>
<p>Comme pour le cuni, il n&#8217;y a pas de méthode empaquetée, prête à être livrée, mais voici quelques points clés.</p>
<h2>Le teaser</h2>
<p>Je le répète souvent, le sexe est la dînette des adultes. C&#8217;est du théâtre. C&#8217;est pour le fun. Et la reproduction, mais bon, la turlute n&#8217;est pas indiquée pour ça.</p>
<p>La pipe n&#8217;échappe pas à cette règle, elle sera meilleur si vous jouez le jeu.</p>
<p>D&#8217;abord il y a <a href="http://sametmax.com/la-moitie-du-plaisir-dune-pipe/">le regard</a>. Un regard sûr(e) de soi (faites semblant), coquin ou carrément cochon. Un air qui dit qu&#8217;on en a envie.</p>
<p>Et il y a l&#8217;approche. Pas trop rapide, un peu joueur ou alors bestial, comme vous voulez, mais faites une mise en scène, c&#8217;est plus sympa.</p>
<p>Encore une fois, personne ne baise 5 étoiles tous les jours, ce sont juste des conseils.</p>
<h2>La prise en main</h2>
<p>Le gland est sensible au début, donc la main à la base du pénis. Vous pouvez y aller fermement, la base n&#8217;est pas sensible. Les doigts autour de la verge, la paume reposant, et poussant, sur la base. Un micro mouvement de va et vient en appuyant lentement, mais avec un peu de force vers le bas peut le faire.</p>
<p><strong>Évitez de remonter la main à plus de quelques centimètres du gland est le plus important au début.</strong></p>
<p>Mais comme pour le broute minou, il y a beaucoup de question de goût dans tout ce que je vais dire, donc souvenez-vous que ce sont des indications pour avoir de bonnes bases, pas des recettes miracles. J&#8217;ai rencontré un suisse qui me disait une fois qu&#8217;il adorait qu&#8217;on lui fasse des genres de brûlure indienne sur la tub. Je sais, j&#8217;ai des conversations bizarres. C&#8217;était près du lac du Loch Ness, alors la bizarrerie, vous savez&#8230;</p>
<p>Si vous savez masturber votre partenaire, vous pouvez alterner sans problème, et même pratiquer une masturbation particulièrement forte sur la fin. Mais attention, branler un mec correctement est généralement plus difficile que de le sucer. Pour vous entraîner, faites le en étant derrière lui d&#8217;abord, votre main sera dans le bon sens de la courbure donc se sera plus facile.</p>
<h2>La prise en bouche</h2>
<p>Je sais qu&#8217;on voit beaucoup de pornos où la meuf s&#8217;acharnent comme une malade sur le dard de son ou ses partenaires, mais bien que ça puisse être excitant à regarder, c&#8217;est rarement aussi agréable physiquement que quelqu&#8217;un qui y va à un rythme modéré au départ. </p>
<p>Bien entendu, comme souvent dans le cul, on accélère sur la fin, on y va plus fort, et on peu aussi commencer en mode bête sauvage dès le début, mais c&#8217;est contextuel. Pour la plupart des cas, doucement, puis on accélère.</p>
<p><strong>Le plus important est de ne pas sentir les dents et de bien lubrifier. </strong></p>
<p>Ça veut dire notamment saliver abondamment sur la bite. Abondamment. Crachez dessus si c&#8217;est trop sec. Si, si. Il faut que ça soit bien mouillé. </p>
<p>Et gardez votre air coquin, ça aide.</p>
<p>Pour les dents, c&#8217;est une question d’entraînement. Une copine bi m&#8217;a dit qu&#8217;avant sa première fois avec un mec, elle n&#8217;avait eu que des nanas, et était donc un peu perdu. Elle s&#8217;est finalement entraîné sur son pouce.</p>
<p>C&#8217;est un très bon conseil pour les dents et la salive. Pour le mouvement et autre, non. Mais il est très facile de voir si on sent ses dents sur son propre pouce, et assez simple de s’apercevoir si ça glisse tout seul ou si c&#8217;est un peu sec.</p>
<p>Vous avez déjà du entendre parler ou voir du deept throat ou du bukkake, des pratiques qui consiste essentiellement à traiter la bouche de la femme comme un vagin-auto-tamponneuse. Le plaisir qui en est retiré est purement psychologique et n&#8217;apporte aucun agrément physique. Il y a en fait peu d&#8217;hommes qui aiment ça, même si ils existent. Ce n&#8217;est pas parce que ça vous excite en vidéo que vous le voulez en vrai. Donc renseignez vous avant, et dans le doute, on vit très bien sans.</p>
<h2>Le finish</h2>
<p>Le finish est très important. Si vous êtes en train de faire quelque chose quand il vient, il aura bien plus de plaisir si vous ne vous arrêtez pas quand il jouit. Que ça soit branler ou sucer.</p>
<p>Maintenant il y a des tas de meufs qui n&#8217;ont pas envie de se prendre une giclée de sperme, ce que je comprends. Demandez au mec de prévenir dans ce cas avant qu&#8217;il vienne. Si vous ne dites rien&#8230;</p>
<p>La finition en bouche est très agréable, et bien entendu, personne ne vous oblige à avaler. Aller cracher juste après et vous laver les dents et tout à faire normal. Refuser catégoriquement aussi :-)</p>
<p>Sinon, venir sur les nichons n&#8217;apporte pas de sensation en plus, mais dans la tête ça turbine, et c&#8217;est un bon compromis.</p>
<p>Ne vous mettez pas non plus martèle en tête. Vous lui avez sucé la bite, si en plus il se plaint que la fin lui convient pas, mettez lui un god dans le cul, ça le calmera.</p>
<h2>Quelques exemples</h2>
<p>Bon, tout ça c&#8217;est très théorique, mais ça donne quoi en pratique ?</p>
<p>Voici deux styles un peu différents, et les deux sont de bons exemples :</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="510" height="400" src="http://xhamster.com/xembed.php?video=784989" frameborder="0" scrolling="no" class="iframe-class"></iframe>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe src="http://www.youjizz.com/videos/embed/2229839" frameborder="0" width="704" height="550" scrolling="no" allowtransparency="true" class="iframe-class"></iframe>
<p>Et voici un exemple qui peut être excitant en vidéo, mais qui, sauf quelques exceptions (contexte, personnes, alcoolémie, phases de la lune), rend vachement moins bien IRL :</p>
<p> <iframe width="510" height="400" src="http://www.sextvx.com/fr/embed/331780" frameborder="0" scrolling="no"></iframe></p>
<h2>Tips</h2>
<p>Il existe quelques moments particulièrement chouettes pour glisser une fellation. Il faut qu&#8217;elle vienne de vous dans ce cas là, mais ça fait toujours plaisir :</p>
<ul>
<li>Dans la voiture en conduisant.</li>
<li>Sûr le fauteuil pendant un film.</li>
<li>Sous le bureau pendant le travail.</li>
<li>Sous la douche.</li>
<li>Au réveil.</li>
</ul>
<p>L&#8217;idée est que ce soit spontané et imprévu. J&#8217;ai une copine une fois qui, juste avant de partir au boulot, au lieu de m&#8217;embrasser, m&#8217;a sucé en quelques secondes, puis est partie sans dire un mot. Je m&#8217;en souviens encore. </p>
<p>Notez que le problème de la pipe surprise (et même sans surprise), c&#8217;est que le mec peut avoir la bite sale. Or vous n&#8217;allez pas lui demander de se la laver avant, imagez qu&#8217;il fasse ça pour un cuni&#8230;</p>
<p>L&#8217;astuce, c&#8217;est d&#8217;avoir des lingettes pour bébé. Bien choisir sa marque pour que le goût soit pas dégueu, ça fait briller un braquemart en 5 secondes, remplaçant l&#8217;odeur de crevette faisandée par un doux fumet de what-ever-is-inside-the-stuff.</p>
<p>Une fois qu&#8217;il est venu, n&#8217;hésitez pas à le nettoyer avec un mouchoir ou un lingette. C&#8217;est très agréable.</p>
<p>Oh, et si vous avez envie d&#8217;un massage ou d&#8217;un léchage, demandez le avant la pipe, après c&#8217;est foutu :-)</p>
<p>Pour finir, un petit résumé :</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe src="http://flashservice.xvideos.com/embedframe/1356658" frameborder="0" width="510" height="400" scrolling="no" class="iframe-class"></iframe>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7964&amp;md5=bb0b6e4d2cdcb344f834b700c2ac6544" 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=7967
title: Quine en Python
uri: Quine-en-Python
url: http://sametmax.com/quine-en-python/
content:
<p>Une quine en informatique, c&#8217;est un programme qui, quand il est exécuté, affiche un code source qui permet d&#8217;obtenir le même résultat. La plupart des quines affichent leur propre code. Évidement, ouvrir le fichier de code et l&#8217;afficher ne compte pas comme une quine valide&#8230;</p>
<p>C&#8217;est un exercice beaucoup plus difficile qui n&#8217;en à l&#8217;air, même si normalement tout langage turing complet en est capable.</p>
<p>Techniquement, la quine la plus courte en Python est un fichier vide, ce qui est une quine valide. Mais comme ce n&#8217;est pas très fun, voici un exemple court avec des vrais caractères ASCII dedans:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">a=<span style="color: #483d8b;">'a=%s;print a%%`a`'</span><span style="color: #66cc66;">;</span>print a<span style="color: #66cc66;">%`</span>a<span style="color: #66cc66;">`</span></pre></div></div>

<p>Notez l&#8217;emploie de variables qui ne servent à rien d&#8217;autre que d&#8217;optenir une forme de symétrie.</p>
<p>Une autre version plus longue :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"> b=<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\\</span>'</span><span style="color: #66cc66;">;</span>g=<span style="color: #483d8b;">'&quot;'</span><span style="color: #66cc66;">;</span>p=<span style="color: #483d8b;">'%'</span><span style="color: #66cc66;">;</span>s=<span style="color: #483d8b;">&quot;b='%s%s';g='%s';p='%s';s=%s%s%s;print s%s(b,b,g,p,g,s,g,p)&quot;</span><span style="color: #66cc66;">;</span>print s<span style="color: #66cc66;">%</span><span style="color: black;">&#40;</span>b,b,g,p,g,s,g,p<span style="color: black;">&#41;</span></pre></div></div>

<p> Beaucoup de quines utilisent ce principe de créer une chaîne contenant une partie du programme et d&#8217;afficher et évaluer la chaîne en même temps. Parfois avec des boucles :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">x = <span style="color: black;">&#91;</span><span style="color: #483d8b;">'print &quot;x =&quot;, x'</span>, <span style="color: #483d8b;">'for m in x: print m'</span><span style="color: black;">&#93;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;x =&quot;</span>, x
<span style="color: #ff7700;font-weight:bold;">for</span> m <span style="color: #ff7700;font-weight:bold;">in</span> x: <span style="color: #ff7700;font-weight:bold;">print</span> m</pre></div></div>

<p>En Python, on peut évidement faire des variantes avec <code>sys.write</code>, <code>exec</code>, etc. Voici <a href="http://blog.amir.rachum.com/blog/2012/08/05/self-printing-programs-in-python/">un article</a> qui liste des snippets tordus et sympathiques pour y arriver.</p>
<p>Ça ne sert strictement à rien, mais c&#8217;est dimanche, personne ne va lire cet article de toute façon.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7967&amp;md5=ee81bcb3b383487f3dd600365e691c81" 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=7985
title: You are deprecated
uri: You-are-deprecated
url: http://sametmax.com/you-are-deprecated/
content:
<p style="text-align: center;"><em><small>Ceci est un post invité de <a href="http://sametmax.com/author/toniob/">Toniob</a> posté sous licence <a href="http://creativecommons.org/licenses/by/3.0/">creative common 3.0 unported</a>.</small></em></p>
<p>Oh oui, je sais ce que vous allez me dire, et vous avez parfaitement raison. Oui, il m&#8217;arrive d&#8217;être un peu obtus sur certaines choses, surtout quand il s&#8217;agit d&#8217;un domaine que je connais. Bref, aujourd&#8217;hui nous allons parler de ifconfig et de route.</p>
<p>Soyons clair tout de suite : arrêtez d&#8217;utiliser ces merdes, elles sont dépréciées depuis longtemps ! Je sais comment sont les informaticiens de manière générale, et les administrateurs systèmes en particulier. Il est difficile de changer leurs habitudes. Mais si on vous proposait Scarlett Johansson, vous resteriez fidèle à Régine ou Jonathan Rhys Meyers si vous aviez Mickey Rourke ? Je vois à vos yeux lubriques que vous m&#8217;avez saisi. Alors c&#8217;est parti.</p>
<div id="attachment_7987" class="wp-caption alignnone" style="width: 490px"><a href="http://sametmax.com/you-are-deprecated/ifconfig-deprecated/" rel="attachment wp-att-7987"><img src="media/6711f3c7.ifconfig-deprecated.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/11/ifconfig-deprecated.jpg" alt="" title="ifconfig-deprecated" width="480" height="288" class="size-full wp-image-7987" /></a><p class="wp-caption-text">- ifconfig ? - ouiiiii ** tum tum tum tum **</p></div>
<p><strong>Les interfaces</strong></p>
<p>Utilisez la commande ip, c&#8217;est un ordre. Elle remplacera avantageusement ifconfig. Dans la suite de ce billet, je mettrai des exemples de commandes avec ifconfig et leur équivalent avec ip. Commençons avec du simple, afficher la liste des interfaces disponibles :</p>
<p><code>
<pre># ifconfig -a
eth0      Link encap:Ethernet  HWaddr 00:90:f5:ee:62:31
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 lg file transmission:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
          Interruption:20 Mémoire:f7e00000-f7e20000

lo        Link encap:Boucle locale
          inet adr:127.0.0.1  Masque:255.0.0.0
          adr inet6: ::1/128 Scope:Hôte
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:12 errors:0 dropped:0 overruns:0 frame:0
          TX packets:12 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 lg file transmission:0
          RX bytes:720 (720.0 B)  TX bytes:720 (720.0 B)
$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 1000
    link/ether 00:90:f5:ee:62:31 brd ff:ff:ff:ff:ff:ff</pre>
<p></code></p>
<p>Vous voyez, pour le moment ce n&#8217;est pas si compliqué, vous économisez même de précieuses lettres. Vous constatez que la sortie est différente, mais vous y trouverez globalement les mêmes informations. C&#8217;est une question d&#8217;habitude. Personnellement, ça m&#8217;a pris un peu de temps, mais je ne reviendrais en arrière pour rien au monde.</p>
<p>On va maintenant assigner une adresse ip. Bon, j&#8217;avoue, c&#8217;est un peu plus long cette fois avec la commande ip :</p>
<p><code>
<pre># ifconfig eth0 192.168.1.1/24
# ip addr add 192.168.1.1/24 dev eth0</pre>
<p></code></p>
<p>Et si maintenant nous ajoutions une adresse ipv4 ? Sauf qu&#8217;avec ifconfig, ce n&#8217;est pas possible, on ne peut le faire qu&#8217;avec ip :</p>
<p><code>
<pre># ip addr add 192.168.1.2/32 dev eth0</pre>
<p></code></p>
<p>Si on affiche la configuration de l&#8217;interface réseau :</p>
<p><code>
<pre># ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 00:90:f5:ee:62:31
          inet adr:192.168.1.1  Bcast:0.0.0.0  Masque:255.255.255.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 lg file transmission:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
          Interruption:20 Mémoire:f7e00000-f7e20000
$ ip addr show eth0
2: eth0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc pfifo_fast state DOWN group default qlen 1000
    link/ether 00:90:f5:ee:62:31 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.1/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet 192.168.1.2/32 scope global eth0
       valid_lft forever preferred_lft forever</pre>
<p></code></p>
<p>Et oui, rien du côté de ifconfig. Il ne voit pas que l&#8217;interface dispose de deux adresses différentes. Alors qu&#8217;il fallait utiliser des alias d&#8217;interface avec ifconfig, plus de souci de ce côté là avec ip. Voici maintenant quelques exemples d&#8217;autres commandes pouvant être utiles :</p>
<p><code>
<pre># ifconfig eth0 mtu 9000
# ip link set eth0 mtu 9000</pre>
<p></code></p>
<p><code>
<pre># ifconfig eth0 up
# ip link set eth0 up</pre>
<p></code></p>
<p><strong>Les routes</strong></p>
<p>Passons maintenant aux routes. Si vous utilisez ifconfig, vous vous servez aussi probablement de route. C&#8217;est fini les conneries maintenant ! Commençons par les afficher :</p>
<p><code>
<pre># route -n
Table de routage IP du noyau
Destination     Passerelle      Genmask         Indic Metric Ref    Use Iface
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0
$ ip route
192.168.1.0/24 dev eth0  proto kernel  scope link  src 192.168.1.1</pre>
<p></code></p>
<p>Oui, la sortie est moins verbeuse par défaut. Ça devrait vous plaire pour vos scripts shell. Ajoutons maintenant une route par défaut :</p>
<p><code>
<pre># route add default gw 192.168.1.254
# ip route add defaut via 192.168.1.254</pre>
<p></code></p>
<p>Et si on regarde le résultat de la commande ip route maintenant :</p>
<p><code>
<pre>$ ip route
default via 192.168.1.254 dev eth0
192.168.1.0/24 dev eth0  proto kernel  scope link  src 192.168.1.1</pre>
<p></code></p>
<p>Contrairement à route, ip route génère une sortie qui peut être copiée / collée dans un ip route add. Pratique pour dupliquer une conf sur un autre serveur. Pour ajouter une route vers un hôte ou un réseau en particulier :</p>
<p><code>
<pre># route add -net 192.168.2.0 netmask 255.255.255.0 gw 192.168.1.253
# ip route add 192.168.2.0/24 via 192.168.1.253</pre>
<p></code></p>
<p>C&#8217;est une affaire de goût, mais je préfère largement la syntaxe de ip à celle de route.</p>
<p><strong>Conclusion</strong></p>
<p>Voilà cette petite introduction à la commande ip est terminée. Essayez de remplacer ifconfig dans vos usages au quotidien. Ça prend un peu de temps pour s&#8217;y faire, mais la syntaxe plus claire et les fonctionnalités disponibles permettent vite d&#8217;être plus rapide dans la configuration réseau d&#8217;une machine. Les exemples que j&#8217;ai donnés dans cet article devraient être suffisants pour 90% des usages. Si vous cherchez à vouloir en faire plus, il suffit d&#8217;ajouter l&#8217;option help à votre ligne de commande pour avoir des informations. Plus pratique que d&#8217;avoir à taper dans le man sans arrêt.</p>
<p>Si cet article vous plaît (merci de me faire des commentaires élogieux, c&#8217;est mon premier ici), j&#8217;essaierai de vous faire découvrir un peu plus la stack réseau sous Linux. Si les vlans sont connus, les bondings un peu moins, je pense que les macvtaps sont un mystère pour la plupart d&#8217;entre vous. Et tout se fait avec l&#8217;aide d&#8217;ip en plus, que demande le peuple ?</p>
<p>Et si la conf réseau ça vous saoule, je trouverai à m&#8217;énerver sur d&#8217;autres choses (le larousse n&#8217;a qu&#8217;à bien se tenir).</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7985&amp;md5=7688f2e615a39a55e2be8fb8328f7629" 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=8013
title: Marre des mots de passe pour push sur git ?
uri: Marre-des-mots-de-passe-pour-push-sur-git
url: http://sametmax.com/marre-des-mots-de-passe-pour-push-sur-git/
content:
<p>Vous êtes dans une situation où vous ne pouvez pas utiliser uniquement une clé pour vous authentifier, et il faut taper votre putain de mot de passe à chaque push.</p>
<p><a href="http://sametmax.com/git-push-via-http-ou-comment-travailler-au-macdo/">Ça sent le vécu n&#8217;est-ce pas ?</a></p>
<p>Mais bien entendu git vient avec une option bien cachée au fond de son fion pour adresser ce problème :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">git</span> config credential.helper <span style="color: #ff0000;">'cache --timeout=3600'</span></pre></div></div>

<p>Et votre authentification sera gardée en mémoire pour une heure. Vous pouvez faire :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">git</span> config <span style="color: #660033;">--global</span> credential.helper <span style="color: #ff0000;">'cache --timeout=3600'</span></pre></div></div>

<p>Pour l&#8217;étendre à tous les repos de votre machine.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8013&amp;md5=e4c62cc7ed21334f85fbfed045830fc7" 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=7981
title: Créer un super utilisateur Django sans prompt
uri: Créer-un-super-utilisateur-Django-sans-prompt
url: http://sametmax.com/creer-un-super-utilisateur-django-sans-prompt/
content:
<p>Automatiser le déploiement d&#8217;un projet Django passe par un <code>syncdb</code> sans prompt, et donc pas de création de superutilisateur :</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 syncdb <span style="color: #660033;">--noinput</span></pre></div></div>

<p>Vous pouvez bien entendu toujours en créer un plus tard, avec :</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 createsuperuser <span style="color: #660033;">--username</span>=vous <span style="color: #660033;">--email</span>=votre_mail</pre></div></div>

<p>Mais il va vous prompter pour saisir le mot de passe ou alors mettre un mot de passe inutilisable automatiquement, ça ne résout pas votre problème. Une astuce consiste à le créer avec un code Python et à piper ce code dans un shell :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;from django.contrib.auth.models import User; User.objects.filter(username='vous').count() or User.objects.create_superuser('vous', votre_email', 'mot_de_passe')&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> .<span style="color: #000000; font-weight: bold;">/</span>manage.py shell</pre></div></div>

<p>Personnellement je colle ça dans une tache <a href="http://sametmax.com/travailler-moins-pour-gagner-plus-en-15-minutes-avec-python-fabric/">fabric</a>. Parfois on peut même générer le mot de passe aléatoirement avec un <a href="http://sametmax.com/quest-ce-quun-uuid-et-a-quoi-ca-sert/">uuid</a> qui est printé localement.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7981&amp;md5=5968a2cf4dce21ecfb87305b3e6e8fbd" 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=7745
title: Floodsport…
uri: Floodsport
url: http://sametmax.com/floodsport/
content:
<p style="text-align: center;"><em><small>Ceci est un post invité de <a href="http://sametmax.com/author/01ivier/">01ivier</a> posté sous licence <a href="http://creativecommons.org/licenses/by/3.0/">creative common 3.0 unported</a>.</small></em></p>
<p>L&#8217;un des premiers &#8220;vrais&#8221; scripts  que j&#8217;ai écrit en Python avait pour fonction de <a href="http://fr.wiktionary.org/wiki/flooder">flooder</a> une boite mail&#8230;</p>
<p>Pas très sympathique à première vue, mais c&#8217;est sans compter le fait que j&#8217;ai pris ma carte au club des gentils depuis plusieurs années&#8230;</p>
<p>Je floode donc dans la joie et la bonne humeur.</p>
<p>Tout d&#8217;abord, il m&#8217;a fallu identifier un moyen pas trop compliqué d&#8217;envoyer un mail.<br />
J&#8217;ai donc récupéré un bout de code je ne sais où et j&#8217;ai viré tout ce qui dépassait :</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;">import</span> <span style="color: #dc143c;">smtplib</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">email</span>.<span style="color: black;">MIMEText</span> <span style="color: #ff7700;font-weight:bold;">import</span> MIMEText
&nbsp;
de_qui = <span style="color: #483d8b;">'ton@adresse.mail'</span>
a_qui = <span style="color: #483d8b;">'son@adresse.mail'</span> 
ton_server_smtp = <span style="color: #483d8b;">'smtp.ton.FAI'</span>
&nbsp;
message = MIMEText<span style="color: black;">&#40;</span><span style="color: #483d8b;">'Ceci est le corps du mail'</span><span style="color: black;">&#41;</span>      
message<span style="color: black;">&#91;</span><span style="color: #483d8b;">'Subject'</span><span style="color: black;">&#93;</span> = <span style="color: #483d8b;">'Ceci est le titre du mail'</span>                  
&nbsp;
server = <span style="color: #dc143c;">smtplib</span>.<span style="color: black;">SMTP</span><span style="color: black;">&#40;</span>ton_server_smtp<span style="color: black;">&#41;</span>                 
server.<span style="color: black;">sendmail</span><span style="color: black;">&#40;</span>de_qui, a_qui, message.<span style="color: black;">as_string</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>   
server.<span style="color: black;">quit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Le message a été envoyé avec un succès phénoménal !&quot;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>On reconnaît tout de suite le style qui caractérise les champions: pas de fonction, tout en ligne droite !<br />
J&#8217;aimerai pouvoir vous dire ce qu&#8217;est MIMEText, mais ayant pu me débrouiller jusqu&#8217;ici sans le savoir&#8230; et bien je ne le sais pas. (Et ne comptez pas sur moi pour aller le chercher juste pour vous. J&#8217;ai une posture de mauvais élève à assumer.) </p>
<p>À ce niveau, sur ma Linux Mint, il me suffit de renseigner <em>de_qui</em>, <em>a_qui</em> et <em>ton_server_smtp</em> puis d&#8217;ouvrir un terminal là où se trouve mon script et de taper :</p>

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

<p>(Oui, j&#8217;appelle souvent mes fichiers go.py. Comme ça j&#8217;ai l&#8217;impression qu&#8217;ils vont partir plus vite. Essayez, vous verrez. On y croit vraiment. Il faut juste s&#8217;habituer à appuyer un peu plus fort que d&#8217;habitude sur &#8220;entrer&#8221; tout en hurlant &#8220;GO !&#8221;. Mais l&#8217;effet est garanti.)</p>
<p>Si le message a bien &#8220;été envoyé avec un succès phénoménal&#8221; alors, quelque part dans l&#8217;univers, une boite mail a reçu un petit courrier ayant pour titre &#8220;Ceci est le titre du mail&#8221; et pour contenu &#8220;Ceci est le corps du mail&#8221;.<br />
Je vous assure que je ne suis jamais aussi heureux de m&#8217;envoyer un mail que de cette façon.<br />
Parfois je change l&#8217;objet pour me faire une surprise et je suis content.<br />
Ça marche à chaque fois.</p>
<h2>C&#8217;est à ce moment que l&#8217;on parle de petits chiens.</h2>
<p>Maintenant que je savais envoyer un mail, il me fallait trouver un moyen de convertir la photo d&#8217;un petit chien en ASCII-art (rapport à la joie et la bonne humeur du flood, souvenez-vous).<br />
J&#8217;ai trouvé mon bonheur avec le <a href="http://aa-project.sourceforge.net/">projet AA</a>.</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> python-aalib</pre></div></div>

<p>Paf !</p>
<p>J&#8217;ai récupéré <a href="http://jwilk.net/software/python-aalib">ici</a> un bout de code dont j&#8217;ai compris juste l&#8217;essentiel (où changer l&#8217;image, la largeur et la hauteur) et mon style tout en finesse a fait le reste :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> aalib
<span style="color: #ff7700;font-weight:bold;">import</span> Image
&nbsp;
pix = <span style="color: #483d8b;">'toutou.jpg'</span>
nb_lettre_largeur = <span style="color: #ff4500;">80</span>
nb_lettre_hauteur = <span style="color: #ff4500;">40</span>
&nbsp;
screen = aalib.<span style="color: black;">AsciiScreen</span><span style="color: black;">&#40;</span>width = nb_lettre_largeur, height = nb_lettre_hauteur<span style="color: black;">&#41;</span>
image = Image.<span style="color: #008000;">open</span><span style="color: black;">&#40;</span>pix<span style="color: black;">&#41;</span>.<span style="color: black;">convert</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'L'</span><span style="color: black;">&#41;</span>.<span style="color: black;">resize</span><span style="color: black;">&#40;</span>screen.<span style="color: black;">virtual_size</span><span style="color: black;">&#41;</span>
screen.<span style="color: black;">put_image</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>, image<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: black;">&#40;</span>screen.<span style="color: black;">render</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>&#8220;GO ! GO !&#8221;</p>

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

<p><a href="http://sametmax.com/floodsport/pitichien/" rel="attachment wp-att-7801"><img src="media/48ac4693.pitichien.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/11/pitichien.jpg" alt="" title="pitichien" width="600" height="439" class="alignnone size-full wp-image-7801" /></a></p>
<p>Ici aussi, une joie authentique est au rendez vous à chaque tentative.<br />
C&#8217;est merveilleux.</p>
<h2>Où l&#8217;on mélange les torchons et les torchons&#8230;</h2>
<p>Je savais comment envoyer un mail.<br />
Je savais comment convertir une photo de petit chien en ASCII.</p>
<p>La suite découlait de source.<br />
Il me fallait désormais unifier le tout pour pouvoir envoyer des dizaines de mails à la même adresse de manière à ce que la photo du petit chien apparaissent dans le client de messagerie de mon destinataire grâce à l&#8217;empilement des titres des messages en partant du principe qu&#8217;il utiliserai une police à chasse fixe pour l&#8217;affichage.<br />
Tout ce qu&#8217;il y a de plus classique.</p>
<p>À l&#8217;époque, sur gMail, le thème &#8220;Terminal&#8221; proposait une police monospaced verte sur fond noir du plus bel effet.<br />
Mais ce n&#8217;est plus le cas.<br />
Heureusement, en plagiant l&#8217;interface de gMail, Yahoo a aussi plagié le thème &#8220;Terminal&#8221; avec la police qui nous intéresse.<br />
Voici donc le petit chien que je me suis envoyé sur un compte créé pour l&#8217;occasion.</p>
<p><a href="http://sametmax.com/floodsport/tootooyahoo/" rel="attachment wp-att-7876"><img src="media/bc6201fb.tootooyahoo.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/11/tootooyahoo.jpg" alt="Tootoo for yahoo" title="tootooyahoo" width="600" height="448" class="alignnone size-full wp-image-7876" /></a></p>
<p>Ne me dites pas que ça ne vous donne pas envie de chialer.</p>
<p>Voici le script auquel j&#8217;ai (empiriquement) fini par arriver pour obtenir ce résultat émouvant :</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: #808080; font-style: italic;"># la lib smtp qui nous permet de dialoguer avec un serveur de mail</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">smtplib</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># pour simuler une irrégularité dans l'envoi</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">time</span> <span style="color: #ff7700;font-weight:bold;">import</span> sleep
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">random</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">random</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># nécessaire pour l'ASCII-Art</span>
<span style="color: #ff7700;font-weight:bold;">import</span> aalib
<span style="color: #ff7700;font-weight:bold;">import</span> Image
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">email</span>.<span style="color: black;">MIMEText</span> <span style="color: #ff7700;font-weight:bold;">import</span> MIMEText
&nbsp;
de_qui = <span style="color: #483d8b;">'À RENSEIGNER'</span>        
a_qui = <span style="color: #483d8b;">'À RENSEIGNER'</span>         
serveur_smtp = <span style="color: #483d8b;">'À RENSEIGNER'</span>  
&nbsp;
&nbsp;
i = j = <span style="color: #ff4500;">25</span>  <span style="color: #808080; font-style: italic;"># nombre de mail a envoyer donc de ligne,</span>
nb = <span style="color: #ff4500;">81</span>     <span style="color: #808080; font-style: italic;"># nombre de caractères par ligne, correspond au nombre de caractères</span>
            <span style="color: #808080; font-style: italic;"># affichés par Yahoo pour un titre avec le skin &quot;terminal&quot;  </span>
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;">###############</span>
<span style="color: #808080; font-style: italic;">## FONCTIONS ##</span>
<span style="color: #808080; font-style: italic;">###############</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> gotoascii<span style="color: black;">&#40;</span>pix<span style="color: black;">&#41;</span>:    
&nbsp;
    screen = aalib.<span style="color: black;">AsciiScreen</span><span style="color: black;">&#40;</span>width = nb-<span style="color: #ff4500;">1</span>, height = j<span style="color: black;">&#41;</span>
    image = Image.<span style="color: #008000;">open</span><span style="color: black;">&#40;</span>pix<span style="color: black;">&#41;</span>.<span style="color: black;">convert</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'L'</span><span style="color: black;">&#41;</span>.<span style="color: black;">resize</span><span style="color: black;">&#40;</span>screen.<span style="color: black;">virtual_size</span><span style="color: black;">&#41;</span>
    screen.<span style="color: black;">put_image</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>, image<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># les replace() concernent des caractères qui sont gérés différemment </span>
    <span style="color: #808080; font-style: italic;"># des autres quand ils sont utilisés dans le tite d'un mail.</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#40;</span>screen.<span style="color: black;">render</span><span style="color: black;">&#40;</span><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: 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: 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: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> essai<span style="color: black;">&#40;</span>pix<span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;"># permet éventuellement de tester le rendu de l'image avant de l'envoyer</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: black;">&#40;</span>gotoascii<span style="color: black;">&#40;</span>pix<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> ligne<span style="color: black;">&#40;</span>num_l, pix<span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;"># Comme il y a 'nb' élément par ligne, on compte de 'nb' en 'nb'</span>
    <span style="color: #808080; font-style: italic;"># en fonction du numéro de la ligne renseigné par 'num_l' </span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#40;</span>gotoascii<span style="color: black;">&#40;</span>pix<span style="color: black;">&#41;</span><span style="color: black;">&#91;</span>nb<span style="color: #66cc66;">*</span>num_l:nb<span style="color: #66cc66;">*</span><span style="color: black;">&#40;</span>num_l+<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> send<span style="color: black;">&#40;</span>num, pix<span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #dc143c;">email</span> = MIMEText<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Qu'est-ce qu'on s'amuse !&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># L'objet du mail est la ligne donnée en premier argument</span>
    <span style="color: #808080; font-style: italic;"># de l'image ASCII donnée en deuxième argument</span>
    <span style="color: #dc143c;">email</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'Subject'</span><span style="color: black;">&#93;</span> = ligne<span style="color: black;">&#40;</span>num, pix<span style="color: black;">&#41;</span>
&nbsp;
    server = <span style="color: #dc143c;">smtplib</span>.<span style="color: black;">SMTP</span><span style="color: black;">&#40;</span>serveur_smtp<span style="color: black;">&#41;</span>                 
    server.<span style="color: black;">sendmail</span><span style="color: black;">&#40;</span>de_qui, a_qui, <span style="color: #dc143c;">email</span>.<span style="color: black;">as_string</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>   
    server.<span style="color: black;">quit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>                                       
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;">#########################</span>
<span style="color: #808080; font-style: italic;">## PROGRAMME PRINCIPAL ##</span>
<span style="color: #808080; font-style: italic;">#########################</span>
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;"># Écoute le flag -test pour faire... des tests</span>
<span style="color: #808080; font-style: italic;"># --&gt; python go.py -test monImage.jpg</span>
<span style="color: #ff7700;font-weight:bold;">if</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;-test&quot;</span>: 
&nbsp;
    essai<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>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">else</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">while</span> i <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">0</span>:
&nbsp;
        <span style="color: #808080; font-style: italic;"># Augmente le délais et brise la régularité des envois de mail</span>
        <span style="color: #808080; font-style: italic;"># afin d'éviter, peut-être, d'être black-listé par Yahoo :-p</span>
        <span style="color: #808080; font-style: italic;"># Utilité purement hypothétique.</span>
        sleep<span style="color: black;">&#40;</span><span style="color: #ff4500;">20</span><span style="color: #66cc66;">*</span><span style="color: #dc143c;">random</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>+<span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Envoi le mail          </span>
        send<span style="color: black;">&#40;</span>i-<span style="color: #ff4500;">1</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>                 
        <span style="color: #ff7700;font-weight:bold;">if</span> i == <span style="color: #ff4500;">1</span>:
            <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Mail n°{0} envoyé. Il n'en reste plus.&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>j+<span style="color: #ff4500;">1</span>-i<span style="color: black;">&#41;</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;Mail n°{0} envoyé. Il en reste encore {1}.&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>j+<span style="color: #ff4500;">1</span>-i, i-<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        i -= <span style="color: #ff4500;">1</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Bravo ! Cet envoi a été un succès !&quot;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Pour l&#8217;utiliser, j&#8217;ai fait en sorte de pouvoir passer l&#8217;image à envoyer en argument.</p>

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

<p>J&#8217;ai écrit ce script il y a un peu plus de 2 ans, et, même si <a href="http://sametmax.com/apprendre-le-python-en-10-ans/">je progresse lentement</a>, je me rends bien compte désormais, que je recalcule l&#8217;image à chaque mail .<br />
Mais je vous l&#8217;ai laissé en l&#8217;état, car c&#8217;est tout aussi attendrissant qu&#8217;un chiot, je trouve.<br />
Surtout qu&#8217;à part ça, le reste frôle la perfection (la gestion des arguments doit en laisser plus d&#8217;un rêveur, j&#8217;imagine).</p>
<p>Enfin, grâce à Sam &#038; Max, j&#8217;ai découvert qu&#8217;il était possible d&#8217;utiliser d&#8217;autres photos que celle du petit chien.<br />
Merci à eux.</p>
<p><a href="http://sametmax.com/floodsport/bubuste/" rel="attachment wp-att-7914"><img src="media/131c16ed.bubuste.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/11/bubuste.jpg" alt="" title="bubuste" width="600" height="434" class="alignnone size-full wp-image-7914" /></a></p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7745&amp;md5=669d67de1c99bad591297792c5dc5a6b" 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=7761
title: Compter les doublons avec l’ORM Django
uri: Compter-les-doublons-avec-l-ORM-Django
url: http://sametmax.com/compter-les-doublons-avec-lorm-django/
content:
<p><code>GROUP BY </code>et <code>HAVING</code> sont assez peu intuitifs en SQL, et encore moins avec l&#8217;ORM Django.</p>
<p>Voici donc la recette pour compter le nombre d’occurrences des valeurs d&#8217;un champ, pour par exemple trouver les doublons.</p>
<p>En supposant une table <code>Massage</code> avec une valeur <code>finish</code> :</p>
<pre>
ID         FINISH
1          manuel
2          oral
3          oral
4          oral
</pre>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> Massage.<span style="color: black;">objects</span>.<span style="color: black;">values</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'finish'</span><span style="color: black;">&#41;</span>.<span style="color: black;">annotate</span><span style="color: black;">&#40;</span>count=Count<span style="color: black;">&#40;</span><span style="color: #483d8b;">'id'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#123;</span><span style="color: #483d8b;">'manuel'</span>: <span style="color: #ff4500;">2</span>, <span style="color: #483d8b;">'oral'</span>: <span style="color: #483d8b;">'9'</span>: <span style="color: #483d8b;">'rectal'</span>: <span style="color: #ff4500;">1</span>, <span style="color: #483d8b;">'paradoxal'</span>: -<span style="color: #ff4500;">1</span><span style="color: black;">&#125;</span></pre></div></div>

<p>Pour obtenir uniquement les doublons, il suffit de filtrer pour avoir les valeurs qui ont un <code>count</code> plus grand que 1 :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">Massage.<span style="color: black;">objects</span>.<span style="color: black;">values</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'finish'</span><span style="color: black;">&#41;</span>.<span style="color: black;">annotate</span><span style="color: black;">&#40;</span>count=Count<span style="color: black;">&#40;</span><span style="color: #483d8b;">'id'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>.<span style="color: #008000;">filter</span><span style="color: black;">&#40;</span>count__gt=<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span></pre></div></div>

 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7761&amp;md5=70ebd178c4abc22f9fe60ba0f38b5e38" 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=7613
title: Paramètres imbriqués dans une fonction Python
uri: Paramètres-imbriqués-dans-une-fonction-Python
url: http://sametmax.com/parametres-imbriques-dans-une-fonction-python/
content:
<p>Une fonction très peu connue de Python est la possibilité de définir un paramètre en indiquant qu&#8217;il s&#8217;agit d&#8217;une séquence. Python va automatiquement appliquer l&#8217;<a href="http://sametmax.com/operateur-splat-ou-etoile-en-python/">unpacking</a> dessus :</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> message_geolocalise<span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #008000;">long</span>, lat<span style="color: black;">&#41;</span>, message<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'%s'</span> <span style="color: #66cc66;">%</span> message
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Longitude : %s'</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">long</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Latitude : %s'</span> <span style="color: #66cc66;">%</span> lat
...     
<span style="color: #66cc66;">&gt;&gt;&gt;</span> point = <span style="color: black;">&#40;</span><span style="color: #ff4500;">4.344</span>, <span style="color: #ff4500;">2.44</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> message = <span style="color: #483d8b;">&quot;glittering prizes&quot;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> message_geolocalise<span style="color: black;">&#40;</span>point, message<span style="color: black;">&#41;</span>
glittering prizes
Longitude : <span style="color: #ff4500;">4.344</span>
Latitude : <span style="color: #ff4500;">2.44</span></pre></div></div>

<p>Cette fonctionnalité a été <a href="http://www.python.org/dev/peps/pep-3113/">retirée</a> en Python 3, jugée rarement utilisée, et surtout facilement remplaçable par un unpacking explicite :</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> message_geolocalise<span style="color: black;">&#40;</span>coord, message<span style="color: black;">&#41;</span>:
    <span style="color: #008000;">long</span>, lat = coord
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'%s'</span> <span style="color: #66cc66;">%</span> message
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Longitude : %s'</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">long</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Latitude : %s'</span> <span style="color: #66cc66;">%</span> lat</pre></div></div>

<p>En effet, en Python on peut utiliser de l&#8217;unpacking imbriqué :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">a, <span style="color: black;">&#40;</span>b, c<span style="color: black;">&#41;</span> = <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span><span style="color: black;">&#93;</span></pre></div></div>

<p>Et cela a été abusé en le mélangeant la syntaxe des paramètres imbriqués, qui rend le truc franchement illisible.</p>
<p>Voilà, c&#8217;était le post &#8220;vous aviez un poney que vous ne saviez pas et maintenant que vous le savez vous l&#8217;avez plus&#8221;.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7613&amp;md5=e5d0ed3069ebdb46f5eadb0499c77224" 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=8045
title: Quitter son pays
uri: Quitter-son-pays
url: http://sametmax.com/quitter-son-pays/
content:
<p style="text-align: center;"><em><small>Ceci est un post invité de <a href="http://sametmax.com/author/Erik/">Erik</a> posté sous licence <a href="http://creativecommons.org/licenses/by/3.0/">creative common 3.0 unported</a>.</small></em></p>
<p>A l&#8217;occasion d&#8217;un <a href="http://sametmax.com/parlez-nous-de-vous/">article récent</a> où Sam &#038; Max nous invitaient à leur parler de nous, Max m&#8217;a proposé de me fendre d&#8217;un article sur mon départ de France. Voici donc une rétrospective sur un aspect de ma vie. Cet article est long et je traite dans la 1ère moitié de mon parcours, puis de mes observations.</p>
<h3>Mon parcours</h3>
<p>En 2003, je termine mes études d&#8217;ingénieur en traitement du signal &#038; télécoms, mais en statut d&#8217;auditeur libre. Ce qui signifie que malgré mes 11,68/20 de moyenne, mon implication dans des cours du soir pour prouver ma bonne foi (modules de communication et de management au CNAM), et des lettres de soutient d&#8217;un prof du CNAM et de 2 anciens maitres de stage, on ne me donne pas de diplôme. A l&#8217;époque, le directeur de mon école d&#8217;ingénieurs nous annonce qu&#8217;il faut nous préparer à une durée moyenne de chomage de 7 mois. Sachant que certains sont embauchés immédiatement sur leur lieu de stage final, les statistiques ne semblent pas jouer en ma faveur. Ce qui me branche comme orientation professionnelle à l&#8217;époque, c&#8217;est l&#8217;armée, pour bosser dans le renseignement. J&#8217;aime la crypto et j&#8217;ai toujours eu un problème avec l&#8217;autorité quand celle-ci s&#8217;exerce abusivement, arbitrairement, injustement. Je pense que l&#8217;armée est une machine où l&#8217;autorité est plus impersonnelle donc plus juste. Et puis il y a la retraite de bonne heure, et puis y&#8217;a pas de chômage dans cette branche.</p>
<p>C&#8217;est alors que mon maitre de stage d&#8217;1 an plus tôt chez un opérateur télécom des Pays-Bas me dit qu&#8217;il monte sa boite, qu&#8217;il veut vendre un logiciel pour les télécoms à un opérateur en Thailande. En réalité mon stage lui avait servi d&#8217;étude de faisabilité. Bref, il me propose de bosser pour lui en Thailande, avec la perspective d&#8217;un salaire 2 à 2,5 fois supérieur à ce que touchent les copains de promo. Tchao le projet de rentrer dans l&#8217;armée et bonjour la Thailande ! Le 1er souci auquel on est confronté quand on se lance, c&#8217;est l&#8217;argent. Je recommande de ne pas se lancer sans avoir 3000€ de réserve. Le rusé renard qui faisait appel à mes services ne me payait pas l&#8217;hotel (~800€ par mois) et je n&#8217;ai signé mon contrat et n&#8217;ai été payé qu&#8217;après 2 mois de travail et quelques emails paniqués où je disais que j&#8217;étais pas sûr de pouvoir manger jusqu&#8217;à la fin de la semaine.</p>
<p>Niveau boulot, c&#8217;était extraordinaire. Je bossais 16 heures par jour (de mon plein gré et non forcé), de 9h à 3h du mat&#8217; mais je compte 2 heures de pause pour inclure le déjeuner et le diner. Ca laissait 4 heures de sommeil et 2 heures pour l&#8217;hygiène, les transports, et les loisirs. C&#8217;est énorme mais je le répète, c&#8217;était de mon plein gré. Ca me permettait d&#8217;abattre plus de boulot et de pouvoir être en phase avec le patron retourné en France, car le décalage horaire est de 5 ou 6 heures selon la saison. Je bossais aussi 6 ou 7 jours selon les semaines. Le logiciel réellement codé était beaucoup moins avancé que ce qui avait été vendu. J&#8217;étais donc obligé de mettre les bouchées doubles sur les tâches de conception et de développement, et je me prenais des insultes de la part du client sur les phases de livraison. C&#8217;est au cours de ce projet que j&#8217;ai rencontré une ingénieure thailandaise qui partagerait ma vie pendant 7 ans mais souvent à distance car elle est devenue consultante à son tour. Mais c&#8217;est tout ce que je dirai à son sujet car il ne m&#8217;appartient pas de raconter sa vie.</p>
<p>Après 7 mois de Thailande et un peu de repos en France, mon ancien patron fait appel à mes services en tant qu&#8217;employé. Conditions salariales très moyennes, mais un boulot c&#8217;est un boulot et quand je vois des potes ingénieurs qui se font embaucher au SMIC ou qui bossent chez McDo, je ne vais pas cracher sur ce job. Direction Bruxelles. Je vous épargne les détails sur la relation conflictuelle avec mon employeur que je quitte en très mauvais termes après un peu plus d&#8217;un an. Je poursuis néanmoins ma mission belge mais en indépendant. Chez l&#8217;opérateur, ça sent mauvais. Un nouveau PDG arrive qui décrète que tout le monde prendra 0% d&#8217;augmentation sauf les managers (12%) et lui-même (16,5%) tandis que l&#8217;entreprise dégage 10% ou 11% de bénéfice net. Etant indépendant, ça ne me concerne pas mais on est humain et on vit avec des collègues qui sont employés et dont l&#8217;avenir s&#8217;assombrit. Nouvelle lubie du PDG: l&#8217;outsourcing. Bien qu&#8217;opérateur télécom, il prétend que la technique n&#8217;est pas son coeur de métier. On sait que c&#8217;est de la comm&#8217; pour tromper les gens qui verront les infos dans le journal ou au JT, mais ça fait mal. Il y a un grand projet d&#8217;identification de toutes les tâches pour transférer toutes les équipes techniques chez un sous-traitant qui lui-même sera chargé de licencier en masse et de délocaliser le travail vers la Roumanie et le Liban. Tout ça met 1 an à se mettre en place et pendant cette année, l&#8217;ambiance se dégrade. Tous les midis après le repas, les collègues s&#8217;organisent un concours de Sudoku à leur bureau et même le chef d&#8217;équipe participe. Plus personne n&#8217;y croit. Des gens démissionnent. D&#8217;autres sauvent leur peau en faisant une mobilité interne vers un service non-outsourcé. Mon avenir étant compromis à moyen terme, je profite d&#8217;une opportunité de contrat aux Pays-Bas où je rejoins madame.</p>
<p>Je ne vais pas détailler tous les événements suivants, mais mes contrats suivants m&#8217;ont amené à travailler à nouveau en Belgique, puis en Afrique du Sud, et à vivre mes intercontrats en Thailande puis en Arménie quand madame y a travaillé et que j&#8217;étais sans boulot.</p>
<p>Pour répondre à Max qui demandait pourquoi j&#8217;avais quitté mon pays, je dirais donc que je ne l&#8217;ai pas choisi. J&#8217;ai suivi des opportunités mais ça ne résulte pas d&#8217;une volonté de quitter mon pays ou de me rendre dans un autre pays. En revanche, il est certain qu&#8217;avec le temps on développe un vrai amour pour d&#8217;autres destinations. Le pays que j&#8217;aime le plus, c&#8217;est la Thailande. La corruption y est omniprésente, il y a plein de problèmes de santé, du racisme, il y fait plus chaud et humide que dans un hammam, les gens regardent ta copine de travers quand ils voient qu&#8217;elle est avec un blanc, en se demandant si c&#8217;est une pute, y&#8217;a plein de choses qui ne vont pas&#8230; et pourtant c&#8217;est un endroit où on se sent bien. Ceci dit, il faut garder la tête sur les épaules : si on se sent bien en Thailande, c&#8217;est indubitablement lié au fait qu&#8217;on a un paquet de pognon comparé au Thai moyen.</p>
<h3>Mes observations</h3>
<p>Il me faut remarquer quelques points supplémentaires sur l&#8217;expatriation &#8230;quoique je n&#8217;aime pas le mot &#8220;expatriation&#8221; qui fait tellement penser aux employés choyés par leurs entreprises et qui ne vont jamais se mêler à la population du pays qui les accueille.</p>
<p><strong>1)</strong> Loin des yeux, loin du coeur : quand on vit à l&#8217;étranger, on perd ses amis de France. J&#8217;ai gardé un contact avec mon meilleur ami, sa femme, mon 2ème meilleur pote, et 2 autres copains. Pour le reste, je conserve une relation amicale avec la dizaine de copains d&#8217;études avec qui on partage un forum phpBB. Mais j&#8217;ai perdu de vue tous les autres.</p>
<p><strong>2)</strong> On devient un extra-terrestre. Ca n&#8217;est vrai que pour ceux qui restent vraiment longtemps à l&#8217;étranger, mais on est confronté à des réalités différentes. Il y a une infinité de choses qu&#8217;on prend pour acquis en France, des choses vraies ou fausses, et sur lesquelles la vie à l&#8217;étranger va apporter un éclairage nouveau. Et quand on revient en France, qu&#8217;on interagit avec des gens qui ne sont jamais partis, il peut y avoir un décalage. Vous imaginez toutes les choses qu&#8217;on peut faire ou dire de travers quand on s&#8217;adresse à un étranger ? Et bien c&#8217;est la même chose. On intègre des habitudes, des mimiques, ou des façons de penser qui peuvent être décalées par rapport à la France. Quelquefois c&#8217;est rigolo, et quelquefois ça rappelle l&#8217;allégorie de la caverne de Platon (extrait de l&#8217;excellent bouquin &#8220;La république&#8221; vivement recommandé) : on a l&#8217;impression d&#8217;être le mec qui est sorti de la caverne et qui a perçu un niveau supplémentaire de réalité, et quand on retourne en parler aux mecs qui sont restés dans la caverne, les mecs te trouvent méprisant ou refusent de te croire. Bref, j&#8217;ai pas besoin de psy mais y&#8217;a quand même quelques trucs frustrants dans ma vie.</p>
<p><strong>3)</strong> On découvre son propre pays. C&#8217;est un peu lié au point précédent. Quand on vit en France, on ne s&#8217;en rend pas compte. Mais les intellectuels pédants et vaniteux qui nous disent que nos journaux télévisés sont de la propagande&#8230; ont raison. Ca n&#8217;est pas nécessairement une propagande organisée sciemment. C&#8217;est probablement plus une question de prisme culturel. On a l&#8217;habitude de nous présenter un certain type d&#8217;information sous un certain angle. Mais quand on vit à l&#8217;étranger, il y a forcément des étrangers qui vont nous poser des questions sur la France, sur ce qu&#8217;ils ont vu dans leurs propres média, ou dans les média américains, et ils vont nous confronter&#8230; soit avec une sincère ingénuité, soit vicieusement. Et dans un cas comme dans l&#8217;autre, on va être confronté à un éclairage particulier sur le fonctionnement de la France, un éclairage qui est absent de nos média. Ceci génère un choc cognitif ou une dissonance cognitive. On est confronté à une réalité incompatible avec les idées qu&#8217;on s&#8217;était forgées et c&#8217;est douloureux. Instinctivement, émotionnellement, on va avoir pour réflexe de rejeter l&#8217;information présentée par l&#8217;interlocuteur. Mais si on arrive à mettre notre intellect au-dessus de nos émotions, on va aller vérifier les infos, et si c&#8217;est confirmé, on va avoir comme une boule de nerf au niveau de l&#8217;estomac, comme une rage qui monte, une colère sourde mais qui n&#8217;a pas d&#8217;autre objet que nous-même et l&#8217;erreur dans laquelle on a été. C&#8217;est douloureux, épuisant, frustrant, mais c&#8217;est précieux. C&#8217;est un sujet à part entière qui mériterait un article de blog, mais c&#8217;est le genre de chose qui permet à posteriori de se dire &#8220;je suis devenu meilleur grâce à cela&#8221;.</p>
<p><strong>3bis)</strong> du coup, je n&#8217;ai pas développé l&#8217;idée de découvrir son pays. Quand on vit à l&#8217;étranger, notre pays nous manque. Donc ok, y&#8217;a des gens qui vont nous confronter à un truc lu dans la presse internationale. Mais comme la France nous manque, on va prendre le réflexe de s&#8217;informer. Et puis ça permet de rester en phase avec le quotidien que vivent la famille et les amis. On écoute ou on lit France-Info, les news Google ou Yahoo, choisissez votre poison ! En ce qui me concerne, la politique ne m&#8217;intéressait pas avant mon départ, sauf Karl Zero qui a du talent pour le story-telling, mais désormais je suis devenu un geek de l&#8217;information et de la politique.</p>
<p><strong>4)</strong> Le temps ne s&#8217;arrête pas. Vivre à l&#8217;étranger c&#8217;est bien. Il y a certains conforts, certaines joies, etc. Mais notre vie française, nos relations avec les amis et la famille sont mises en pause. Pourtant, pour eux, le temps continue d&#8217;avancer. L&#8217;achat d&#8217;un bien immobilier, la construction d&#8217;une famille, l&#8217;adhésion à un club de sport, l&#8217;engagement dans une action associative, descendre des bières sur une terrasse avec les copains ou se retrouver tous les jeudis à la même pizzéria, c&#8217;est le genre de chose qui disparait à moins de savoir qu&#8217;on est installé pour la vie dans un endroit donné à l&#8217;étranger. A l&#8217;étranger, on peut prendre du bon temps, aller faire quelques visites touristiques, de la plongée sous-marine, et on peut gagner pas mal de pognon. Mais après quelques années, on se dit qu&#8217;on échangerait bien tout ce pognon contre la situation de potes qui ont des fins de mois difficiles mais ont une baraque, un jardin, des enfants, une routine, une vie.</p>
<p><strong>5)</strong> On découvre les peuples : on découvre des sociétés et des coutumes qui sont parfois très différentes et parfois étrangement similaires aux nôtres. Ca fait partie de l&#8217;enrichissement personnel. Comme ça, ça semble inutile, sauf que ça participe à notre dimension intellectuelle et politique. Quand tu es blanc et que tu marches dans les rues de Bangkok, y&#8217;a tous les taxis libres qui ralentissent en arrivant à ta hauteur, et y&#8217;a tous les rabatteurs qui te proposent soit des putes, soit des bars/spectacles à caractère sexuel, soit des films porno. Ca te fait réfléchir sur le racisme et sur l&#8217;hypersexualisation de la Thailande. Quand tu entends des hommes Thaï dire qu&#8217;il est &#8220;normal&#8221; de tromper sa femme et que tout le monde le fait, ça te fait réfléchir sur l&#8217;égalité des sexes et ça relativise l&#8217;hypersexualisation de la Thailande. Quand tu apprends qu&#8217;une femme Thaï divorcée n&#8217;a aucune chance de refonder un couple, ça te fait encore plus réfléchir sur l&#8217;égalité des sexes. Quand tu es aux Pays-Bas et qu&#8217;en réunion un collègue dit à la figure d&#8217;un autre que son idée est complètement débile, tu vois l&#8217;autre acquiescer et reconnaitre son erreur et ça te fait réfléchir sur l&#8217;éthique du travail&#8230; parce qu&#8217;en France, un truc comme ça finirait en engueulade voire en baston.</p>
<p>Voilà, voilà ! J&#8217;aime les pavés et encore je me suis retenu de développer certains thèmes abordés. S&#8217;il fallait conclure, je dirais que l&#8217;expatriation est très formatrice mais qu&#8217;on est faits pour vivre sédentairement tôt ou tard. Donc que vous choisissiez de vous installer définitivement à l&#8217;étranger ou que vous projetiez de revenir en France, il faut garder cet objectif de sédentarité en tête pour choisir au mieux votre mode de vie. Et aussi, profitez des opportunités pour partager le mode de vie des gens du pays d&#8217;accueil. Dernier conseil : même si je n&#8217;aime pas les Français de l&#8217;étranger, enregistrez-vous tout de même auprès de l&#8217;ambassade. Vous recevrez des invitations à des événements où on peut se gaver de petits fours et pourquoi pas rencontrer quelques personnes sympa malgré tout pour tisser des relations amicales ou créer des opportunités professionnelles.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8045&amp;md5=61a4e2c02264bd4b036c17a8c50662b7" 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=8082
title: Pourquoi il faut éviter import * en Python
uri: Pourquoi-il-faut-éviter-import-en-Python
url: http://sametmax.com/pourquoi-il-faut-eviter-import-en-python/
content:
<p>Ne pas utiliser l&#8217;<a href="http://sametmax.com/operateur-splat-ou-etoile-en-python/">opérateur splat</a> dans un import, vous l&#8217;avez sans doute lu 100 fois, mais savez-vous pourquoi ?</p>
<p>Regardez la fonction <code>open</code> :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">help</span><span style="color: black;">&#40;</span><span style="color: #008000;">open</span><span style="color: black;">&#41;</span>
    <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>name<span style="color: black;">&#91;</span>, mode<span style="color: black;">&#91;</span>, buffering<span style="color: black;">&#93;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span> -<span style="color: #66cc66;">&gt;</span> <span style="color: #008000;">file</span> <span style="color: #008000;">object</span>
&nbsp;
    Open a <span style="color: #008000;">file</span> using the <span style="color: #008000;">file</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #008000;">type</span>, returns a <span style="color: #008000;">file</span> <span style="color: #008000;">object</span>.  <span style="color: black;">This</span> <span style="color: #ff7700;font-weight:bold;">is</span> the
    preferred way to <span style="color: #008000;">open</span> a <span style="color: #008000;">file</span>.  <span style="color: black;">See</span> <span style="color: #008000;">file</span>.__doc__ <span style="color: #ff7700;font-weight:bold;">for</span> further information.
<span style="color: black;">&#40;</span>END<span style="color: black;">&#41;</span></pre></div></div>

<p>Maintenant, si j&#8217;importe le module <code>os</code>, ça ne change rien :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">help</span><span style="color: black;">&#40;</span><span style="color: #008000;">open</span><span style="color: black;">&#41;</span>
    <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>name<span style="color: black;">&#91;</span>, mode<span style="color: black;">&#91;</span>, buffering<span style="color: black;">&#93;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span> -<span style="color: #66cc66;">&gt;</span> <span style="color: #008000;">file</span> <span style="color: #008000;">object</span>
&nbsp;
    Open a <span style="color: #008000;">file</span> using the <span style="color: #008000;">file</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #008000;">type</span>, returns a <span style="color: #008000;">file</span> <span style="color: #008000;">object</span>.  <span style="color: black;">This</span> <span style="color: #ff7700;font-weight:bold;">is</span> the
    preferred way to <span style="color: #008000;">open</span> a <span style="color: #008000;">file</span>.  <span style="color: black;">See</span> <span style="color: #008000;">file</span>.__doc__ <span style="color: #ff7700;font-weight:bold;">for</span> further information.
<span style="color: black;">&#40;</span>END<span style="color: black;">&#41;</span></pre></div></div>

<p>Si par contre j&#8217;importe tout le contenu du module <code>os</code>, sans namespace :</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;">os</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">help</span><span style="color: black;">&#40;</span><span style="color: #008000;">open</span><span style="color: black;">&#41;</span>
    <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>filename, flag <span style="color: black;">&#91;</span>, mode=0777<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span> -<span style="color: #66cc66;">&gt;</span> fd
&nbsp;
    Open a <span style="color: #008000;">file</span> <span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">for</span> low level IO<span style="color: black;">&#41;</span>.
<span style="color: black;">&#40;</span>END<span style="color: black;">&#41;</span></pre></div></div>

<p>La différence ?</p>
<p>Dans le premier cas, on a la fonction <code>open()</code> built-in de Python. Dans le second cas, la fonction <code>os.open()</code> a été importée et a remplacée la fonction <code>open()</code>.</p>
<p>Ici le bug sera très difficile à trouver, car les deux fonctions ont presque la même signature :</p>
<p><code>open(name[, mode[, buffering]]) -> file object</code></p>
<p>VS </p>
<p><code>open(filename, flag [, mode=0777]) -> fd</code></p>
<p>Et en plus un usage très similaire.</p>
<p>Bottom line, <code>import *</code>, c&#8217;est pour les sessions shell. Dans vos fichiers de code, ne l&#8217;utilisez pas, vous ne savez pas ce que vous importez.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8082&amp;md5=e41900ebed59acfdf42fcf7ebddfac09" 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=8098
title: C’est pour des trucs comme ça que j’adore Python…
uri: C-est-pour-des-trucs-comme-ça-que-j-adore-Python
url: http://sametmax.com/cest-pour-des-trucs-comme-ca-que-jadore-python/
content:
<p>La manipulation de structures de données est fantastique dans ce langage.</p>
<p>J&#8217;avais un problème du genre : </p>
<p>&#8220;soit des personnes dans une file ayant un rang supposé&#8230;&#8221;"</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">persons = <span style="color: black;">&#91;</span>
    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Nadine'</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>,
    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Tom'</span>, <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>,
    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Christophe'</span>, <span style="color: #ff4500;">7</span><span style="color: black;">&#41;</span>,
    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Cloclo'</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>,
    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Lily'</span>, <span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>,
    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Georges'</span>, <span style="color: #ff4500;">7</span><span style="color: black;">&#41;</span>,
    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Paul'</span>, <span style="color: #ff4500;">6</span><span style="color: black;">&#41;</span>,
    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Bérénice'</span>, <span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>,
    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Ursula'</span>, <span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span>,
    <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Lea'</span>, <span style="color: #ff4500;">15</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#93;</span></pre></div></div>

<p>&#8220;&#8230;trouver, parmi les 5 premières, celles qui sont effectivement à leur place&#8221;</p>
<p>Vous connaissez mon amour immodéré pour les <a href="http://sametmax.com/python-love-les-listes-en-intention-partie/">listes en intention</a> en Python :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: black;">&#91;</span>name <span style="color: #ff7700;font-weight:bold;">for</span> i, <span style="color: black;">&#40;</span>name, rank<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">enumerate</span><span style="color: black;">&#40;</span>persons<span style="color: black;">&#91;</span>:<span style="color: #ff4500;">5</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: black;">&#40;</span>i + <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span> == rank<span style="color: black;">&#93;</span>
<span style="color: black;">&#91;</span>u<span style="color: #483d8b;">'Tom'</span>, u<span style="color: #483d8b;">'Lily'</span><span style="color: black;">&#93;</span></pre></div></div>

<p>Snif. j&#8217;en pleurerais presque.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8098&amp;md5=b068ab4f0e4baf6c3a5ae28b676c7f3f" 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=8115
title: Astuces de recherche
uri: Astuces-de-recherche
url: http://sametmax.com/astuces-de-recherche/
content:
<p>Quand vous voulez traduire un mot compliqué d&#8217;une langue à l&#8217;autre, les outils de traduction en ligne marchent pas super bien. Une bonne solution ? Chercher le terme sur wikipedia, puis demander l&#8217;article dans une autre langue. Non seulement on a la traduction voulue dans le titre de l&#8217;article, mais en plus tout le champ lexical lié dans le corps de l&#8217;article.</p>
<p>Tips : la commande bang pour ddg est <code>!wfr</code> pour la version française de wikipédia.</p>
<p>Quand vous cherchez un nouveau mot à la noix comme &#8220;lulz&#8221;, un truc cochon style &#8220;bukakke&#8221; ou une abréviation obscure du genre &#8220;GTFO&#8221;, vous n&#8217;allez pas la trouver dans le dico ou sur wikipedia. La meilleure source pour ce genre de terme : <a href="http://www.urbandictionary.com/">urbandictionry.com</a>. En plus, c&#8217;est drôle.</p>
<p>Tips : la commande bang pour ddg est <code>!ud</code></p>
<p>Vous voulez regarder un film ou une série en VO streaming mais elle n&#8217;est pas sortie en France ? Ou alors votre connexion bride ces fournisseurs ? Ou vous avez peur de vous faire choper ?</p>
<p>Allez sur les sites de streaming en espangol ! Ils listent les mêmes séries, le plus souvent en VO sous-titré ES, sur des hébergeurs différents complètement hors radar de nos tristes sires français. Et en plus, il n&#8217;y a pas de limite de temps ou de débit. Exemple : <a href="http://seriesyonkis.com/pe">seriesyonkis</a> et <a href="http://pelis24.com/">peli24</a>.</p>
<p>Tips : évitez les séries doublées en espagnol comme la peste. C&#8217;est HORRIBLE. Dans stargate O&#8217;Neil a la voix de Teal&#8217;c et inversement&#8230;</p>
<p>Vous allez sur des sites de rencontre et vous voulez évitez les faux profiles ? Clic-droit sur la photo et enregistrez l&#8217;image sur votre bureau. Allez sur <a href="http://www.google.com/imghp">Google Image</a>, et dans le champ, cliquez sur l&#8217;appareil photo pour uploader l&#8217;image.</p>
<p>Vous allez très vite voir si l&#8217;image a été réutilisée.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8115&amp;md5=c77c06b16c4fac2c87d5127963da52bb" 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=8103
title: Qu’est-ce qu’un namespace ?
uri: Qu-est-ce-qu-un-namespace
url: http://sametmax.com/quest-ce-quun-namespace/
content:
<p>Un mot qui vient et qui revient comme on en a des tas en informatique, et qui est utilisé par tout le monde comme si chacun était supposé savoir.</p>
<p>Très énervant quand on ne sait pas ce que ça veut dire.</p>
<p>Un namespace, ou espace de noms, est simplement un conteneur de noms, un groupe.</p>
<p>On s&#8217;en sert pour pouvoir distinguer deux choses qui ont le même nom.</p>
<p>Par exemple, un trou du cul peut être un anus ou un connard. Si quelqu&#8217;un fait la mention d&#8217;un &#8220;trou du cul&#8221;, j&#8217;ai besoin de contexte pour savoir si il parle d&#8217;un orifice ou d&#8217;un fils d&#8217;horreur. Ce contexte peut être donné par un namespace.</p>
<p>Comment est représenté un namespace dépend de l&#8217;outil utilisé.</p>
<p>Ainsi, en XML, c&#8217;est un préfixe puis deux points :</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;xsd:element<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/xsd:element<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;taoisme:element<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/taoisme:element<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>Ici j&#8217;ai deux balises &#8220;element&#8221;, mais elles sont préfixées par deux namespaces : <code>xsd</code> et <code>taoisme</code>.</p>
<p>C&#8217;est tout. Il n&#8217;y a rien d&#8217;autre caché derrière le namespace, c&#8217;est simplement un moyen de s&#8217;assurer qu&#8217;on sait bien de quoi on parle.</p>
<p>Certains namespaces sont standardisés. Par exemple, <code>xsd</code> est un namespace réservé aux balises qu&#8217;on retrouve dans un fichier <em>.xsd</em>. D&#8217;autres sont créés par les utilisateurs pour des raisons d&#8217;organisation.</p>
<p>En effet, un des avantages du namespace, c&#8217;est qu&#8217;il évite que deux références homonymes ne s&#8217;écrasent l&#8217;une l&#8217;autre.</p>
<p>Par exemple en Python, le nom du module qui contient une fonction peut servir de namespace.</p>
<p>Si je fais :</p>

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

<p>Alors j&#8217;ai accès à trois fonctions open():</p>
<ul>
<li><strong>os.open()</strong>: la fonction du <code>open()</code> du module <code>os</code> dont le nom est préfixé par le namespace <em>os</em>.</li>
<li><strong>shelve.open()</strong>: la fonction du <code>open()</code> du module <code>shelve</code> dont le nom est prefixé par le namespace <em>shelve</em>.</li>
<li><strong>open()</strong>: la fonction du <code>open()</code> dont le nom n&#8217;est PAS préfixé est qui est donc dans le namespace <em>en cours</em>.</li>
</ul>
<p>Et aucune fonction ne s&#8217;écrase l&#8217;une l&#8217;autre. Le nom du module, étant utilisé comme namespace, permet la distinction pour l&#8217;humain ET la machine.</p>
<p>Dans ce langage, cependant, on peut copier une référence d&#8217;un namespace à l&#8217;autre. 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;">datetime</span> <span style="color: #ff7700;font-weight:bold;">import</span> date</pre></div></div>

<p>Ceci va importer <code>date</code> et le rendre disponible dans le namespace en cours. Du coup on aura pas besoin de préfixer <code>date</code> pour l&#8217;utiliser dans le namespace en cours, mais en contrepartie, on ne pourra pas créer de variable <code>date</code> car cela écraserait la référence précédente.</p>
<p>Si vous prenez par exemple PHP 5 qui n&#8217;avait pas encore de mécanisme de namespace à l&#8217;époque, les dev étaient obligés de créer artificiellement un namespace en allongeant le nom de toutes leurs fonctions avec &#8216;sujet_&#8217;. Ce qui donnait <a href="http://php.net/manual/en/book.mysql.php">des noms à rallonge</a> du genre : <strong>mysql_real_escape_string()</strong>.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8103&amp;md5=7acfbe8e08424567f559e22640312edc" 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=8084
title: Le deuil d’une idée
uri: Le-deuil-d-une-idée
url: http://sametmax.com/le-deuil-dune-idee/
content:
<p style="text-align: center;"><em><small>Ceci est un post invité de <a href="http://sametmax.com/author/Erik/">Erik</a> posté sous licence <a href="http://creativecommons.org/licenses/by/3.0/">creative common 3.0 unported</a>.</small></em></p>
<p>Dans mon <a href="http://sametmax.com/quitter-son-pays/">précédent article</a> sur le site de Sam et Max, je parlais d&#8217;expatriation. En parlant des discussions qu&#8217;on pouvait avoir avec des étrangers j&#8217;ai évoqué le sentiment particulier qui vous saisit lorsqu&#8217;un interlocuteur vous présente des arguments ou des idées qui vont mener à la destruction de votre opinion passée et à l&#8217;intégration d&#8217;une nouvelle opinion opposée à la précédente. J&#8217;avais dit que ce sentiment à lui seul méritait un article complet et puisqu&#8217;un commentateur a voulu en savoir plus, voici la réponse à sa demande.</p>
<p>Le sujet de cet article est un phénomène ressenti. Est-ce que ça m&#8217;est propre ou est-ce que d&#8217;autres personnes vivent la même situation de la même manière ? Je pense que c&#8217;est générique mais comme cela survient dans des conditions un peu particulières et qui, je le crains, ne seront pas vécues par beaucoup de gens, je n&#8217;ai jamais eu l&#8217;occasion d&#8217;en discuter avec quelqu&#8217;un partageant ce ressenti.</p>
<p>Ce dont je parle, c&#8217;est la sensation physique et mentale qu&#8217;on a lorsqu&#8217;on découvre qu&#8217;on avait des opinions fausses et qu&#8217;au delà de la simple découverte on intègre cette découverte dans notre conscience et on admet publiquement avoir été dans l&#8217;erreur et on admet reconnaître la validité de l&#8217;opinion à laquelle on s&#8217;était préalablement opposé.</p>
<p>Ca fait beaucoup de découvertes et d&#8217;admissions, mais ces précisions sont importantes parce qu&#8217;il est question d&#8217;une expérience très personnelle. Si notre erreur était sans importance sur un sujet sans importance, comme donner la mauvaise réponse en regardant &#8220;Questions pour un champion&#8221; à la télé, il est évident que ça ne nous touchera pas.</p>
<p>Je vais en venir à des exemples précis, ne vous impatientez pas ! Mais il faut aussi expliquer dans quelles situations ce phénomène survient. Je suis un grand débatteur. Sur un site d&#8217;actualités informatiques, j&#8217;ai déjà contribué plus de 4500 messages dans plus de 1000 sujets et comme pour mon précédent article chez Sam et Max, j&#8217;ai pour habitude d&#8217;écrire des pavés. Sur un forum privé avec des amis, c&#8217;est plus de 10,000 messages que j&#8217;ai laissés tantôt pour de la conversation de comptoir et tantôt pour du débat, encore et toujours sous forme de pavé. C&#8217;est un de mes travers : ce qui se conçoit bien s&#8217;énonce clairement et pour cela je n&#8217;arrive pas à faire des phrases courtes et peu nombreuses. Si je veux éviter ou limiter la méprise chez les gens qui me lisent et me répondent, j&#8217;ai la compulsion d&#8217;être aussi précis et exhaustif que possible. Le débat sur des forums est une forme d&#8217;art, une discipline à part entière. Benjamin Bayart, l&#8217;ancien président de French Data Network, y fait allusion dans ce qui est désormais appelé &#8220;<a href="http://erikdefrance.blogspot.fr/2013/11/lechelle-bayart.html">l&#8217;échelle Bayart</a>&#8221; : une classification des internautes en fonction de leur maturité dans l&#8217;utilisation d&#8217;internet. Au stade de &#8220;commentateur&#8221;, on échange de réelles informations avec nos interlocuteurs et pour peu qu&#8217;on ait des gens de bonne volonté et de bonne foi de chaque côté d&#8217;une certaine thèse, on peut émettre et recevoir des arguments qui feront progresser nos connaissances et seront à même de nous faire progresser vers la vérité et de dépasser nos erreurs lorsque c&#8217;est le débatteur adverse qui a raison. Quand des arguments sont suffisamment étayés pour être convaincants et sont inattaquables, il se passe généralement l&#8217;une des 2 choses suivantes. La 1ère réaction possible est le <i>ragequit</i>, ce qui veut dire que blessé dans notre amour-propre on quitte la discussion qu&#8217;on laisse derrière nous pour ne plus la voir et ne pas l&#8217;affronter. La 2ème réaction possible est d&#8217;intégrer la validité des arguments qui nous ont été présentés et de le reconnaître publiquement. C&#8217;est plus difficile à faire qu&#8217;à dire et c&#8217;est l&#8217;objet de cet article. J&#8217;ai détaillé l&#8217;exemple du débat sur un forum internet, mais le même genre d&#8217;interaction est possible hors internet simplement en discutant avec un ami.</p>
<p>Cette sensation dont je parle, c&#8217;est comme une boule de nerf à l&#8217;estomac ou au niveau du plexus. Ca vous prend aux tripes. La boule de nerf se traduit aussi par une gorge noueuse et une déglutition difficile ou douloureuse. Les muscles sont tendus. On transpire. Vous avez déjà eu un grand sentiment de colère dirigé contre vous-même ? Vous avez déjà fulminé ? Et bien c&#8217;est cela. C&#8217;est de la colère et du stress. On a envie de mettre un coup de poing dans le mur. C&#8217;est comme si les idées dans notre tête menaient une guerre les unes contre les autres. Une seule opinion sortira gagnante et l&#8217;autre devra mourir. Dans le cerveau, c&#8217;est un peu comme quand vous vous faites virer d&#8217;un boulot (ou autre situation stressante). Vous savez que ressasser ces choses douloureuses est inutile et puisque vous avez intégré l&#8217;information intellectuellement, vous aimeriez bien pouvoir en détourner votre attention pour arrêter d&#8217;en souffrir. Mais au lieu de cela, vous êtes pris d&#8217;obsession et votre attention revient vers ce sujet encore et encore. Quand vient la fin de journée, vous êtes épuisé physiquement et mentalement.</p>
<p>La première fois où je me rappelle avoir vécu cette sensation, je n&#8217;ai pas reconnu publiquement mon erreur mais j&#8217;ai intégré consciemment l&#8217;argument présenté par mon interlocuteur. C&#8217;était à l&#8217;époque du PACS, pendant mes études. En arrivant au restaurant universitaire avec un copain d&#8217;études, on s&#8217;est fait distribuer des tracts au sujet des homosexuels. Je ne me rappelle plus si c&#8217;était en leur faveur ou leur défaveur, et ce n&#8217;est pas important. A l&#8217;époque, j&#8217;étais de l&#8217;avis que l&#8217;homosexualité n&#8217;était pas naturelle. Mon erreur résidait dans le fait de prendre mon hétérosexualité comme une norme universelle. Mais le pote présent avec moi de manière très nonchalante a su me présenter un argument simple et imparable sur le fait que l&#8217;homosexualité était tout à fait naturelle même si elle concerne une minorité de personnes. Je ne saurais pas retrouver ses mots et c&#8217;est peu important. De toutes façons, cet article n&#8217;a pas vocation à débattre sur l&#8217;homosexualité. Pratiquement 15 ans après cette discussion, mes émotions sont encore en désaccord avec mon cerveau. J&#8217;ai toujours une réaction émotionnelle négative si je vois 2 mecs en train de se rouler une pelle, mais intellectuellement (et donc politiquement) je suis à fond pour faire disparaître les différences légales qui existent entre hétéros et homos. Mais ce qui compte et qu&#8217;il faut retenir, c&#8217;est cette confrontation de l&#8217;intellect à une idée contraire mais justifiée et qui nécessite de changer d&#8217;opinion.</p>
<p>La seconde fois, il me semble, fut lorsque ma compagne Thaï a discuté avec moi des prisons françaises. Pour faire simple, elle m&#8217;a fait valoir que nos prisons nationales étaient assez inhumaines comparées à ce qui se fait dans d&#8217;autres pays. Venant d&#8217;un petit bout de femme ayant grandi à 10000 km de la France, ça m&#8217;a sérieusement chauffé. Pendant ma pause diner, j&#8217;ai sorti Google et j&#8217;ai commencé à me renseigner sur ce que madame disait. Et il est vrai que le système carcéral français est vilain comparé à ce qui se fait dans les autres pays développés. A l&#8217;époque, je commençais à peine à m&#8217;intéresser à la politique et donc c&#8217;est un sujet que je ne connaissais pas. En tout cas, je ne le connaissais pas avant d&#8217;avoir dégainé mon Google. Et dans les années suivantes, ce que j&#8217;ai alors découvert a été confirmé par les multiples rapports alarmants du Contrôleur général des lieux de privation de liberté, de la Cour des Comptes, les multiples condamnations de la France par la Cour Européenne des Droits de l&#8217;Homme, et les diverses ordonnances par le Conseil d&#8217;Etat tantôt pour dératiser une prison, tantôt pour rénover une autre qui aurait fait honte à Midnight Express. Surpopulation, taux de suicide très supérieur à ce qui se passe à l&#8217;étranger, incarcération de gens qui relèvent plutôt de la psychiatrie&#8230; C&#8217;était donc début 2004, quelques mois après le début de mon expatriation. Je n&#8217;ai jamais eu la fibre nationaliste mais se faire dire par sa chérie thaïlandaise que la France est un pays inhumain en matière de prisons ça fait mal au coeur, et découvrir qu&#8217;elle a raison est encore plus douloureux. Comme dit plus haut, c&#8217;est vraiment un sentiment physique et mental et je pense que le terme de &#8220;douleur&#8221; est approprié. Il y a une réelle souffrance.</p>
<p>Par la suite, j&#8217;ai eu plusieurs occasions sur les forums internet de développer mes connaissances de la manière décrite plus haut. J&#8217;ai ainsi pu découvrir des choses qui allaient contre mes opinions. Inutile de lister tous les sujets sur lesquels c&#8217;est arrivé. Il m&#8217;est arrivé de retomber dans le <i>ragequit</i>. C&#8217;est normal. C&#8217;est naturel. Ce n&#8217;est pas du jour au lendemain qu&#8217;on apprend à dire &#8220;<i>merci de m&#8217;avoir montré à quel point j&#8217;avais tort et pourquoi</i>&#8220;. Même aujourd&#8217;hui, alors que j&#8217;ai bien intégré la chose, ça reste quelque chose de douloureux mais on s&#8217;y soumet plus facilement. Comme les prises de sang ou les visites chez le dentiste (ou pas, pour le dentiste). Pratiquement tous les sujets qui prêtent à débat passionné ont une réponse et à moins d&#8217;avoir activement recherché l&#8217;information qui transforme votre opinion en connaissance, la validité de votre opinion c&#8217;est zéro. Votre opinion est à peu près aussi valide que le résultat d&#8217;un tirage à pile ou face.</p>
<p>On a une tendance naturelle (c&#8217;est prouvé scientifiquement) à refuser l&#8217;exploration des arguments adverses. On a un penchant naturel pour les arguments qui nous confortent (le mot &#8220;confort&#8221; n&#8217;est pas fortuit) dans nos opinions. C&#8217;est confortable d&#8217;être dans un endroit sécurisant et qui renforce ce qu&#8217;on tient pour acquis tandis qu&#8217;un défi à nos opinions est une forme d&#8217;agression. C&#8217;est le genre de chose qui mène au <a href="http://fr.wikipedia.org/wiki/Biais_de_confirmation">biais de confirmation</a> et autres processus erronnés de raisonnement.</p>
<p>Petit aparté : il est tout à fait envisageable à ce stade de mon article qu&#8217;un lecteur ait cette question à me poser : Qu&#8217;est-ce qu&#8217;un argument convaincant ? Comment peux-tu être sûr de la validité d&#8217;un argument ou du résultat d&#8217;une étude, etc. ? Ce genre de question est trop complexe pour faire un article dessus sur le site de Sam et Max. Dans ma démarche intellectuelle, je me suis tapé de la lecture, du podcast et du visionnage de conférences sur plusieurs sujets qui concourent à la compréhension de cette thématique. On parle de logique, de scepticisme scientifique, philosophie des sciences, théorie de la connaissance, épistémologie, et j&#8217;ai déjà consacré quelques centaines d&#8217;heures d&#8217;écoute ou de visionnage à des débats sur des thématiques religieuses, philosophiques et scientifiques. En fait, j&#8217;ai une série d&#8217;articles en cours de rédaction sur mon blog pour aborder ces thèmes et même selon mes standards de pavés, ces articles sont conséquents et je commence à envisager la rédaction d&#8217;un livre. Donc voilà : si vous comptiez poser une question comme ça, je vous ai pris de court. Nananèreeuuuuh&#8230; :-P</p>
<p>Si vous n&#8217;avez jamais vécu ce phénomène dont je vous parle et si vous n&#8217;arrivez pas à vous représenter la chose, réfléchissez donc à une opinion ou une croyance qui vous est chère et ce que ça vous ferait si on vous mettait sous le nez la preuve irréfutable que vous vous êtes trompé ! Le meilleur exemple est probablement la religion : si vous avez une religion et que demain je vous démontre de manière irréfutable que votre religion est fausse, vous le vivrez comment ? Je ne vais pas mener ici le débat sur la religion parce que ce n&#8217;est pas le sujet. Et pour la raison exposée plus haut, je sais que mettre au défi ses croyances importantes est une forme d&#8217;agression. Donc je ne mènerai pas ce débat, mais j&#8217;espère que cet exemple peut être parlant pour les lecteurs pour essayer d&#8217;imaginer ce que ça peut faire quand leur opinion ou leur croyance est prise en défaut. Sérieusement, si vous êtes religieux, réfléchissez à cette situation hypothétique ! Et si vous ne l&#8217;êtes pas, essayez d&#8217;avoir la réflexion sur un autre sujet qui vous tient à coeur.</p>
<p>Pour comprendre ce phénomène dont je parle, il y a une autre analogie qui me semble adéquate et c&#8217;est ce qui a inspiré le titre de cet article. C&#8217;est le <a href="http://fr.wikipedia.org/wiki/Elisabeth_K%C3%BCbler-Ross#Stades_de_la_mort_annonc.C3.A9e">modèle de Kübler-Ross</a> aussi appelé &#8220;les 5 étapes du deuil&#8221; : le déni, la colère, le marchandage, la dépression et l&#8217;acceptation. Reconnaître son erreur, c&#8217;est comme faire le deuil d&#8217;une opinion.</p>
<p>J&#8217;espère que cet article répond à la question qui m&#8217;a été posée et que les lecteurs auront su mettre le contenu en relation avec leur propre vécu.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8084&amp;md5=f52394ace47cde38bf5609327b171230" 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=8141
title: Pour vos thumbnails, ImageMagick à la rescousse
uri: Pour-vos-thumbnails-ImageMagick-à-la-rescousse
url: http://sametmax.com/pour-vos-thumbnails-imagemagick-a-la-rescousse/
content:
<p><a href="http://www.imagemagick.org/">ImageMagick</a> est la solution de manipulation d&#8217;images la plus souple et versatile à disposition. Après pas mal de tests, Max en avait conclu qu&#8217;appeler la lib avec un bon <a href="http://docs.python.org/2/library/subprocess.html">subprocess</a> était simplement plus rapide et donnait des résultats de meilleure qualité que d&#8217;utiliser PIL en Python ou GD en PHP.</p>
<p>Et je peux vous dire qu&#8217;il en a fait des tests pour obtenir le thumbnail des nichons parfait. C&#8217;est un perfectionniste quand il s&#8217;agit des tétons.</p>
<p>En général, on trouve ImageMagick dans les dépôts. Par exemple, sous debian :</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> imagemagick</pre></div></div>

<p>Mais il n&#8217;est pas rare que Max compile la bête histoire d&#8217;avoir la même version partout :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">wget</span> http:<span style="color: #000000; font-weight: bold;">//</span>mirror.checkdomain.de<span style="color: #000000; font-weight: bold;">/</span>imagemagick<span style="color: #000000; font-weight: bold;">/</span>ImageMagick-6.8.7-<span style="color: #000000;">4</span>.tar.gz ; <span style="color: #c20cb9; font-weight: bold;">tar</span> <span style="color: #660033;">-xvf</span> ImageMagick-6.8.7-<span style="color: #000000;">4</span>.tar.gz ; <span style="color: #7a0874; font-weight: bold;">cd</span> ImageMagick-6.8.7-<span style="color: #000000;">4</span>
.<span style="color: #000000; font-weight: bold;">/</span>configure
<span style="color: #c20cb9; font-weight: bold;">make</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #c20cb9; font-weight: bold;">make</span> <span style="color: #c20cb9; font-weight: bold;">install</span>
<span style="color: #c20cb9; font-weight: bold;">ln</span> <span style="color: #660033;">-s</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>convert <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>convert
<span style="color: #c20cb9; font-weight: bold;">ln</span> <span style="color: #660033;">-s</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>identify <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>identify</pre></div></div>

<p>Après tout ça, vous aurez accès à plusieurs commandes, qui permettent des manipulations d&#8217;images diverses.</p>
<p>Par exemple, <code>identify</code> permet de récupérer des informations sur l&#8217;image telles que le format, la profondeur des couleurs&#8230; Nous on l&#8217;utilise surtout pour récupérer la taille :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">identify <span style="color: #660033;">-format</span> <span style="color: #ff0000;">&quot;%[fx:w],%[fx:h]&quot;</span> <span style="color: #ff0000;">&quot;chemin/vers/image&quot;</span></pre></div></div>

<p>On peut utiliser un wrapper tel que <a href="http://docs.wand-py.org">wand</a> pour utiliser ça depuis Python. Mais il est très facile de se faire un wrapper vite fait à la main :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> envoy
<span style="color: #ff7700;font-weight:bold;">from</span> minibelt <span style="color: #ff7700;font-weight:bold;">import</span> normalize
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> ImageMagicError<span style="color: black;">&#40;</span><span style="color: #008000;">Exception</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, result, encoding<span style="color: black;">&#41;</span>:
        msg = normalize<span style="color: black;">&#40;</span>result.<span style="color: black;">std_err</span>.<span style="color: black;">decode</span><span style="color: black;">&#40;</span>encoding<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">super</span><span style="color: black;">&#40;</span>ImageMagicError, <span style="color: #008000;">self</span><span style="color: black;">&#41;</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span>msg<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> size<span style="color: black;">&#40;</span>img, encoding=<span style="color: #dc143c;">sys</span>.<span style="color: black;">stdout</span>.<span style="color: black;">encoding</span><span style="color: black;">&#41;</span>:
    r = envoy.<span style="color: black;">run</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'identify -format &quot;%[fx:w],%[fx:h]&quot; &quot;{}&quot;'</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>img<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> r.<span style="color: black;">status_code</span> <span style="color: #66cc66;">!</span>= <span style="color: #ff4500;">0</span>:
        <span style="color: #ff7700;font-weight:bold;">raise</span> ImageMagicError<span style="color: black;">&#40;</span>r, encoding<span style="color: black;">&#41;</span>
&nbsp;
    w, h = r.<span style="color: black;">std_out</span>.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">','</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>w<span style="color: black;">&#41;</span>, <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>h<span style="color: black;">&#41;</span></pre></div></div>

<p>Notez que j&#8217;utilise <a href="https://github.com/sametmax/minibelt">minibelt</a> et <a href="https://github.com/kennethreitz/envoy/">envoy</a> (un wrapper pour subprocess), car je suis une grosse feignasse.</p>
<p>Pour faire un thumbnail, la recette est plus compliquée, car ImageMagick est à l&#8217;image, ce que Perl est à la programmation. There’s_more_than_one_way_to_do_it ©.</p>
<p>Au final, celui qui nous a donné le meilleur résultat en qualité est cette suite d&#8217;arcanes secrètes transmise d&#8217;oreille de druide à oreille de druide :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">convert chemin<span style="color: #000000; font-weight: bold;">/</span>image<span style="color: #000000; font-weight: bold;">/</span>originale <span style="color: #660033;">-thumbnail</span> largeurxhauteur^ <span style="color: #660033;">-gravity</span> center <span style="color: #660033;">-extent</span> largeurxhauteur <span style="color: #660033;">-quality</span> <span style="color: #000000;">80</span> chemin<span style="color: #000000; font-weight: bold;">/</span>vers<span style="color: #000000; font-weight: bold;">/</span>resultat.jpg</pre></div></div>

<p>Ceci va redimensionner l&#8217;image en conservant le ratio, et si le résultat n&#8217;est pas adaptée aux dimensions finales, va en découper une partie tout en préservant le centre de l&#8217;image. La sortie sera un jpg avec un taux de qualité de 80%.</p>
<p>Là encore, un petit wrapper ne fait pas de mal :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> thumb<span style="color: black;">&#40;</span>img, width, heigth, output, crop=<span style="color: #008000;">False</span>, encoding=<span style="color: #dc143c;">sys</span>.<span style="color: black;">stdout</span>.<span style="color: black;">encoding</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> crop:
        <span style="color: #ff7700;font-weight:bold;">if</span> crop <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">True</span>:
            crop = <span style="color: #483d8b;">'center'</span>
        crop = <span style="color: #483d8b;">&quot;-gravity {} -extent {}x{}&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>crop, width, heigth<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        crop = <span style="color: #483d8b;">''</span>
&nbsp;
    <span style="color: #dc143c;">cmd</span> = <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;convert {img} -thumbnail {width}x{heigth}^ {crop} -quality 80 {output}&quot;</span><span style="color: black;">&#41;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>
          img=img, width=width, heigth=heigth, crop=crop, output=output,
    <span style="color: black;">&#41;</span>
&nbsp;
    r =  envoy.<span style="color: black;">run</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">cmd</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> r.<span style="color: black;">status_code</span> <span style="color: #66cc66;">!</span>= <span style="color: #ff4500;">0</span>:
        <span style="color: #ff7700;font-weight:bold;">raise</span> ImageMagicError<span style="color: black;">&#40;</span>r, encoding<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> r</pre></div></div>

<p>Bref, ce genre de petit bricolage est loin d&#8217;être propre, mais il s&#8217;est montré fort robuste et efficace au fil des années. Quand on fait des dizaines de milliers de screenshots de films de cul tous les jours, c&#8217;est important :-)</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8141&amp;md5=3660806e0a423f254095faf72f0ed79c" 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=8020
title: Changer le mot de passe du super utilisateur django en ligne de commande
uri: Changer-le-mot-de-passe-du-super-utilisateur-django-en-ligne-de-comman
url: http://sametmax.com/changer-le-mot-de-passe-du-super-utilisateur-django-en-ligne-de-commande/
content:
<p>Vous avez oublié ce maudit mot de passe ? Impossible de se connecter à l&#8217;admin ?</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 changepassword username</pre></div></div>

<p>Pas besoin d&#8217;être root.</p>
<p>Souvenez-vous aussi que vous pouvez quasiment tout faire depuis un shell en faisant :</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</pre></div></div>

<p>Ce qui vous permet d&#8217;importer les modèles de vos apps et faire toutes les querys que vous voulez.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8020&amp;md5=30502664a6433d32c395442f20ec728d" 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=8150
title: Le point sur le blog (et une mise à jour)
uri: Le-point-sur-le-blog-(et-une-mise-à-jour)
url: http://sametmax.com/le-point-sur-le-blog-et-une-mise-a-jour/
content:
<p>On a fait pas mal de hors sujets ces derniers temps.</p>
<p>Les articles sur le voyage ont encore du sens sur le blog, puisque Max et moi voyageons beaucoup. Et puis le dernier était très bon.</p>
<p>Mais on commence à être loin de Python et du cul. J&#8217;ai rien contre, il faut juste savoir doser.</p>
<p>Du coup il est possible qu&#8217;on refuse (ou publie un peu plus tard) certaines contributions.</p>
<p>Comme d&#8217;habitude, on répond toujours à tous les mails. Parfois avec des mois de retard. Oui, des mois. Mais on répond (ou alors vous êtes dans nos spams ^^). </p>
<p>Je profite de cet article qui est un grand fourre tout pour remercier ÉNORMÉMENT tous les contributeurs qui ont pondu des articles invités et ont corrigé nos fautes :</p>
<ul>
<li>01ivier</li>
<li>cactus</li>
<li>cortex</li>
<li>coyote</li>
<li>Erik</li>
<li>Etienne     </li>
<li>foxmask</li>
<li>golgotha</li>
<li>kontre</li>
<li>mraaaah</li>
<li>poulpe</li>
<li>recher</li>
</ul>
<p>Mais aussi tous ceux qui prennent le temps d&#8217;écrire des commentaires pertinents. Franchement, la qualité des commentaires sur ce blog est juste hallucinante.</p>
<p>J&#8217;espère que j&#8217;en oublie pas, sinon vous avez le droit de me fouetter :-)</p>
<p>Histoire de terminer sur une note de joie, j&#8217;ai mis à jour le <a href="http://sametmax.com/telechargez-le-blog-en-entier-pour-le-lire-hors-ligne/">dump du blog</a>, que vous pouvez <a href="https://github.com/sametmax/miroir-du-blog/archive/master.zip">télécharger ici sous forme de zip</a>.</p>
<p>Grâce à des gentils gens sur Twitter, le dump contient maintenant aussi un backup de tous nos tweets.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8150&amp;md5=7ec7040e585a45bf03b46f362e319cdd" 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=8164
title: Conséquences de print devenant une fonction en Python 3
uri: Conséquence-de-print-devenant-une-fonction-en-Python-3
url: http://sametmax.com/consequence-de-print-devenant-une-fonction-en-python-3/
content:
<p>Devoir utiliser <code>print()</code> au lieu de <code>print</code> m&#8217;arrache la gueule, je dois l&#8217;avouer. J&#8217;ai l&#8217;impression que ces deux parenthèses ma prennent 5 heures à taper, là où avant mon petit espace était à portée de pouce.</p>
<p>Mais évidement, la décision de faire de <code>print</code> une fonction est parfaitement rationnelle, et en voici tous les avantages&#8230;</p>
<h2><code>print</code> n&#8217;est plus une déclaration, mais une expression</h2>
<p>Il y a deux types d&#8217;instructions en Python : les déclarations (&#8216;statement&#8217; dans la langue de Chuck Norris) et les expressions.</p>
<p>Les déclarations sont des instructions indépendantes : <code>while</code>, <code>var = 'valeur'</code>, <code>try</code>, <code>def</code>, etc. On ne peut pas les mettre dans une expression, seulement les imbriquer dans une autre déclaration.</p>
<p>Les expressions, elles, sont imbricables dans n&#8217;importe quoi, et elles retournent toujours quelques chose quelque chose, fusse <code>None</code>. Parmis les expressions on retrouve : les lambdas, les listes en intentions, les appels de fonctions, etc.</p>
<p>Avant, <code>print</code> était une déclaration, ce qui était très peu souple. Maintenant, c&#8217;est un appel de fonction, et donc une expression.</p>
<p>On peut donc utiliser <code>print</code> dans une autre expression et ainsi :</p>
<p>Dans une <a href="http://sametmax.com/fonctions-anonymes-en-python-ou-lambda/">lambda</a> :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">crier = <span style="color: #ff7700;font-weight:bold;">lambda</span> x, <span style="color: #66cc66;">*</span>a, <span style="color: #66cc66;">**</span>k: <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>x.<span style="color: black;">upper</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, <span style="color: #66cc66;">*</span>a, <span style="color: #66cc66;">**</span>k<span style="color: black;">&#41;</span></pre></div></div>

<p>Dans une <a href="http://sametmax.com/python-love-les-listes-en-intention-partie/">liste en intention</a> :</p>

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

<h2>Plus de syntaxe bizarre</h2>
<p>Comment supprimer le saut de ligne quand on print avec l&#8217;ancienne syntaxe ?</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Hello&quot;</span>, <span style="color: #808080; font-style: italic;"># &lt;- notez la virgule</span>
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;You&quot;</span>
Hello You</pre></div></div>

<p>Avec la nouvelle syntaxe :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Hello &quot;</span>, end=<span style="color: #483d8b;">''</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;">'You'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Comment rediriger le print vers stderr avec l&#8217;ancienne syntaxe ?</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span> <span style="color: #dc143c;">sys</span>.<span style="color: black;">stderr</span>, <span style="color: #483d8b;">'arg !'</span></pre></div></div>

<p>Avec la nouvelle ?</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'arg !'</span>, <span style="color: #008000;">file</span>=<span style="color: #dc143c;">sys</span>.<span style="color: black;">stderr</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Comment faire une liste séparée par des virgules avec l&#8217;ancienne syntaxe ?</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> l = <span style="color: black;">&#91;</span><span style="color: #483d8b;">'Des petits trous'</span>, <span style="color: #483d8b;">'des petits trous'</span>, <span style="color: #483d8b;">'toujours des petits trous'</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">', '</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>l<span style="color: black;">&#41;</span>
Des petits trous, des petits trous, toujours des petits trous</pre></div></div>

<p>Avec la nouvelle ?</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #66cc66;">*</span>l, sep=<span style="color: #483d8b;">', '</span><span style="color: black;">&#41;</span></pre></div></div>

<p>En gros, la syntaxe est unifiée, plus besoin de penser à tous ces cas particuliers. Et en plus on peut demander de l&#8217;aide avec <code>help(print)</code> alors qu&#8217;avant ça faisait une syntaxe error.</p>
<h2>On peut récupérer une référence sur
<pre>print</pre>
</h2>
<p>Et donc la passer en paramètre pour faire de l&#8217;<a href="http://sametmax.com/quest-ce-quun-callback/">injection de dépendance</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>a, <span style="color: #ff7700;font-weight:bold;">print</span>=<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># faire un truc avec a</span>
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>a<span style="color: black;">&#41;</span><span style="color: #66cc66;">;</span> <span style="color: #808080; font-style: italic;"># on peut utiliser print normalement</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">logging</span>
log = loging.<span style="color: black;">getLogger</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
truc<span style="color: black;">&#40;</span>machin, <span style="color: #ff7700;font-weight:bold;">print</span>=log<span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># on print pas, on log !</span>
truc<span style="color: black;">&#40;</span>autre_machin, <span style="color: #ff7700;font-weight:bold;">print</span>=<span style="color: #ff7700;font-weight:bold;">lambda</span> <span style="color: #66cc66;">*</span>a, <span style="color: #66cc66;">**</span>k: <span style="color: #008000;">None</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># ignore les prints !</span></pre></div></div>

<p>Et également appliquer tous les outils de programmation fonctionnelle de Python :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">from</span> functools <span style="color: #ff7700;font-weight:bold;">import</span> partial
error = partial<span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">print</span>, <span style="color: #008000;">file</span>=<span style="color: #dc143c;">sys</span>.<span style="color: black;">stderr</span><span style="color: black;">&#41;</span>
error<span style="color: black;">&#40;</span><span style="color: #483d8b;">'Wrong !'</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># va directement sur stderr</span></pre></div></div>

<h2>Activer <code>print()</code> en Python 2.7</h2>
<p>Si vous voulez prendre toute de suite de bonnes habitudes, vous pouvez faire, en Python 2.7 :</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> print_function</pre></div></div>

 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8164&amp;md5=a05024d9531d9af8137f90e782c3a559" 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=7729
title: Ecrire une commande Django
uri: Ecrire-une-commande-Django
url: http://sametmax.com/ecrire-une-commande-django/
content:
<p>Quand vous avez à faire un script pour un projet Django, il est pratique de l&#8217;avoir sous forme de sous-commande de <code>manage.py</code> : c&#8217;est portable d&#8217;un projet à l&#8217;autre et ça permet d&#8217;utiliser l&#8217;ORM et les templates sans réglage puisqu&#8217;on a accès à tous les settings, automatiquement.</p>
<p>Malheureusement le wrapper de Django destiné à cela date un peu, il est plutôt lourd, pas très souple et utilise des pratiques qui ne sont plus au goût du jour depuis quelques années. Rien de rédhibitoire, mais tout de même.</p>
<p>D&#8217;abord, il faut placer sa commande dans un fichier portant le nom de la commande, et dans un package <code>management.commands</code> d&#8217;une de vos apps.</p>
<p>Par exemple, si vous voulez faire une commande &#8220;nettoyer_godmichets&#8221; dans l&#8217;application &#8220;sex_shop&#8221;, il faudra la mettre bien profondément dans le tréfonds de votre projet :</p>
<pre>racine
│   ├── sex_shop
│   │   ├── management
│   │   │   ├── commands
│   │   │   │   ├── nettoyer_godmichets.py
│   │   │   │   ├── __init__.py
│   │   │   │   └── __init__.pyc
│   │   │   ├── __init__.py</pre>
<p>Notez les fichiers <em>__init__.py</em>, indispendables sinon votre commande ne sera pas trouvée. Oh, et &#8216;sex_shop&#8217; doit être dans <code>INSTALLED_APPS</code>.</p>
<p>Ensuite, votre commande doit être une classe héritant de <code>BaseCommand</code>. Sa méthode <code>handle()</code> sera appelée automatiquement au lancement de la commande.</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;">core</span>.<span style="color: black;">management</span>.<span style="color: black;">base</span> <span style="color: #ff7700;font-weight:bold;">import</span> BaseCommand
<span style="color: #ff7700;font-weight:bold;">from</span> sex_shop.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> Godmichet
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Command<span style="color: black;">&#40;</span>BaseCommand<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: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>options<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">for</span> god <span style="color: #ff7700;font-weight:bold;">in</span> Godmichet.<span style="color: black;">objects</span>.<span style="color: #008000;">all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
            god.<span style="color: black;">clean</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Et vous pouvez lancer la commande :</p>

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

<p>Néanmoins généralement on voudra avoir un peu de décorum.</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> <span style="color: #dc143c;">optparse</span> <span style="color: #ff7700;font-weight:bold;">import</span> make_option
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">core</span>.<span style="color: black;">management</span>.<span style="color: black;">base</span> <span style="color: #ff7700;font-weight:bold;">import</span> BaseCommand
<span style="color: #ff7700;font-weight:bold;">from</span> sex_shop.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> Godmichet, Marque
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Command<span style="color: black;">&#40;</span>BaseCommand<span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;"># ici on peut mettre un message d'aide</span>
    <span style="color: #008000;">help</span> = <span style="color: #483d8b;">'Fait briller dard dard les dards'</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># optionellement une aide pour les arguments</span>
    args = <span style="color: #483d8b;">'marque1, [marque2], marque3'</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># On peut ajouter des options passables à la commande</span>
    option_list = BaseCommand.<span style="color: black;">option_list</span> + <span style="color: black;">&#40;</span>
        make_option<span style="color: black;">&#40;</span><span style="color: #483d8b;">'--dry-run'</span>,
            action=<span style="color: #483d8b;">'store_true'</span>,
            dest=<span style="color: #483d8b;">'dry_run'</span>,
            default=<span style="color: #008000;">False</span>,
            <span style="color: #008000;">help</span>=<span style="color: #483d8b;">'Affichage uniquement, aucune action réelle'</span><span style="color: black;">&#41;</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: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>options<span style="color: black;">&#41;</span>:
&nbsp;
        <span style="color: #808080; font-style: italic;"># on retrouve dans args les arguments positionnels de la commande</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> args:
            <span style="color: #ff7700;font-weight:bold;">for</span> god <span style="color: #ff7700;font-weight:bold;">in</span> Godmichet.<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;"># Plutôt que print(), on peut utiliser ce wrapper</span>
                <span style="color: #808080; font-style: italic;"># pour ecrire sur le terminal. Cela permet de bénéficier</span>
                <span style="color: #808080; font-style: italic;"># automatiquement de l'option --verbosity</span>
                <span style="color: #008000;">self</span>.<span style="color: black;">stdout</span>.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Processing %s'</span> <span style="color: #66cc66;">%</span> god.<span style="color: black;">name</span><span style="color: black;">&#41;</span>
&nbsp;
                <span style="color: #808080; font-style: italic;"># La valeur des options est passée via kwargs.</span>
                <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> options<span style="color: black;">&#91;</span><span style="color: #483d8b;">'dry_run'</span><span style="color: black;">&#93;</span>:
                    god.<span style="color: black;">clean</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            <span style="color: #808080; font-style: italic;"># l'utilisateur a passé des marques ? On nettoie que les gods</span>
            <span style="color: #808080; font-style: italic;"># de ces marques...</span>
            <span style="color: #ff7700;font-weight:bold;">for</span> marque <span style="color: #ff7700;font-weight:bold;">in</span> args:
                <span style="color: #ff7700;font-weight:bold;">try</span>:
                    gods = Marque.<span style="color: black;">objects</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span>name=marque<span style="color: black;">&#41;</span>.<span style="color: black;">gods</span>.<span style="color: #008000;">all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
                    <span style="color: #ff7700;font-weight:bold;">for</span> god <span style="color: #ff7700;font-weight:bold;">in</span> gods:
                        <span style="color: #008000;">self</span>.<span style="color: black;">stdout</span>.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Processing %s'</span> <span style="color: #66cc66;">%</span> god.<span style="color: black;">name</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> options<span style="color: black;">&#91;</span><span style="color: #483d8b;">'dry_run'</span><span style="color: black;">&#93;</span>:
                            god.<span style="color: black;">clean</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
                <span style="color: #ff7700;font-weight:bold;">except</span> Marque.<span style="color: black;">DoesNotExist</span>:
                    <span style="color: #808080; font-style: italic;"># si la marque n'existe pas, on fait une erreur</span>
                    <span style="color: #808080; font-style: italic;"># ceci arrête le script, retourne un code d'erreur 1</span>
                    <span style="color: #808080; font-style: italic;"># et met le texte en rouge</span>
                    <span style="color: #ff7700;font-weight:bold;">raise</span> CommandError<span style="color: black;">&#40;</span><span style="color: #483d8b;">'La marque %s n'</span>existe pas<span style="color: #483d8b;">' %s marque)</span></pre></div></div>

<p>Et voilà, votre commande accepte maintenant optionnellement qu&#8217;on lui passe une liste de marques et/ou une option <code>--dry-run</code>:</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 nettoyer_godmichet devilmaycry choucroutebestfriend <span style="color: #660033;">--dry-run</span></pre></div></div>

<p>En plus de ça, la commande accepte automatiquement :</p>
<ul>
<li><code>--help</code></li>
<li><code>--verbosity</code></li>
<li><code>--settings</code></li>
<li><code>--pythonpath</code></li>
</ul>
<p>Qui ont le même effet que sur toutes les commandes django officielles.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7729&amp;md5=e5a09ee82a859a49b547ebb46111ce2a" 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=8160
title: En Python 3, le type bytes est un array d’entiers
uri: En-Python-3-le-type-bytes-est-un-array-d-entiers
url: http://sametmax.com/en-python-3-le-type-bytes-est-un-array-dentiers/
content:
<p>Le plus gros changement quand on passe de Python 2 à Python 3, c&#8217;est la gestion des chaînes de caractères.</p>
<p>Pour rappel :</p>
<ul>
<li>En 2.7, les chaînes sont par défaut des arrays d&#8217;octets, et il faut les décoder pour obtenir de l&#8217;unicode.</li>
<li>En 3, les chaînes sont par défaut de type &#8216;unicode&#8217;, et il faut les encoder pour obtenir de un array d&#8217;octets.</li>
</ul>
<p>Si vous avez besoin d&#8217;une mise à jour sur l&#8217;encoding en Python, on <a href="http://sametmax.com/lencoding-en-python-une-bonne-fois-pour-toute/">a un article pour ça</a>.</p>
<p>Comme toute entrée ou sortie est forcément un flux d&#8217;octets, mais pas forcément dans le même encodage, Python 2.7 pouvait poser problème pour le débutant qui essayait de comprendre pourquoi son programme plantait, bordel de merde.</p>
<p>La version 3 prend plusieurs mesures pour éviter les bugs vicieux liés à l&#8217;encodage de caractères:</p>
<ul>
<li>L&#8217;encodage par défaut du code est UTF8.</li>
<li>L&#8217;encodage par défaut de lecture et d&#8217;écriture est UTF8.</li>
<li>On ne peut plus mélanger &#8216;bytes&#8217; et &#8216;unicode&#8217;.</li>
<li>Les messages d&#8217;erreur expliquent clairement et tôt tout problème.</li>
</ul>
<p>La plupart du temps, quand on va manipuler du texte, on va donc toujours manipuler de l&#8217;unicode, en Python 3. Ce dernier va nous forcer à faire le décodage / encodage au bon moment.</p>
<p>Mais il restera quelques fois le besoin de manipuler du <code>bytes</code>, et ce type a subi un lifting&#8230;</p>
<h2>La base</h2>
<p>Créer un array d&#8217;octets (le type <code>bytes</code>&#8216;, en Python 3) demande de préfixer une chaîne avec &#8216;b&#8217; :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> s = b<span style="color: #483d8b;">'I am evil, stop laughing!'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>s<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>class <span style="color: #483d8b;">'bytes'</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>s<span style="color: black;">&#41;</span>
b<span style="color: #483d8b;">'I am evil, stop laughing!'</span></pre></div></div>

<p>Première remarque, on ne peut plus utiliser ce type pour afficher quoi que ce soit, puisque l&#8217;affichage est une représentation du type (appel à <code>__repr__</code>), et pas du texte mis en forme. Déjà Python vous indique la couleur : si vous voulez manipulez du texte, n&#8217;utilisez pas ce type.</p>
<p>Comparez avec le type unicode :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> u = s.<span style="color: black;">decode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'utf8'</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>u<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>class <span style="color: #483d8b;">'str'</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>u<span style="color: black;">&#41;</span>
I am evil, stop laughing<span style="color: #66cc66;">!</span></pre></div></div>

<p>L&#8217;affichage marche comme on s&#8217;y attend. Bref, vous êtes forcé de toujours rester sur de l&#8217;unicode (le type <code>str</code> en Python 3, ce qui porte à confusion) si vous manipulez du texte. Heureusement, c&#8217;est quasiment toujours ce que vous aurez.</p>
<p>Par exemple, si vous ouvrez un fichier en Python 3 :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> content = <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: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>content<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>class <span style="color: #483d8b;">'str'</span><span style="color: #66cc66;">&gt;</span></pre></div></div>

<p>C&#8217;est du texte. A moins de demander qu&#8217;il soit ouvert en mode binaire :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;&gt;</span> content = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/etc/fstab'</span>, <span style="color: #483d8b;">'rb'</span><span style="color: black;">&#41;</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>content<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>class <span style="color: #483d8b;">'bytes'</span><span style="color: #66cc66;">&gt;</span></pre></div></div>

<p>Une autre différence MAJEURE, c&#8217;est que, si dans Python 2.7, les arrays d&#8217;octets pouvaient être manipulés comme un array de lettres :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> s = <span style="color: #483d8b;">'I put the goal in golem...'</span> 
<span style="color: #66cc66;">&gt;&gt;&gt;</span> s<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> <span style="color: #808080; font-style: italic;"># en Python 2.7</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">'I'</span></pre></div></div>

<p>En Python 3, les array d&#8217;octets sont au mieux manipulables comme un array d&#8217;entiers :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> s = b<span style="color: #483d8b;">'I put the goal in golem...'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> s<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> <span style="color: #808080; font-style: italic;"># en Python 3</span>
<span style="color: #ff4500;">73</span></pre></div></div>

<p>La représentation sous forme de lettre est gardée pour l&#8217;initialisation pour des raisons pratiques, mais sous le capot, il se passe ç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: #dc143c;">bytes</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">73</span>, <span style="color: #ff4500;">32</span>, <span style="color: #ff4500;">112</span>, <span style="color: #ff4500;">117</span>, <span style="color: #ff4500;">116</span>, <span style="color: #ff4500;">32</span>, <span style="color: #ff4500;">116</span>, <span style="color: #ff4500;">104</span>, <span style="color: #ff4500;">101</span>, <span style="color: #ff4500;">32</span>, <span style="color: #ff4500;">103</span>, <span style="color: #ff4500;">111</span>, <span style="color: #ff4500;">97</span>, <span style="color: #ff4500;">108</span>, <span style="color: #ff4500;">32</span>, <span style="color: #ff4500;">105</span>, <span style="color: #ff4500;">110</span>, <span style="color: #ff4500;">32</span>, <span style="color: #ff4500;">103</span>, <span style="color: #ff4500;">111</span>, <span style="color: #ff4500;">108</span>, <span style="color: #ff4500;">101</span>, <span style="color: #ff4500;">109</span>, <span style="color: #ff4500;">46</span>, <span style="color: #ff4500;">46</span>, <span style="color: #ff4500;">46</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
b<span style="color: #483d8b;">'I put the goal in golem...'</span></pre></div></div>

<p>D&#8217;ailleurs, on ne peut même plus faire d&#8217;opérations de formatage avec des octets comme en Python 2.7 :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> b<span style="color: #483d8b;">&quot;Welcome to the league of %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">input</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span><span style="color: black;">&#41;</span>
Draven
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&lt;stdin&gt;&quot;</span>, line <span style="color: #ff4500;">1</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #66cc66;">&lt;</span>module<span style="color: #66cc66;">&gt;</span>
<span style="color: #008000;">TypeError</span>: unsupported operand <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>s<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> <span style="color: #66cc66;">%</span>: <span style="color: #483d8b;">'bytes'</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #483d8b;">'str'</span></pre></div></div>

<p><code>format()</code> ne marche pas non plus. On est assez proche du tableau d&#8217;octets en C, sauf qu&#8217;en plus, on ne peut pas le modifier :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> s = b<span style="color: #483d8b;">&quot;My right arm is a lot stronger than my left arm.&quot;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> s<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> = <span style="color: #ff4500;">1</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&lt;stdin&gt;&quot;</span>, line <span style="color: #ff4500;">1</span>, <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #66cc66;">&lt;</span>module<span style="color: #66cc66;">&gt;</span>
<span style="color: #008000;">TypeError</span>: <span style="color: #483d8b;">'bytes'</span> <span style="color: #008000;">object</span> does <span style="color: #ff7700;font-weight:bold;">not</span> support item assignment</pre></div></div>

<p>Les arrays d&#8217;octets sont donc maintenant essentiellement des outils de communication avec le monde extérieur.</p>
<h2>Bytearray</h2>
<p>Il existe encore des raisons de manipuler des arrays d&#8217;octets : les applications scientifiques. Typiquement, les algos de crypto opérent sur des arrays d&#8217;octets.</p>
<p>Pour cette raison, Python 3 vient également avec un nouveau type de base : <code>bytearray</code>, un array d&#8217;octets modifiable.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> s = <span style="color: #dc143c;">bytearray</span><span style="color: black;">&#40;</span>b<span style="color: #483d8b;">&quot;this tasted purple !&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> s<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span>:<span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span> = b<span style="color: #483d8b;">'at'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>s<span style="color: black;">&#41;</span>
<span style="color: #dc143c;">bytearray</span><span style="color: black;">&#40;</span>b<span style="color: #483d8b;">'that tasted purple !'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Et on a toutes les opérations de liste dessus, comme <code>append</code>, <code>pop()</code>, etc :</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> b<span style="color: #483d8b;">' ,puY'</span>:
...     <span style="color: black;">s</span>.<span style="color: black;">insert</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, x<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>s<span style="color: black;">&#41;</span>
<span style="color: #dc143c;">bytearray</span><span style="color: black;">&#40;</span>b<span style="color: #483d8b;">'Yup, that tasted purple !'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Attention par contre, ces opérations attendent un entier en paramètres et NON un array d&#8217;octets.</p>
<p>Et un dernier détail :</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;">isinstance</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">bytes</span>, <span style="color: #dc143c;">bytearray</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">False</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">bytearray</span>, <span style="color: #dc143c;">bytes</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">False</span></pre></div></div>

<h2>Différence entre string et array d&#8217;octets</h2>
<p>Il est facile de confondre tout ce merdier.</p>
<p>En Python 2.7, le type <code>str</code> était un array d&#8217;octets, et on le manipulait comme une chaîne, d&#8217;où la difficulté de transition.</p>
<p>En Python 3, bien qu&#8217;on puisse créer un array d&#8217;octets avec une syntaxe utilisant des lettres, ils ne sont plus du tout utilisés pour la manipulation de texte. Si vous voulez manipuler du texte qui vient de l&#8217;extérieur de votre programme, il faudra toujours le décoder pour obtenir un type <code>str</code> (qui est l&#8217;ancien type <code>unicode</code> de Python 2.7).</p>
<p>Le décodage sera fait automatiquement dans la plupart des cas, et plantera si on tombe sur un cas où vous devez le faire à la main et que vous ne le faites pas. Du coup, plus de difficulté à trouver d&#8217;où vient ce bug d&#8217;encoding, car on a toujours l&#8217;erreur à la source. </p>
<p>En ce sens, Python 3 est beaucoup plus clair : les octets d&#8217;un côté, le texte de l&#8217;autre. Bon, tout ça c&#8217;est de la surcouche, au final, tout est octet. Mais on a rarement envie de manipuler un octet directement, sinon on coderait encore en assembleur.</p>
<p>Avec ce système, Python 3 est le langage le plus sain que j&#8217;ai pu rencontrer dans sa gestion de l&#8217;encodage : il ne cache rien, oblige l&#8217;utilisateur à coder avec de bonnes habitudes, facilite le débugage et met sur le devant de la scène la problématique de l&#8217;encoding, qui est le plus souvent cachée vite fait sous le tapis.</p>
<p>L&#8217;alternative intelligente la plus proche étant celle de node.js, qui <a href="https://github.com/joyent/node/blob/master/lib/buffer.js#L126">interdit tout simplement la plupart des encodings dans son API</a>.</p>
<p>La bonne nouvelle ? 99% du temps, vous n&#8217;aurez même pas à vous en soucier, car ASCII est inclus dans UTF8, et ce sont les encodings les plus utilisés. Avec Python 3 forçant UTF8 par défaut partout et des chaînes en unicode dès le départ, il n&#8217;y a presque rien à faire. Je doute que la plupart des gens aient même à manipuler le type <code>bytes</code>.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8160&amp;md5=71b1c2304c867db19a765d673fbf002f" 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=8177
title: Introduction à Ansible: l’outil du sysadmin paresseux mais pragmatique
uri: Introduction-à-Ansible-l-outil-du-sysadmin-paresseux-mais-pragmati
url: http://sametmax.com/introduction-a-ansible-loutil-du-sysadmin-paresseux-mais-pragmatique/
content:
<p style="text-align: center;"><em><small>Ceci est un post invité de <a href="http://sametmax.com/author/VonTenia/">VonTenia</a> posté sous licence <a href="http://creativecommons.org/licenses/by/3.0/">creative common 3.0 unported</a>.</small></em></p>
<p>Je profite du fait que Sam &#038; Max me donnent la parole pour vous parler d’Ansible, un programme très puissant et relativement simple dont je me sers depuis récemment (beaucoup trop tardivement à mon goût), mais qui a radicalement changé ma façon de gérer mes déploiements d’appli sur serveur.</p>
<p><strong>Avant-propos</strong> : Ce guide s’adresse avant tout à ceux et celles ayant le minimum d’aisance avec les systèmes linux. Je pense qu’il est nécessaire de savoir marcher avant d’apprendre à courir, l’automatisation de configuration est une bonne chose (vous allez voir que vous ne pourrez plus vous en passer), mais si vous n’avez aucune idée de comment éditer un fichier de configuration, ou comment redémarrer un service, vous risqueriez bien d&#8217;être pris au dépourvu&#8230; Mieux vaut alors pour vous commencer par apprendre les bases de l’administration système puis revenir une fois à l’aise avec le concept.</p>
<h3>Pourquoi utiliser un “Configuration Management Tool”</h3>
<p>Vous vous dites : mon boulot c’est de coder, l’administration système c’est sympa 5 minutes mais ça me gonfle… Et pourtant, au final votre application sera accédée via vos serveurs, et selon leur fragilité, la satisfaction de vos clients pourrait en pâtir (ce malgré votre excellent code parfaitement testé).</p>
<p>En tant que dev, il serait risible pour vous de ne pas versionner votre code ou ne pas le tester. Pourtant c’est ce que vous faites avec vos systèmes en n’utilisant pas de CfM. Et personne n’est à l&#8217;abri des aléas de la vie, par exemple:</p>
<ul>
<li>vous êtes hébergé dans le cloud et votre voisin d’hyperviseur s&#8217;avère maintenir un site Tor de trafic d’organes et de prostitution animalière (tout ça pour blanchir des bitcoins)… Vous apprécierez moyennement le downtime lorsque le FBI saisira le serveur que vous partagiez avec cet indélicat voisin.</li>
<li>Votre sysadmin ultra compètent pourrait se trouver dans l&#8217;incapacité d’exercer à la suite d’une banale auto-asphyxie érotique qui aurait mal tournée. Et bien évidemment il n’a rien documenté avant, le saligaud…</li>
</ul>
<p>Bref, le genre de risque qu&#8217;on apprend à identifier quand on passe sa certif ITIL&#8230;</p>
<h3>Les alternatives aux CfM</h3>
<p>Je vous vois venir, me disant que vous ne m’avez pas attendu pour envisager les situations précédentes. Vous avez déjà un plan de secours, à savoir :</p>
<ul>
<li>
<p><strong>Des scripts :</strong> Si vous êtes déjà un peu plus malin que la moyenne, vous vous êtes aperçu que pour déployer une nouvelle machine, vous tapez toujours les mêmes commandes : installer vos packages, les configurer, démarrer les services. Vous aurez donc votre collection de scripts shell ou fabric pour vous aider à la tâche.</p>
<p>Inconvénient : il faut être très organisé, gérer les différents fichiers de config peut prendre du temps lorsqu’il faut les modifier pour chaque serveur. Il est aussi parfois dangereux de relancer le script plusieurs fois sur la même machine, cela peut avoir des conséquences pour le moins hasardeuses.</p>
</li>
<li>
<p><strong>Une image disque :</strong> Une fois votre serveur configuré et parfaitement fonctionnel, vous avez pris soin d’en prendre une image disque. Le saint Graal de la prod, contenant la vérité absolue. En cas de crash vous serez opérationnel en un rien de temps.</p>
<p>Inconvénient : Les besoins de votre application vont évoluer avec le temps, les fichiers de configuration auront probablement changé aussi. A chaque changement vous devez refaire votre image… Ça devient assez lourd à la longue, et c’est facile d’oublier de le faire jusqu’au jour où “the shit hit the fan”.</p>
</li>
<li>
<p><strong>Rien (ou presque) :</strong> Si vous êtes comme moi, d’un naturel optimiste, vous n’avez quasiment pas de solution de secours (à part des backups). Le jour ou votre serveur crash, vous essayez de fixer le problème, et au pire vous en re-configurez un nouveau, ce qui vous prends entre 2 heures et 2 jours, en fonction de la dernière fois où vous avez eu à le faire (je n’ai jamais prétendu être un sysadmin très compètent&#8230;). Sans aller jusqu’au crash irrécupérable, le simple fait de vouloir changer d’hébergeur peut vous faire perdre un temps précieux. Vous perdez donc en flexibilité.</p>
<p>Inutile de vous dire que si vous faites parti de cette catégorie, je vous invite d’autant plus à continuer de lire.</p>
</li>
</ul>
<h3>Ansible à votre secours</h3>
<p>Ansible est un outil open-source de gestion de configuration écrit en python (aussi dispo en version commerciale avec une interface graphique et un service de déploiement). La configuration se fait via des fichiers appelés “Playbooks”. Citons parmi les avantages :</p>
<ul>
<li>Un système déclaratif : syntaxe YAML facilement lisible, ce qui rend l’apprentissage très rapide (plus qu’avec Chef à mon goût, où l’on s&#8217;empêtre très vite dans des problèmes de dépendance, et en plus je ne suis pas très fluent en ruby).</li>
<li>Templating des fichiers de configuration : qui permet d’avoir des fichiers dynamiquement générés en fonction de ce que vous voulez, tel que le rôle du serveur, ou bien dépendant d’un autre serveur. En plus le langage de template par défaut est Jinja2, ça plaira aux amateurs de Django.</li>
<li>Quasiment rien à installer. A part Ansible sur votre machine hôte, tout ce dont vous avez besoin c’est d’un accès root via SSH sur vos serveurs cibles.</li>
</ul>
<p>Ansible ne sert pas qu’à déployer votre infrastructure, il peut aussi servir à tester et s’assurer que tous les services qui sont censés fonctionner soient bien tous actifs, et que tous les fichiers de configurations sont bien à jour. Autant vous dire que plus vous avez de machines, plus ça devient intéressant.</p>
<p>Je sens que j&#8217;écris beaucoup et que j’ai déjà perdu la moitié des lecteurs. Aussi je vous invite à suivre ce petit tutoriel que j’ai préparé rien que pour vous parce que vous êtes quand même sympa.</p>
<h3>Tutoriel : Déployer une app django</h3>
<p>Nous allons essayer de déployer l’application <a href="https://github.com/sametmax/Django--an-app-at-a-time">Django&#8211;an-app-at-a-time</a> sur un système Debian wheezy en utilisant Ansible.</p>
<h4>1. Préparer la machine cible</h4>
<p>Pour les besoins du test, créer un serveur tout neuf sous Debian Wheezy :</p>
<ul>
<li>Soit en utilisant Virtualbox (dans ce cas utilisez <a href="http://www.debian.org/CD/netinst/">Debian netinstall</a>). N&#8217;installez que le système de base et le serveur SSH. Seul impératif: un accès ssh via root sur la machine.</li>
<li>Si vous avez les moyens, vous pouvez aussi vous créer temporairement une machine cloud sur OVH ou digital ocean, ça pourrait être plus rapide.</li>
</ul>
<h4>2. Installer Ansible</h4>
<p>Sur votre machine hôte (que j’assume être sous Ubuntu pour simplifier):</p>
<p>
Installez Ansible, via pip (de façon globale sans passer par virtualenv) :<br />
<code>$ sudo pip install ansible</code></p>
<p>Générez clefs privée/publique si vous n’en avez pas déjà :<br />
<code>$ ssh-keygen</code></p>
<p>Copiez la clef publique sur le serveur cible (qui sera désigné par 192.168.1.1 dans ce tutoriel, mais bien entendu remplacez par l’adresse de votre serveur cible).<br />
<code>$ ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.1.1</code></p>
<p>Créez le fichier <strong>/etc/ansible/hosts</strong> qui contiendra la liste des serveurs à gérer, et placez-y l&#8217;adresse de votre serveur:<br />
<code>$ sudo vim /etc/ansible/hosts</code><br />
<code>192.168.1.1</code></p>
<p>Testez que le serveur soit bien accessible:<br />
<code>$ ansible all -m ping -u root </code><br />
devrait retourner:<br />
<code>192.168.1.1 | success >> {<br />
    "changed": false,<br />
    "ping": "pong"<br />
}</code></p>
<p>Bravo, Ansible est installé et peut communiquer avec votre serveur cible. En avant pour la magie !</p>
<p><img src="media/1cacfe5f.its-Magic.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/12/its-Magic.gif" alt="" title="its-Magic" width="350" height="196" class="alignnone size-full wp-image-8192" /><br />

</p>
<h4>3. Récupérer le Playbook de démo et l&#8217;exécuter</h4>
<p>Clonez mon repo github concocté avec amour et exécutez le playbook:</p>
<p><code>$ git clone https://github.com/Remiz/playbook-demo.git<br />
$ cd playbook-demo/<br />
$ ansible-playbook site.yml</code></p>
<p>Maintenant, plus qu&#8217;à attendre&#8230;</p>
<p><img src="media/68dfe1b0.cookie-monster.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/12/cookie-monster.gif" alt="" title="cookie monster is waiting..." width="250" height="143" class="alignnone size-full wp-image-8203" /></p>
<h4>3. Admirer le résultat</h4>
<p>Visitez le site hébergé à l’adresse de votre serveur (dans mon exemple <a href="http://192.168.1.1">http://192.168.1.1</a>)</p>
<p>Votre réaction la plus normale devrait être la suivante :</p>
<p><img src="media/523ae907.areyouawizard.png" data-original-source="http://sametmax.com/wp-content/uploads/2013/12/areyouawizard.png" alt="" title="areyouawizard" width="200" height="259" class="alignnone size-full wp-image-8209" /></p>
<p>Je vous invite maintenant à ouvrir le playbook <a href="https://github.com/Remiz/playbook-demo/blob/master/site.yml">site.yml</a> et essayer de comprendre. Durant ce court laps de temps, nous avons:</p>
<ul>
<li>Créé un utilisateur “myproject”</li>
<li>Ajouté cet utilisateur aux sudoers</li>
<li>Ajouté votre clef privée locale</li>
<li>Mis a jour la date du serveur</li>
<li>Installé/activé le serveur NTP</li>
<li>Sécurisé le serveur en installant fail2ban et en configurant le firewall iptables (laissant ouvert les ports 22, 80, 443 et 4949 pour le monitoring sous munin)</li>
<li>Installé quelques outils systèmes bien utiles tel que git ou htop</li>
<li>Installé/configuré Nginx, Supervisor, Pip, virtualenv</li>
<li>Cloné le repo Django&#8211;an-app-at-a-time</li>
<li>Créé un virtualenv avec django/gunicorn</li>
<li>Configuré gunicorn pour être lancé via supervisor</li>
<li>et finalement deployé les fichiers statiques&#8230;</li>
</ul>
<p>Pas mal en 5 minutes, non ? Maintenant si vous ne me croyez pas, je vous invite à vous connecter sur votre serveur</p>
<p><code>$ ssh myproject@192.168.1.1</code></p>
<p>et tester les commandes suivantes :</p>
<p><code>$ date<br />
$ sudo iptables -L<br />
$ ps -ef | grep fail2ban<br />
$ ps -ef | grep gunicorn</code></p>
<p>Notez que je n’ai pas utilisé runserver de Django, tout est proprement déployé sur une stack gunicorn/supervisor/virtualenv, bref je me suis pas foutu de votre gueule. Le Playbook est à vous, c’est cadeau. J&#8217;espère qu’il vous servira comme base pour vos futurs déploiements, et si jamais vous vous rendez compte que vous gagnez un temps fou à l&#8217;utiliser, n&#8217;hésitez pas à me payer une pinte si vous êtes de passage au Canada.</p>
<p>Une autre expérience intéressante consiste à relancer l&#8217;exécution du playbook :</p>
<p><code>$ ansible-playbook site.yml</code></p>
<p>Tout devrait aller beaucoup plus vite, et à la place de “changed” après chaque instruction, vous devriez lire “ok”. Ce qui veut dire qu’un playbook est plus intelligent qu’un bête script, et ne se contente pas d&#8217;exécuter des instructions, Ansible va garantir quel tel service soit bien actif et qu’il utilise bien le dernier fichier de conf. Ce qui en fait l’outil parfait pour tester vos systèmes automatiquement.</p>
<h3>La syntaxe Playbook</h3>
<p>Le but de ce tutoriel n’est que de vous présenter Ansible, aussi je ne rentrerai pas trop dans les détails et je vous inviterai à vous rendre sur le site officiel pour une <a href="http://www.ansibleworks.com/docs/">documentation</a> plus complète.</p>
<p>Un playbook est avant tout composé de tâches :</p>
<p><code>- name: Texte qui décris votre tâche<br />
    module: option=value</code></p>
<p>Une tâche va donc appeler un <a href="http://www.ansibleworks.com/docs/modules.html">module</a> Ansible, dont la fonction peut être de copier un fichier, démarrer un service, clôner un repository… Il y en a vraiment beaucoup. Chaque module reçoit des paramètres tels que : un fichier de configuration source (sur votre machine hôte), un path de destination, un package apt à installer… Référez vous à la doc pour savoir quels paramètres sont acceptés.</p>
<p>Exemples :</p>
<p><code>- name: Démarrer fail2ban<br />
    service: name=fail2ban state=started enabled=true</code></p>
<p>va s’assurer que le service appelé fail2ban soit bien démarré (le démarrer si ce n’est pas le cas), mais aussi s’assurer qu’il soit bien présent au démarrage du système. Quand je vous disait que la syntaxe est très simple (même plus simple qu’avec des scripts shell).</p>
<p>Autre exemple:</p>
<p><code>- name: Configurer Nginx<br />
          template: src=templates/nginx.conf.j2<br />
          dest=/etc/nginx/sites-enabled/{{ user }}.conf<br />
notify: restart nginx</code></p>
<p>se traduit par : récupérer le template de conf dans le répertoire local templates/ (le parser avec les bonnes valeurs), et placer le résultat dans le répertoire de conf de Nginx (en utilisant le nom d’utilisateur comme nom du fichier). Enfin redémarrer nginx via un handler (uniquement si le contenu du fichier de conf a changé).</p>
<h3>Conclusion (et aller plus loin)</h3>
<p>Je vous conseille de lire la documentation officielle, elle est plutôt bien faite, dites-vous que je ne connaissais pas du tout cet outil il y a deux semaines et je m’en sert désormais régulièrement (et je suis du genre slow-learner). Renseignez vous particulièrement sur les <a href="http://www.ansibleworks.com/docs/playbooks_roles.html#id5">rôles</a> que vous pouvez donner à vos serveurs, ce qui vous permet de diviser vos playbooks (frontend, cluster DB, worker celery…), et ce qui encourage aussi la réutilisation (par exemple j’ai toujours un rôle “common” qui inclus tout ce qui est nécessaire à l&#8217;ensemble de mes serveurs : utilisateur admin, sécurité, timezone…). Comme on n’apprend jamais aussi bien que par l’exemple, n&#8217;hésitez pas à vous inspirer des <a href="https://github.com/ansible/ansible-examples">exemples</a> issus de la doc (l’outil évolue vite et certains ne sont plus entièrement valides, mais c’est toujours bon à prendre).</p>
<p>Si vous voulez pousser l’automatisation jusqu&#8217;à l&#8217;extrême, il est aussi possible de configurer Ansible sur vos serveurs pour se connecter à un repo git, récupérer les playbooks et fichiers de conf appropriés et s’auto-configurer&#8230;</p>
<p>Voila, mon rôle s&#8217;arrête ici et libre à vous d’en apprendre plus. Au final j&#8217;espère avoir tenu ma promesse d&#8217;éclairer vos esprit sur les miracles de l’automatisation.</p>
<p><img src="media/05cbc3ad.mind-blown1.gif" data-original-source="http://sametmax.com/wp-content/uploads/2013/12/mind-blown1.gif" alt="" title="mind-blown" width="200" height="200" class="alignnone size-full wp-image-8212" /></p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8177&amp;md5=0929d9232ef6125d29da5de891ac4d52" 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=8245
title: Petite astuce d’unpacking en Python
uri: Petite-astuce-d-unpacking-en-Python
url: http://sametmax.com/petite-astuce-dunpacking-en-python/
content:
<p>L&#8217;<a href="http://sametmax.com/operateur-splat-ou-etoile-en-python/">unpacking</a>, fonction géniale de Python s&#8217;il en est, peut se faire sur un seul element :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> a = <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> b, = a
<span style="color: #66cc66;">&gt;&gt;&gt;</span> b
<span style="color: #ff4500;">1</span></pre></div></div>

<p>Pour cet exemple, pas super utile. Par contre dans une boucle :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> l = <span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</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: 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;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">for</span> i, <span style="color: #ff7700;font-weight:bold;">in</span> l:
...     <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#41;</span>
...     
<span style="color: #ff4500;">1</span>
<span style="color: #ff4500;">1</span>
<span style="color: #ff4500;">1</span></pre></div></div>

 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8245&amp;md5=b6c322772bea30ecaf2728f2b4e40409" 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=8269
title: Anecdotes sexuelles à travers le monde
uri: Anecdotes-sexuelles-à-travers-le-monde
url: http://sametmax.com/anecdotes-sexuelles-a-travers-le-monde/
content:
<p>Franchement c&#8217;était mal parti. Je voulais écrire un article de cul ce matin, mais malgré un dépassement de nos <a href="http://sametmax.com/129-drafts/">129 drafts</a> (oui, ça continue à augmenter&#8230;), j&#8217;avais envie de rien.</p>
<p>J&#8217;ai demandé à Max si il avait fini son retour d&#8217;expérience sur l&#8217;épilation permanente des poils des couilles, mais il a laissé la machine en France sans avoir pu terminer ses séances. Du coup, c&#8217;est pas concluant. Un indice toute de même : ça fait mal.</p>
<p>Et puis je suis tombé sur ça :</p>
<div id="attachment_8270" class="wp-caption aligncenter" style="width: 523px"><a href="media/42746c93.1t4lgDS.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/12/1t4lgDS.jpg"><img src="media/42746c93.1t4lgDS.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/12/1t4lgDS.jpg" alt="Photo d&#039;une manif &quot;we want porn in iraq&quot;" title="La cruauté de l&#039;homme n&#039;a-t-elle donc pas de limite ?" width="513" height="627" class="size-full wp-image-8270" /></a><p class="wp-caption-text">La cruauté de l&#039;homme n&#039;a-t-elle donc pas de limite ?</p></div>
<h2>Et ça a fait tilt</h2>
<p>Je péroquette, mais Max et moi on a pas mal voyagé. Et j&#8217;ai pu voir pas mal de manières différentes d&#8217;aborder la sexualité. Par exemple il est très difficile de baiser dans certains pays. </p>
<p>Que quelqu&#8217;un m&#8217;éclaire, impossible de coucher avec une indienne (je ne parle pas de prostitution, bien entendu). Je suis arrivé jusqu&#8217;à boire un verre. J&#8217;ai eu tous les signes d’intérêts possibles, mais impossible d&#8217;aller plus loin. Je dois être complètement à côté de la plaque sur le marché indien.</p>
<p>Il y a aussi bien évidement, le Japon. On vous avait déjà parlé de l&#8217;espèce de dichotomie qu&#8217;il y a entre une part de la population japonaise super inhibée (mon frère en revient, et j&#8217;ai des amis qui y ont vécu qui en témoignent) et la <a href="http://sametmax.com/les-japonais-et-le-sexe-des-gros-malades-ou-pas/">représentation pornographique qui peut en être faite</a>. </p>
<p>Apparemment, il y a un pan de la population, appelé &#8220;herbivore&#8221;, qui est <a href="http://fortune.fdesouche.com/327861-japon-une-generation-dherbivores-asexues">complètement asexuée</a>. Pourtant les témoignages que j&#8217;en ai, c&#8217;est qu&#8217;il y aussi un monde de la nuit particulièrement décontracté sur le sujet.</p>
<p>Mais je ne parle pas ici d&#8217;expérience, puisque je n&#8217;y suis pas encore allé en personne.</p>
<h2>Par contre, ce qui m&#8217;a bluffé, c&#8217;est l&#8217;Afrique</h2>
<p>Par exemple, en Algérie, le sexe est super taboo. Du coup, quand j&#8217;entrais dans les cyber café, je voyais que des mecs sur des sites pornos.</p>
<p>Et uniquement sur ça :</p>
<div id="attachment_8271" class="wp-caption aligncenter" style="width: 460px"><a href="media/c322cc74.4.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/12/4.jpg"><img src="media/c322cc74.4.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2013/12/4.jpg" alt="Photo d&#039;une jeune femme blonde utilisant une godmichet" title="Avec le voile, ça rend moins bien il faut avouer" width="450" height="300" class="size-full wp-image-8271" /></a><p class="wp-caption-text">Avec le voile, ça rend moins bien il faut avouer</p></div>
<p>Des blanches, blondes.</p>
<p>Rien d&#8217;autre. Pas l&#8217;actu. Pas de jeux flash. Même pas facebook.</p>
<p>Du cul, partout, sur tous les postes.</p>
<p>Au mali, j&#8217;ai donné un cours de Python avec un de mes exercices habituels : un téléchargeur d&#8217;image pornos. Je sais, je suis un super prof.</p>
<p>Cet exercice passe super bien en Europe, mais là, choc culturel, les mecs ont rougi. Si si, rougi. Un noir qui rougi, c&#8217;est trop choupinet.</p>
<p>On parle du même pays qui a pour coutume d&#8217;enfermer les jeunes mariés pendant une semaine dans leur chambre. Enfermer. Je le promet. Ils sont nourris par un membre de la famille, et ne sortent pas avant la fin de la lune de miel.</p>
<p>Mon collègue marié sur place m&#8217;a confié qu&#8217;il avait pris ses précautions avec wifi + DVD&#8230;</p>
<p>En Uganda, un soir à mon hôtel, je commande, tard, un coca. Apparemment, ça doit être un mot de passe pour &#8220;envoyez moi une pute svp&#8221;, parce que ma serveuse d&#8217;étage était habillée sexy, bien maquillée, et après avoir servi mon soda a attendu là, sans rien dire, en me regardant. Généralement le service de chambre fait mine de demander un pourboire et se casse le plus vite possible.</p>
<p> Devant mon air intrigué, elle me demande si je n&#8217;ai VRAIMENT pas besoin d&#8217;autre chose&#8230; En sortant de ma chambre, je croise un vieux accompagné de deux paires de jambes de 3 mètres 12, et je comprends le principe.</p>
<h2> Chez nous, c&#8217;est pas mal aussi</h2>
<p>Bon, l&#8217;Europe de l&#8217;Est, c&#8217;est hyper sexualisé dans les grandes villes, mais ça toute personne qui y va s&#8217;en rend compte. On vous a déjà aussi parlé <a href="http://sametmax.com/une-journee-dans-un-fkk-maison-close-allemande/">des FKK en Allemagne</a>.</p>
<p>Non, ce qui est étonnant, c&#8217;est de voir de ses propres yeux le bordel de la sexualité aux USA. Vous avez d&#8217;un côté le monde de la pub qui montre des éphèbes, et de l&#8217;autre la population réelle qui est remplie de gens en mauvaise santé, souvent gros, rarement beaux, et mal dans leur peau. </p>
<p>Vous avez des bars où les nanas se bourrent la gueule, et on peut venir les ramasser limite sans rien dire, comme en Angleterre après 23h. Et vous avez les meufs hyper prudes qui ne couchent pas avant le mariage. C&#8217;est vrai, ce n&#8217;est pas un sitecom, c&#8217;est la réalité de tous les jours.</p>
<p>Max a tendance à me dire que la France est un pays de frustrés sexuels, avec des meufs hyper-éxigentes par rapport à ce qu&#8217;elle ont à offrir et qui ont peur de tout, et des gars sans couilles qui ne respectent pas leurs envies et en deviennent des boulets avec une vie de merde.</p>
<p>Analyse agressive, mais j&#8217;ai du mal à le contredire certains jours. Et je pense que c&#8217;est une caricature qui peut s&#8217;appliquer à la plupart des pays occidentaux industrialisés. C&#8217;est triste.</p>
<p>Dans le domaine du cul, je n&#8217;ai pas encore croisé un pays où la société ait une approche globalement saine. C&#8217;est à dire des gens qui ne tombent pas systématiquement dans un excès. Après tout, attendre le mariage, pourquoi pas. Mettre une meuf à poil pour vendre une voiture, pourquoi pas. Regarder du porno hardcore dans un cyber, pourquoi pas. Mais quand on est dans une systématisation d&#8217;un comportement qui est en plus éloigné de la réalité, ça craint. <strong>Qu&#8217;on ne viennent pas me dire que ce sont des causes, ce sont des symptômes.</strong> </p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8269&amp;md5=1e0ce6be9eb9eabd86eaa7fb8356fb4b" 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=8268
title: Ignorer certains caractères spéciaux dans un template django
uri: Ignorer-certains-caractères-spéciaux-dans-un-template-django
url: http://sametmax.com/ignorer-certains-caracteres-speciaux-dans-un-template-django/
content:
<p>Hier Max me demandait comment mettre un template Javascript dans un template Django s&#8217;ils utilisent la même syntaxe.</p>
<p>La réponse : utiliser le tag &#8220;verbatim&#8221; :</p>
<pre>{% verbatim %}
  Mettre ici le code que django doit afficher tel quel, sans interpréter.
{% endverbatim %}</pre>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8268&amp;md5=8befa07ac1d855e17ce1f253e695bef8" 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=7440
title: Qu’est-de que MVC et à quoi ça sert ?
uri: Qu-est-de-que-MVC-et-à-quoi-ça-sert
url: http://sametmax.com/quest-de-que-mvc-et-a-quoi-ca-sert/
content:
<p>MVC, pour &#8220;Modèle, Vue, Contrôleur&#8221;, est le nom donné à une manière d&#8217;organiser son code. C&#8217;est une façon d&#8217;appliquer le principe de séparation des responsabilités, en l’occurrence celles du traitement de l&#8217;information et de sa mise en forme.</p>
<p>Une fois n&#8217;est pas coutume je vais donner un exemple en Python <strong>et PHP</strong>, car c&#8217;est une question qui hante les codeurs de ce langage. En effet on leur rabâche qu&#8217;il faut utiliser MVC, que tel framework est MVC, que leur code à eux ne l&#8217;est pas, etc. Sans que nulle part, évidement, on ne donne une explication correcte de la notion.</p>
<p>Long article, petite musique.</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="420" height="315" src="//www.youtube.com/embed/Bb1_zqQ-BUA" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<p><em>(piqué à What the cut :-))</em></p>
<h2>Principe de base</h2>
<p>Il n&#8217;y a pas de Tables De La Loi qui disent ce qu&#8217;est le MVC, il y a donc autant de manières de le faire que de programmes. En fait, c&#8217;est un simple principe d&#8217;organisation de code, et il y en a d&#8217;<a href="http://cirw.in//blog/time-to-move-on.html">autres</a>. Mais généralement, c&#8217;est basé sur la répartition suivante :</p>
<ul>
<li>Une part du code gère l&#8217;affichage. C&#8217;est la partie &#8220;Vue&#8221;.</li>
<li>Une part du code gère la manipulation des données. C&#8217;est la partie &#8220;Modèle&#8221;.</li>
<li>Tout le reste. L&#8217;espèce de merdier qu&#8217;on va mettre en place pour faire marcher le programme, c&#8217;est le contrôleur. Souvent, c&#8217;est le code qui réagit à l&#8217;action de l&#8217;utilisateur, mais pas seulement.</li>
</ul>
<p>MVC est typiquement quelque chose d&#8217;abstrait qu&#8217;on ne peut pas comprendre avec une explication seule. Passons donc rapidement à un exemple.</p>
<p>Imaginons que l&#8217;on ait des tas de fichiers CSV ainsi faits :</p>
<pre>"Jeu";"Nombre de joueurs Max";"Support"
"Secret of Mana";"3";"Super Nintendo"
"Bomberman";"8";"Super Nintendo"
"Mario Kart";"4";"Nintendo 64"
"Age of Empire 2";"8";"PC"</pre>
<p>Et que nous voulions un programme qui fasse un rapport sur le CSV, affichant :</p>
<pre>Nombre de jeux analysés : 10

Détails
--------

Support: Super Nintendo
Nombre de jeux : 2
Nombre de joueurs max : 8

Support: Nintendo 64
Nombre de jeux : 1
Nombre de joueurs max : 4

etc</pre>
<p>Il y a de nombreuses manières de coder ce programme. Si on le fait en suivant le principe du modèle MVC, on va faire 3 fichiers : un pour le modèle, un pour la vue, et un pour le contrôleur. On peut avoir plus ou moins de 3 fichiers, j&#8217;ai choisi 3 fichiers pour bien illustrer le principe de séparation des responsabilités.</p>
<h3>Le modèle</h3>
<p>Le modèle manipule la donnée. Dans un site Web, le modèle est souvent le code qui permet de faire de requêtes à la base de données. Dans notre cas, c&#8217;est le code qui va manipuler le CSV. Encore une fois, il n&#8217;y a pas de définition divine de ce qu&#8217;est un modèle, ceci n&#8217;est qu&#8217;un exemple de ce que cela PEUT être. C&#8217;est le choix du dev.</p>
<p><em>modele.py</em></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> <span style="color: #dc143c;">__future__</span> <span style="color: #ff7700;font-weight:bold;">import</span> unicode_literals, absolute_import
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">csv</span> <span style="color: #ff7700;font-weight:bold;">import</span> DictReader
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">collections</span> <span style="color: #ff7700;font-weight:bold;">import</span> OrderedDict
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Modele<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #dc143c;">csv</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">total_jeux</span> = <span style="color: #ff4500;">0</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">supports</span> = OrderedDict<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">csv</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> f:
            <span style="color: #808080; font-style: italic;"># on parse le csv</span>
            <span style="color: #ff7700;font-weight:bold;">for</span> data <span style="color: #ff7700;font-weight:bold;">in</span> DictReader<span style="color: black;">&#40;</span>f, delimiter=b<span style="color: #483d8b;">';'</span>, quotechar=b<span style="color: #483d8b;">'&quot;'</span><span style="color: black;">&#41;</span>:
                <span style="color: #808080; font-style: italic;"># on calcule les stats pour que ligne du csv</span>
                support = <span style="color: #008000;">self</span>.<span style="color: black;">supports</span>.<span style="color: black;">setdefault</span><span style="color: black;">&#40;</span>data<span style="color: black;">&#91;</span><span style="color: #483d8b;">'Support'</span><span style="color: black;">&#93;</span>, <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
                support<span style="color: black;">&#91;</span><span style="color: #483d8b;">'nombre_de_jeux'</span><span style="color: black;">&#93;</span> = support.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'nombre_de_jeux'</span>, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span> + <span style="color: #ff4500;">1</span>
                <span style="color: #008000;">self</span>.<span style="color: black;">total_jeux</span> += <span style="color: #ff4500;">1</span>
                <span style="color: #ff7700;font-weight:bold;">if</span> support.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'joueurs_max'</span>, <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&lt;</span> data<span style="color: black;">&#91;</span><span style="color: #483d8b;">'Nombre de joueurs Max'</span><span style="color: black;">&#93;</span>:
                    support<span style="color: black;">&#91;</span><span style="color: #483d8b;">'joueurs_max'</span><span style="color: black;">&#93;</span> = data<span style="color: black;">&#91;</span><span style="color: #483d8b;">'Nombre de joueurs Max'</span><span style="color: black;">&#93;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__iter__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;"># goodies pour pouvoir itérer sur le modèle</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">supports</span>.<span style="color: black;">iteritems</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Ca s&#8217;utilise comme ça :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> modele = Modele<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Bureau/jeux.csv&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> modele.<span style="color: black;">total_jeux</span>
<span style="color: #ff4500;">4</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">for</span> support, data <span style="color: #ff7700;font-weight:bold;">in</span> modele:
    <span style="color: #ff7700;font-weight:bold;">print</span> support
    <span style="color: #ff7700;font-weight:bold;">print</span> data
...
<span style="color: black;">Super</span> Nintendo
<span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'nombre_de_jeux'</span>: <span style="color: #ff4500;">2</span>, u<span style="color: #483d8b;">'joueurs_max'</span>: <span style="color: #483d8b;">'8'</span><span style="color: black;">&#125;</span>
Nintendo <span style="color: #ff4500;">64</span>
<span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'nombre_de_jeux'</span>: <span style="color: #ff4500;">1</span>, u<span style="color: #483d8b;">'joueurs_max'</span>: <span style="color: #483d8b;">'4'</span><span style="color: black;">&#125;</span>
PC
<span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'nombre_de_jeux'</span>: <span style="color: #ff4500;">1</span>, u<span style="color: #483d8b;">'joueurs_max'</span>: <span style="color: #483d8b;">'8'</span><span style="color: black;">&#125;</span></pre></div></div>

<p>On voit ici le principe : le modèle ne fait que manipuler la donnée, et rien d&#8217;autre. Il extrait, regroupe, calcule, raffine, et donne une belle interface propre pour que le reste du programme puisse utiliser le résultat sans avoir à connaitre les détails du traitement.</p>
<h3>La vue</h3>
<p>La vue, c&#8217;est de la présentation. C&#8217;est comment on veut que la donnée soit présentée à l&#8217;utilisateur. Ça peut être le code qui pond du HTML ou produit un CSV, ou fait configurer de jolis boutons dans une UI.</p>
<p>Dans notre cas, c&#8217;est le code qui va formater le texte pour la console.</p>
<p>On veut un truc comme ça :</p>
<pre>
Nombre de jeux analysés : 10

Détails
--------

Support: Super Nintendo
Nombre de jeux : 2
Nombre de joueurs max : 8

Support: Nintendo 64
Nombre de jeux : 1
Nombre de joueurs max : 4</pre>
<p>Normalement, on voudrait un template. Mais on a pas de langage de template qui accepte les boucles dans la lib standard, alors on va faire comme la norme WSGI et retourner un générateur de strings.</p>
<p><em>vue.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: #dc143c;">__future__</span> <span style="color: #ff7700;font-weight:bold;">import</span> unicode_literals, absolute_import
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> rapport<span style="color: black;">&#40;</span>modele<span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># affichage de l'en-tête</span>
    <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Nombre de jeux analysés : {total_jeux}<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>
           <span style="color: #483d8b;">&quot;Détails<span style="color: #000099; font-weight: bold;">\n</span>--------<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: black;">&#41;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>total_jeux=modele.<span style="color: black;">total_jeux</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># affichage des stats pour chaque console</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> support, data <span style="color: #ff7700;font-weight:bold;">in</span> modele:
        <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Support: {support}<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>
               <span style="color: #483d8b;">&quot;Nombre de jeux : {nombre_de_jeux}<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>
               <span style="color: #483d8b;">&quot;Nombre de joueurs max : {joueurs_max}<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: black;">&#41;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>
               support=support, <span style="color: #66cc66;">**</span>data<span style="color: black;">&#41;</span></pre></div></div>

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

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> m = Modele<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Bureau/jeux.csv&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>rapport<span style="color: black;">&#40;</span>m<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span>u<span style="color: #483d8b;">'Nombre de jeux analys<span style="color: #000099; font-weight: bold;">\x</span>e9s : 4<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>D<span style="color: #000099; font-weight: bold;">\x</span>e9tails<span style="color: #000099; font-weight: bold;">\n</span>--------<span style="color: #000099; font-weight: bold;">\n</span>'</span>, u<span style="color: #483d8b;">'Support: Super Nintendo<span style="color: #000099; font-weight: bold;">\n</span>Nombre de jeux : 2<span style="color: #000099; font-weight: bold;">\n</span>Nombre de joueurs max : 8<span style="color: #000099; font-weight: bold;">\n</span>'</span>, u<span style="color: #483d8b;">'Support: Nintendo 64<span style="color: #000099; font-weight: bold;">\n</span>Nombre de jeux : 1<span style="color: #000099; font-weight: bold;">\n</span>Nombre de joueurs max : 4<span style="color: #000099; font-weight: bold;">\n</span>'</span>, u<span style="color: #483d8b;">'Support: PC<span style="color: #000099; font-weight: bold;">\n</span>Nombre de jeux : 1<span style="color: #000099; font-weight: bold;">\n</span>Nombre de joueurs max : 8<span style="color: #000099; font-weight: bold;">\n</span>'</span><span style="color: black;">&#93;</span></pre></div></div>

<p>Encore une fois, ceci n&#8217;est pas LA manière de faire une vue. Ceci est UNE manière de faire une vue. Le but de la vue est de contenir le code qui se charge de formater la donnée pour l&#8217;utilisateur. </p>
<p>Il est plus courant d&#8217;utiliser un template pour cela, c&#8217;est à dire une sorte lib de texte à trou à remplir plus tard avec le modèle. C&#8217;est plus facile et flexible qu&#8217;une fonction. Il y a des tas de <a href="https://wiki.python.org/moin/Templating">libs de templates en Python</a>. Je ferai sans doute un article dessus un jour. Si vous voulez un truc simple et rapide, utilisez <a href="http://www.joonis.de/en/code/templite">templite</a> : rien besoin d&#8217;installer, ça tient dans un fichier. Si vous voulez le truc le plus standard possible, utiliser <a href="http://jinja.pocoo.org/docs/">jinja2</a>, c&#8217;est plus ou moins la lib la plus connue actuellement.</p>
<h3>Le contrôleur</h3>
<p>Le contrôleur, c&#8217;est tout le reste. Essayer de définir le contrôleur est généralement voué à l&#8217;échec, tant sa nature change d&#8217;une application à l&#8217;autre. Certains disent que c&#8217;est le code glue qui permet de lier le modèle et la vue. D&#8217;autres qu&#8217;il contient la logique de flux du programme. Personnellement, je vous invite à vous fier à la définition &#8220;c&#8217;est tout le reste&#8221;. Avec l&#8217;expérience, vous en viendrez à faire des modèles et des vues de plus en plus adaptées, et la partie contrôleur découlera d&#8217;elle-même.</p>
<p>De toute façon, aucun MVC n&#8217;est parfait, et un peu de vue dégouline parfois sur le contrôleur, un peu de contrôleur coule dans le modèle, ou inversement. Il ne sert à rien d&#8217;être un nazi du MVC, c&#8217;est une bonne pratique, pas un dogme religieux.</p>
<p>Dans notre cas le programme a besoin d&#8217;un code qui :</p>
<ul>
<li>Importe notre vue et notre modèle.</li>
<li>Prend en paramètre le fichier CSV via la ligne de commande.</li>
<li>Mélange tout ça pour afficher le résultat dans la console.</li>
</ul>
<p>Le contrôleur est par ailleurs le point d&#8217;entrée d&#8217;un programme. Et ce sera essentiellement ça, le contrôleur de notre programme : un point d&#8217;entrée.</p>
<p><em>controlleur.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: #dc143c;">__future__</span> <span style="color: #ff7700;font-weight:bold;">import</span> unicode_literals, absolute_import
&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>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> vue <span style="color: #ff7700;font-weight:bold;">import</span> rapport
<span style="color: #ff7700;font-weight:bold;">from</span> modele <span style="color: #ff7700;font-weight:bold;">import</span> Modele
&nbsp;
<span style="color: #808080; font-style: italic;"># on prend le csv en paramètre du script</span>
<span style="color: #ff7700;font-weight:bold;">try</span>:
    f = <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: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">IndexError</span>:
    <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Veuillez passer le chemin d'un fichier CSV en paramètre.&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># on vérifie que le csv existe</span>
<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">isfile</span><span style="color: black;">&#40;</span>f<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: #483d8b;">&quot;Le fichier '%s' n'existe pas&quot;</span> <span style="color: #66cc66;">%</span> f<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># on analyse le CSV et on affiche le rapport</span>
<span style="color: #ff7700;font-weight:bold;">for</span> texte <span style="color: #ff7700;font-weight:bold;">in</span> rapport<span style="color: black;">&#40;</span>Modele<span style="color: black;">&#40;</span>f<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> texte</pre></div></div>

<h3>Résultat final</h3>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">$ python controlleur.<span style="color: black;">py</span> jeux.<span style="color: #dc143c;">csv</span>
Nombre de jeux analysés : <span style="color: #ff4500;">4</span>
&nbsp;
Détails
--------
&nbsp;
Support: Super Nintendo
Nombre de jeux : <span style="color: #ff4500;">2</span>
Nombre de joueurs <span style="color: #008000;">max</span> : <span style="color: #ff4500;">8</span>
&nbsp;
Support: Nintendo <span style="color: #ff4500;">64</span>
Nombre de jeux : <span style="color: #ff4500;">1</span>
Nombre de joueurs <span style="color: #008000;">max</span> : <span style="color: #ff4500;">4</span>
&nbsp;
Support: PC
Nombre de jeux : <span style="color: #ff4500;">1</span>
Nombre de joueurs <span style="color: #008000;">max</span> : <span style="color: #ff4500;">8</span></pre></div></div>

<p>Vous pouvez <a href="https://github.com/sametmax/codes-des-articles/tree/master/2013/decembre">télécharger le code Python de cet article</a>.</p>
<h2>Exemple en PHP</h2>
<p>Le PHP a eu beaucoup de succès du fait de la facilité avec laquelle on pouvait coder un site Web, en mélangeant code et HTML. Malheureusement cela a donné lieu à des codes très sales, où on trouvait les requêtes SQL à côté de l&#8217;affichage d&#8217;un tableau, l&#8217;analyse des paramètres <code>$_GET</code> à deux pas de la vérification du mot de passe.</p>
<p>MVC a été une réponse à cela.</p>
<p>Un modèle MVC propre sera généralement très riche et complexe, mais il est possible de bricoler un site en MVC basique à la main sans trop de problème. Je ne vous recommande pas d&#8217;utiliser ce code en prod, mais c&#8217;est un bon début pour comprendre comment ça marche. Une fois que vous serez à l&#8217;aise avec l&#8217;idée, n&#8217;hésitez pas à coder le votre sur un petit projet, puis à tester un framework. <a href="http://symfony.com/">Symfony</a>, par exemple, est une valeur sûre en PHP.</p>
<p>Admettons que notre site ait deux pages : <em>accueil</em> et <em>liste des utilisateurs</em>.</p>
<p>L&#8217;accueil dit juste bonjour, la liste affiche tous les utilisateurs du site Web. Passionnant.</p>
<h3>Le modèle</h3>
<p>L&#8217;idée est de mettre toutes les requêtes SQL au même endroit.</p>
<p>Les vieux routards du PHP m&#8217;excuseront, mais je n&#8217;ai plus codé dans ce langage depuis des années, donc mon style va dater un peu :-) Et honnêtement tous ces points-virgules, ces dollars et ces brackets dans tous les sens, sans compter la flèche comme caractère de look up, ça me perturbe grandement.</p>
<p><em>modele.php</em></p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #000088;">$con</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysqli_connect</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;127.0.0.1&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'root'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'admin123'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'ma_db'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">class</span> User <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$name</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$age</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #000088;">$name</span><span style="color: #339933;">,</span> <span style="color: #000088;">$age</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$name</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">age</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$age</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    static <span style="color: #000000; font-weight: bold;">function</span> liste<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #000088;">$users</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$query</span> <span style="color: #339933;">=</span>  <span style="color: #990000;">mysqli_query</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$con</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'SELECT * FROM `user`'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$row</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_fetch_assoc</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$query</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$users</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> User<span style="color: #009900;">&#40;</span><span style="color: #000088;">$row</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$row</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #b1b100;">return</span> users<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></div></div>

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

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$users</span> <span style="color: #339933;">=</span> User<span style="color: #339933;">-&gt;</span><span style="color: #004000;">liste</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$users</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$user</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$user</span><span style="color: #339933;">.</span>name <span style="color: #339933;">.</span> <span style="color: #0000ff;">'('</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$users</span><span style="color: #339933;">.</span>age<span style="color: #339933;">.</span> <span style="color: #0000ff;">'ans)'</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Ce qui affiche tous les noms et les ages des utilisateurs.</p>
<p>Bien, on a isolé l&#8217;accès aux données, maintenant on va isoler la mise en forme.</p>
<h3>La vue</h3>
<p>Ou plutôt, les vues, puisqu&#8217;on a deux pages, et donc deux vues.</p>
<p>Vous ne le savez peut être pas, mais PHP vient avec une <a href="http://www.php.net/manual/fr/control-structures.alternative-syntax.php">syntaxe alternativ</a>e spécialement conçue pour être utilisée dans le HTML. Elle est similaire à la syntaxe originale, mais les blocs sont ouverts avec <code>:</code> au lieux de <code>{</code> et fermés par <code>endinstruction</code>. Les variables sont affichées avec <<code>?=$nom_de_variable?></code>.</p>
<p>Par exemple:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span> <span style="color: #000088;">$truc</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
    &lt;p&gt;
        <span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$machin</span><span style="color: #000000; font-weight: bold;">?&gt;</span>
    &lt;/p&gt;
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endif</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Cette syntaxe permet de bien séparer le texte du code PHP, et donc sera utilisée pour la vue.</p>
<p><em>accueil.php</em></p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #339933;">&lt;</span>html<span style="color: #339933;">&gt;&lt;</span>body<span style="color: #339933;">&gt;&lt;</span>h1<span style="color: #339933;">&gt;</span>Bonjour<span style="color: #339933;">&lt;/</span>h1<span style="color: #339933;">&gt;&lt;/</span>body<span style="color: #339933;">&gt;&lt;/</span>html<span style="color: #339933;">&gt;</span></pre></div></div>

<p><em>liste_utilisateurs.php</em></p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">&lt;html&gt;
    &lt;body&gt;
        &lt;h1&gt;Utilisateurs&lt;/h1&gt;
&nbsp;
        &lt;ul&gt;http://www.php.net/manual/fr/control-structures.alternative-syntax.php
            <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">foreach</span> <span style="color: #000088;">$users</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$user</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
                &lt;li&gt;<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span><span style="color: #000000; font-weight: bold;">?&gt;</span> (<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">age</span><span style="color: #000000; font-weight: bold;">?&gt;</span> ans)&lt;/li&gt;
            <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endforeach</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
        &lt;/ul&gt;
&nbsp;
    &lt;/body&gt;
&lt;/html&gt;</pre></div></div>

<p>Et voilà, on a deux pages, et la deuxième affiche notre liste d'utilisateur. Vous remarquerez qu'il n'y a pas de requête ou de logique de choix de page, pas d'accès à <code>mysql_*</code> ou à <code>$_GET</code> dans ce code. Que de l'affichage.</p>
<h3>Le contrôleur</h3>
<p>Puisque le contrôleur, c'est le reste, ce sera à la fois notre point d'entrée, notre code glue et notre routing.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'page'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$_GET</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'page'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> <span style="color: #0000ff;">'liste'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">require</span> <span style="color: #0000ff;">'modele.php'</span>
    <span style="color: #b1b100;">require</span> <span style="color: #0000ff;">'liste_utilisateurs.php'</span>
<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">require</span> <span style="color: #0000ff;">'accueil.php'</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Et c'est tout.</p>
<p>Si l'utilisateur va sur l'adresse <em>monsite.com/</em>, il va arriver sur l'accueil, si il va sur <em>monsite.com/?page=liste</em>, il va atterrir sur la liste des utilisateurs.</p>
<p>Si on veut changer le look de la page, on modifie la vue. Si on veut changer de base de source de données (et lire par exemple depuis un fichier), on change le modèle. Si on veut rajouter des pages, on change le contrôleur. L'avantage de la séparation des responsabilités, c'est la facilité de lecture et donc de maintenance et d'évolution.</p>
<p>J'insiste sur le fait que c'est un exemple pédagogique, et pas quelque chose à utiliser en prod (par exemple à cause des URLs très moches). Mais il va vous permettre de coder votre premier site en MVC, et plus tard, aller vers des versions plus sérieuses.</p>
<p>L'important, c'est la séparation donnée / formatage / reste du code.</p>
<h2>MVC dans la vraie vie vivante</h2>
<p>Créer un modèle MVC à la main propre et efficace, c'est énormément de taff. C'est pour cela qu'on utilise des outils tout fait comme des frameworks Web ou des libs graphiques (Qt, wxWidget et Gtk ont toutes des outils MVC, ex : Qt possède <a href="http://en.wikipedia.org/wiki/QML">QML</a>, un dialecte type CSS pour manipuler des vues).</p>
<p>Un modèle MVC simple, mais propre, est celui du micro-framework Web Python <a href="http://bottlepy.org">bottle</a>, dont Max vous avait parlé <a href="http://sametmax.com/creer-un-site-avec-bottle-en-5-minutes-parceque-7-cest-impossible-voyons/">ici</a>. Lisez l'article, et revenez à ce paragraphe, et vous comprendrez que :</p>
<ul>
<li>La vue, c'est le template.</li>
<li>Le modèle n'est inclus dans bottle, il faut le faire à la main ou utiliser quelque chose comme un ORM (<a href="http://sametmax.com/sept-petites-libs-qui-changent-la-vie-dun-dev-python/">peewee</a> est très bien adapté).</li>
<li>Le contrôleur, ce sont les fonctions qu'on trouve sous les décorateurs <code>@url</code>.</li>
</ul>
<p>Comme je l'ai dit précédemment, il y a de nombreuses manières de séparer le contenu de sa présentation.</p>
<p>Django par exemple n'utilise pas un modèle MVC au sens traditionnel, mais plutôt du MVT (Modèle - Vue - Template). Ce qu'il appelle les vues sont en fait ce qu'on appelle le contrôleur dans bottle : les fonctions qui mélangent les données avec le template. Django propose par contre un ORM, qui est bel est bien un système de modèle très élaboré.</p>
<p>C'est une question de sémantique, et au final, qu'importe le flacon, pourvu qu'on ait l'ivresse.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7440&amp;md5=ef13aa60b7ec25234daadd5374a73798" 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=8171
title: Du Darwinisme pythonien
uri: Du-Darwinisme-pythonien
url: http://sametmax.com/du-darwinisme-pythonien/
content:
<p style="text-align: center;"><em><small>Ceci est un post invité de <a href="http://sametmax.com/author/golgotha/">golgotha</a> posté sous licence <a href="http://creativecommons.org/licenses/by/3.0/">creative common 3.0 unported</a>.</small></em></p>
<p>Qui n&#8217;a jamais rêvé de cloner des <del datetime="2013-12-02T19:59:20+00:00">moutons</del> clara morgane et de s&#8217;adonner à des expérimentations scientifiques de haut niveau ?</p>
<p>Bon ici, nous n&#8217;avons pas de clara morgane sous la main pour notre expérience mais, avec le python et les théories scientifiques de Darwin, on peut faire quelques trucs sympas : On va essayer de déterminer le plus court chemin à prendre pour relier plusieurs points entre eux, le truc cool c&#8217;est que pour solutionner le problème on va utiliser un algorithme génétique.</p>
<p>De la génétique dans du python ?!</p>
<p>En fait c&#8217;est assez simple (encore des termes barbares pour épater les copains..), écoutez bien, je vous explique le concept : on va faire des individus, chaque individu va faire un parcours en fonction des points du tracé en paramètre. A la fin, on note chaque individu avec un score, le score étant la longueur du parcours de l&#8217;individu. Vous suivez toujours ? Bien. On prend les meilleurs (Normal) et on les accouple avec des moins bons (faut les pousser un peu, au début ils sont timides mais, après ça va tout seul, c&#8217;est même l&#8217;orgie parfois&#8230;) ce qui donne une nouvelle population, normalement un poil meilleure que l&#8217;ancienne qu&#8217;on va vite mettre à la poubelle. On recommence le processus <code>n</code> fois et à la fin, on devrait arriver à des super individus, genre blonds aux yeux bleus qui parlent 14 langues : ça c&#8217;est notre solution.</p>
<p>Passons aux travaux pratiques !</p>
<p>Je commence par déclarer deux variables globales, la population et la liste de points.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">population = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
a_map = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span></pre></div></div>

<p>Ensuite on créer une classe Point standard :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Point<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
    COUNT = <span style="color: #ff4500;">0</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, x, y<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">X</span> = x
        <span style="color: #008000;">self</span>.<span style="color: black;">Y</span> = y
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__str__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;Point(%s,%s)&quot;</span><span style="color: #66cc66;">%</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">X</span>, <span style="color: #008000;">self</span>.<span style="color: black;">Y</span><span style="color: black;">&#41;</span> 
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> distance<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, other<span style="color: black;">&#41;</span>:
        dx = <span style="color: #008000;">self</span>.<span style="color: black;">X</span> - other.<span style="color: black;">X</span>
        dy = <span style="color: #008000;">self</span>.<span style="color: black;">Y</span> - other.<span style="color: black;">Y</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> sqrt<span style="color: black;">&#40;</span>dx<span style="color: #66cc66;">**</span><span style="color: #ff4500;">2</span> + dy<span style="color: #66cc66;">**</span><span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Rien de particulier ici, l&#8217;objet nous sera utile plus tard.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Individu<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;"># le constructeur de l'objet.</span>
    <span style="color: #808080; font-style: italic;"># on met le score à zéro.</span>
    <span style="color: #808080; font-style: italic;"># on peut aussi lui passer la liste de points</span>
    <span style="color: #808080; font-style: italic;"># pour qu'il initialise une route au hasard.</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, init = <span style="color: #008000;">False</span>, map_point = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">score</span> = <span style="color: #ff4500;">0</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">route</span> = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> init :
            <span style="color: #008000;">self</span>.<span style="color: black;">set_route</span><span style="color: black;">&#40;</span>map_point<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># ici on créé une route avec un mélange des points</span>
    <span style="color: #808080; font-style: italic;"># on utilise shuffle pour mélanger les points.</span>
    <span style="color: #808080; font-style: italic;"># ensuite on calcul le score, c'est à dire la longueur du trajet.</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> set_route<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, map_point<span style="color: black;">&#41;</span> :
        shuffle<span style="color: black;">&#40;</span>map_point<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">route</span> = map_point
        <span style="color: #ff7700;font-weight:bold;">for</span> p <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #008000;">len</span><span style="color: black;">&#40;</span>map_point<span style="color: black;">&#41;</span> - <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span> :
            <span style="color: #008000;">self</span>.<span style="color: black;">score</span> += map_point<span style="color: black;">&#91;</span>p<span style="color: black;">&#93;</span>.<span style="color: black;">distance</span><span style="color: black;">&#40;</span>map_point<span style="color: black;">&#91;</span>p+<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># ici on donne à l'objet la capacité de faire un enfant</span>
    <span style="color: #808080; font-style: italic;"># ça prend comme paramètre l'objet (lui même), et un autre individu.</span>
    <span style="color: #808080; font-style: italic;"># on prend la moitié du trajet de l'objet et on complète avec</span>
    <span style="color: #808080; font-style: italic;"># les points de l'autre individu.</span>
    <span style="color: #808080; font-style: italic;"># on retourne un enfant, qui est un individu.</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> croisement<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, other<span style="color: black;">&#41;</span>:
        child = Individu<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># je prends la moitier de moi-même.</span>
        wdth = <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">route</span><span style="color: black;">&#41;</span>/<span style="color: #ff4500;">2</span>
        first_segment = <span style="color: #008000;">self</span>.<span style="color: black;">route</span><span style="color: black;">&#91;</span>:wdth/<span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span>
        last_segment  = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
        <span style="color: #808080; font-style: italic;"># je complète avec l'autre</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">route</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> :
            <span style="color: #ff7700;font-weight:bold;">if</span> other.<span style="color: black;">route</span><span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> first_segment :
                last_segment.<span style="color: black;">append</span><span style="color: black;">&#40;</span>other.<span style="color: black;">route</span><span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        child.<span style="color: black;">set_route</span><span style="color: black;">&#40;</span>first_segment + last_segment<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> child
&nbsp;
    <span style="color: #808080; font-style: italic;"># ici on défini une fonction pour que l'objet puisse se dessiner.</span>
    <span style="color: #808080; font-style: italic;"># pour cela on utilisera Turtle de python.</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> show_me<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #dc143c;">turtle</span>.<span style="color: black;">clearscreen</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        pen = <span style="color: #dc143c;">turtle</span>.<span style="color: black;">Turtle</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        pen.<span style="color: black;">speed</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
        pen.<span style="color: black;">up</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        pen.<span style="color: black;">setpos</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">route</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>.<span style="color: black;">X</span>, <span style="color: #008000;">self</span>.<span style="color: black;">route</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>.<span style="color: black;">Y</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> point <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">self</span>.<span style="color: black;">route</span> :
            pen.<span style="color: black;">goto</span><span style="color: black;">&#40;</span>point.<span style="color: black;">X</span>, point.<span style="color: black;">Y</span><span style="color: black;">&#41;</span>
            pen.<span style="color: black;">down</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            pen.<span style="color: black;">dot</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
        pen.<span style="color: black;">goto</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">route</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>.<span style="color: black;">X</span>, <span style="color: #008000;">self</span>.<span style="color: black;">route</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>.<span style="color: black;">Y</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Voilà pour l&#8217;objet individu (pas très inspiré sur le nom j&#8217;avoue..) qui est donc capable maintenant de faire pas mal de choses qui sera utile: se montrer, faire un petit (capacité que beaucoup d&#8217;objet lui envie déjà) et choisir une route parmi une liste de points.</p>
<p>La suite, j&#8217;ai écris ça dans des fonctions, il y a surement plus propre mais bon, le but est de vous montrer comment fonctionne un algo génétique, je laisserai le soin aux pro du python d&#8217;améliorer le code en lui-même (je ne vais pas faire tout le boulot non plus !)</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># initialisation des points de la carte.</span>
<span style="color: #808080; font-style: italic;"># prend en paramètre un nombre de points.</span>
<span style="color: #ff7700;font-weight:bold;">def</span> init_map<span style="color: black;">&#40;</span>nb<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">global</span> a_map
    <span style="color: #ff7700;font-weight:bold;">del</span> a_map<span style="color: black;">&#91;</span>:<span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>nb<span style="color: black;">&#41;</span>:
        p = Point<span style="color: black;">&#40;</span>randint<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">300</span><span style="color: black;">&#41;</span>, randint<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">300</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        a_map.<span style="color: black;">append</span><span style="color: black;">&#40;</span>p<span style="color: black;">&#41;</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># initialisation de la population.</span>
<span style="color: #808080; font-style: italic;"># prend en paramètre le nombre d'individus à créer.</span>
<span style="color: #ff7700;font-weight:bold;">def</span> init_pop<span style="color: black;">&#40;</span>nb, map_point<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">global</span> population
    <span style="color: #ff7700;font-weight:bold;">del</span> population<span style="color: black;">&#91;</span>:<span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>nb<span style="color: black;">&#41;</span>:
        i = Individu<span style="color: black;">&#40;</span><span style="color: #008000;">True</span>, map_point<span style="color: black;">&#41;</span>
        population.<span style="color: black;">append</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#41;</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># fonction qui sert à trier les individus suivant leur score.</span>
<span style="color: #808080; font-style: italic;"># utile pour trouver les meilleurs.</span>
<span style="color: #ff7700;font-weight:bold;">def</span> selection<span style="color: black;">&#40;</span>pop<span style="color: black;">&#41;</span>:
    pop.<span style="color: black;">sort</span><span style="color: black;">&#40;</span>key=<span style="color: #ff7700;font-weight:bold;">lambda</span> x: x.<span style="color: black;">score</span>, reverse=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># dans cette fonction, on sélectionne les 15 meilleurs individus de la population</span>
<span style="color: #808080; font-style: italic;"># que l'on croise avec les autres individus.</span>
<span style="color: #808080; font-style: italic;"># la nouvelle population est constituée des 15 meilleurs plus les enfants.</span>
<span style="color: #ff7700;font-weight:bold;">def</span> croisement<span style="color: black;">&#40;</span>pop<span style="color: black;">&#41;</span>:
    new_pop = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
    best_pop = population<span style="color: black;">&#91;</span><span style="color: #ff4500;">85</span>:<span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #008000;">len</span><span style="color: black;">&#40;</span>pop<span style="color: black;">&#41;</span>-<span style="color: #ff4500;">15</span><span style="color: black;">&#41;</span> :
        new_pop.<span style="color: black;">append</span><span style="color: black;">&#40;</span>choice<span style="color: black;">&#40;</span>best_pop<span style="color: black;">&#41;</span>.<span style="color: black;">croisement</span><span style="color: black;">&#40;</span>choice<span style="color: black;">&#40;</span>population<span style="color: black;">&#91;</span><span style="color: #ff4500;">20</span>:<span style="color: #ff4500;">85</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;">return</span> new_pop + best_pop</pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># la fonction principal.</span>
<span style="color: #808080; font-style: italic;"># on passe en paramètre le nombre de générations que l'on souhaite faire</span>
<span style="color: #808080; font-style: italic;"># et le nombre de points. </span>
<span style="color: #808080; font-style: italic;"># Ensuite, on itère selon un algorithme précis :</span>
<span style="color: #808080; font-style: italic;"># Création d'une population initiale.</span>
<span style="color: #808080; font-style: italic;"># Sélection puis croisement de la population</span>
<span style="color: #808080; font-style: italic;"># à chaque génération on regarde si on a un meilleur score</span>
<span style="color: #808080; font-style: italic;"># si oui, on l'affiche.</span>
<span style="color: #ff7700;font-weight:bold;">def</span> play<span style="color: black;">&#40;</span>nb_gene, nb_point<span style="color: black;">&#41;</span> :
    init_map<span style="color: black;">&#40;</span>nb_point<span style="color: black;">&#41;</span>
    init_pop<span style="color: black;">&#40;</span><span style="color: #ff4500;">100</span>, a_map<span style="color: black;">&#41;</span>
    best_score = <span style="color: #ff4500;">1000000</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>nb_gene<span style="color: black;">&#41;</span> :
        <span style="color: #ff7700;font-weight:bold;">global</span> population
        population = croisement<span style="color: black;">&#40;</span>population<span style="color: black;">&#41;</span>
        selection<span style="color: black;">&#40;</span>population<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> best_score <span style="color: #66cc66;">&gt;</span> population<span style="color: black;">&#91;</span><span style="color: #ff4500;">99</span><span style="color: black;">&#93;</span>.<span style="color: black;">score</span> :
            best_score = population<span style="color: black;">&#91;</span><span style="color: #ff4500;">99</span><span style="color: black;">&#93;</span>.<span style="color: black;">score</span>
            <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'meilleur score : '</span> + <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>population<span style="color: black;">&#91;</span><span style="color: #ff4500;">99</span><span style="color: black;">&#93;</span>.<span style="color: black;">score</span><span style="color: black;">&#41;</span>
            population<span style="color: black;">&#91;</span><span style="color: #ff4500;">99</span><span style="color: black;">&#93;</span>.<span style="color: black;">show_me</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Voilà le morceau, je pense que j&#8217;ai laissé assez de commentaires dans le code pour bien comprendre comment ça fonctionne et au niveau du python en lui-même il n&#8217;y a vraiment rien de spécial, ici ce qui compte c&#8217;est que vous voyez rapidement comment fonctionne l&#8217;algorithme.</p>
<p>Alors, maintenant : Pourquoi s&#8217;emmerder à accoupler des objets à 2,78 Ghz ?</p>
<p>Le problème ci-dessus, un problème dit <a href="http://fr.wikipedia.org/wiki/Problème_NP-complet" title="nb-complet" target="_blank">np-complet</a>, c&#8217;est-à-dire que c&#8217;est la merde pour trouver une solution dans un temps raisonnable si on l&#8217;a fait de façon traditionnelle : pour trouver le meilleur trajet sur 10 points, on sera obligé dans un premier temps de trouver tous les trajets possibles, avec N villes on a (N-1)!/2 trajet possible, le nombre de trajets explose littéralement si N augmente. Avec 100 points il est déjà pratiquement impossible de calculer tous les trajets possibles en un temps raisonnable.</p>
<p>C&#8217;est là que l&#8217;algorithme génétique est très fort, on arrive très vite à une solution approchée, il est tout de même à noter que le résultat obtenu par l&#8217;algorithme génétique n&#8217;est pas LA solution exact au problème, il donne une solution approchée.</p>
<p>Dernier point sur le code ci-dessus, ce n&#8217;est que les bases de l&#8217;algorithme génétique, avec ce code vous ne pourrez pas venir à bout d&#8217;un parcours de plus de 20 ou 30 villes, pour cela il faut améliorer l&#8217;algorithme, par exemple le croisement entre deux individus peut être fait de plusieurs façons différentes, dans mon exemple je prends la moitié du &#8220;code génétique&#8221; d&#8217;un individu que je colle à une autre moitié, on peut aussi faire du crossover : c&#8217;est-à-dire qu&#8217;on prend des bouts du code génétique des deux individus alternativement. Ensuite, il y a aussi des mutations génétiques à introduire dans le croisement, à un certain taux, par exemple 1% des croisements entre individus produira une mutation génétique, concrètement : on fait le croisement puis on change aléatoirement des données du code génétique, dans notre exemple on échangera deux points sur le parcours. Cela a pour effet de produire des individus potentiellement meilleurs que les autres, en terme mathématique ça permet aussi de ne pas s&#8217;enfermer dans une solution locale, ce qui est souvent le cas.</p>
<p>J&#8217;espère ne pas vous avoir complètement perdu avec mes explications et vous avoir donné envie de regarder de plus près cet algorithme que je trouve très élégant.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8171&amp;md5=26fc8689f0d88eeb190a0fc3b82bd4c7" 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>


