# articles

feed_id: http://sametmax.com/?p=18443
title: Open bar sur asyncio Recently updated !
uri: Open-bar-sur-asyncio-Recently-updated
url: http://sametmax.com/open-bar-sur-asyncio/
content:
<p>Plus je fais joujou avec asyncio, plus j&#8217;apprécie la lib. Mais je tombe aussi sur des tas de petits trucs qui me font dire qu&#8217;il va falloir créer quelques couches d&#8217;abstraction pour rendre tout ça plus miam.</p>
<p>Par exemple, lire de manière asynchrone les données pipées sur stdin:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">async <span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span>loop<span style="color: black;">&#41;</span>:
&nbsp;
    reader <span style="color: #66cc66;">=</span> asyncio.<span style="color: black;">StreamReader</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> get_reader<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> asyncio.<span style="color: black;">StreamReaderProtocol</span><span style="color: black;">&#40;</span>reader<span style="color: black;">&#41;</span>
&nbsp;
    await loop.<span style="color: black;">connect_read_pipe</span><span style="color: black;">&#40;</span>get_reader<span style="color: #66cc66;">,</span> <span style="color: #dc143c;">sys</span>.<span style="color: black;">stdin</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:
        line <span style="color: #66cc66;">=</span> await reader.<span style="color: #dc143c;">readline</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> line:
            <span style="color: #ff7700;font-weight:bold;">break</span>
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>line<span style="color: black;">&#41;</span>
&nbsp;
loop <span style="color: #66cc66;">=</span> asyncio.<span style="color: black;">get_event_loop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
loop.<span style="color: black;">run_until_complete</span><span style="color: black;">&#40;</span>main<span style="color: black;">&#40;</span>loop<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>C&#8217;est assez verbeux, pas très Pythonique (une factory qui instancie un classe a qui on passe une autre instance, c&#8217;est très java), ça n’exploite pas toute la force de <code>async</code>/<code>await</code> (le <code>while</code> qui pourrait être un <code>async for</code>), et il faut se soucier de lancer la boucle. </p>
<p>En prime, c&#8217;est pas encore évident de trouver qu&#8217;il faut faire ça dans la doc.</p>
<p>Pareil, pour lire de manière asynchrone les données écrites par un utilisateur sur stdin:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> on_stdin<span style="color: black;">&#40;</span>*args<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;Somebody wrote:&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #dc143c;">sys</span>.<span style="color: black;">stdin</span>.<span style="color: #dc143c;">readline</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
loop <span style="color: #66cc66;">=</span> asyncio.<span style="color: black;">get_event_loop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
loop.<span style="color: black;">add_reader</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">stdin</span>.<span style="color: black;">fileno</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> on_stdin<span style="color: black;">&#41;</span>
loop.<span style="color: black;">run_forever</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Bon, là on a du callback, clairement on peut faire mieux. </p>
<p>La bonne nouvelle, c&#8217;est que ça veut dire qu&#8217;on a un champ entier où on peut être le premier à écrire une lib, et donc devenir une implémentation de référence, un outil connu, etc. Si vous avez envie de faire votre trou, c&#8217;est une opportunité, et en plus, c&#8217;est rigolo :)</p>
<p>En effet, avec un peu d&#8217;enrobage, on peut rapidement faire des trucs choupinets:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> AioStdinPipe:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> loop<span style="color: #66cc66;">=</span><span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">loop</span> <span style="color: #66cc66;">=</span> loop <span style="color: #ff7700;font-weight:bold;">or</span> asyncio.<span style="color: black;">get_event_loop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">reader</span> <span style="color: #66cc66;">=</span> asyncio.<span style="color: black;">StreamReader</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> get_reader<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> asyncio.<span style="color: black;">StreamReaderProtocol</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">reader</span><span style="color: black;">&#41;</span>
&nbsp;
    async <span style="color: #ff7700;font-weight:bold;">def</span> __aiter__<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        await <span style="color: #008000;">self</span>.<span style="color: black;">loop</span>.<span style="color: black;">connect_read_pipe</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">get_reader</span><span style="color: #66cc66;">,</span> <span style="color: #dc143c;">sys</span>.<span style="color: black;">stdin</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>
&nbsp;
    async <span style="color: #ff7700;font-weight:bold;">def</span> __anext__<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;">while</span> <span style="color: #008000;">True</span>:
            val <span style="color: #66cc66;">=</span> await <span style="color: #008000;">self</span>.<span style="color: black;">reader</span>.<span style="color: #dc143c;">readline</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> val <span style="color: #66cc66;">==</span> b<span style="color: #483d8b;">''</span>:
                <span style="color: #ff7700;font-weight:bold;">raise</span> StopAsyncIteration
            <span style="color: #ff7700;font-weight:bold;">return</span> val
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> run_in_loop<span style="color: black;">&#40;</span>coro<span style="color: black;">&#41;</span>:
    loop <span style="color: #66cc66;">=</span> asyncio.<span style="color: black;">get_event_loop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    loop.<span style="color: black;">run_until_complete</span><span style="color: black;">&#40;</span>coro<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Et ainsi réduire le premier code à un truc très simple, très clair, très Python:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">@</span>run_in_loop
async <span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    async <span style="color: #ff7700;font-weight:bold;">for</span> line <span style="color: #ff7700;font-weight:bold;">in</span> AioStdinPipe<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>line<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>J&#8217;aime 2016, c&#8217;est une année pleine de possibilités.</p>


feed_id: http://sametmax.com/?p=18200
title: Il n’y a pas de mauvais script… 1 Recently updated !
uri: Il-n-y-a-pas-de-mauvais-script-1-Recently-updated
url: http://sametmax.com/il-ny-a-pas-de-mauvais-script/
content:
<blockquote><p>Ceci est un post invité de <a href="http://sametmax.com/author/atrament/">atrament </a>posté sous licence <a href="http://creativecommons.org/licenses/by/3.0/" target="_blank">creative common 3.0 unported</a>.</p></blockquote>
<p>&#8230; il n&#8217;y  a que des scripts en passe de devenir bons. Avis au débutants, croyez-y, vous ne le resterez pas.</p>
<p>C&#8217;est l&#8217;histoire d&#8217;un des premiers &#8220;vrais scripts&#8221; que j&#8217;ai écrits. Je venais de finir <a href="http://shop.oreilly.com/product/9781565924642.do">Learning Python</a> et <a href="http://shop.oreilly.com/product/9780596158118.do">Programming Python de Mark Lutz</a> (à l&#8217;époque la seconde édition <em>&#8220;couvre python 2 !&#8221;</em>).</p>
<p>J&#8217;étais même pas un script kiddie, et je ne programmais que pour m&#8217;amuser. J&#8217;étais fan de <a href="http://www.sinfest.net/">Sinfest</a>, un web comic gavé de gros blasphème qui tache.</p>
<p>Je me suis mis en tête de télécharger tout ces comics d&#8217;un coup. Voilà ce que ce script était, et ce qu&#8217;il est devenu.</p>
<p><a href="http://0bin.net/paste/X9fhVfT4zwHNwCGe#IksH-LwojHsPmoz6gtLFxeF2DU0u83J0eZCxY+P2N9O">Script originel avec formatage encore moins lisible, sur 0bin.</a></p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#~ Script to DL all sinfest webcomics</span>
<span style="color: #808080; font-style: italic;">#~ one can edit the START and END parameters to DL a subset</span>
STARTDAY <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">17</span>  <span style="color: #808080; font-style: italic;"># 17</span>
STARTMONTH <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">01</span>  <span style="color: #808080; font-style: italic;"># 01</span>
STARTYEAR <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">2011</span>  <span style="color: #808080; font-style: italic;"># 2000</span>
ENDDAY <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">31</span>
ENDMONTH <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">01</span>
ENDYEAR <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">2012</span>
ROOTDIR <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'Sinfest'</span>
ROOTURL <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;http://www.sinfest.net/comikaze/comics/&quot;</span>
IMGEXT <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;.gif&quot;</span>
<span style="color: #808080; font-style: italic;">#~ Code start - no edition from here unless you know what you're doing</span>
<span style="color: #808080; font-style: italic;">#~ --------------------</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">distutils</span>.<span style="color: black;">file_util</span> <span style="color: #ff7700;font-weight:bold;">import</span> copy_file
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">urllib</span> <span style="color: #ff7700;font-weight:bold;">import</span> urlopen
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #808080; font-style: italic;">#~ ROOTDIR=os.getcwd()+ROOTDIR</span>
<span style="color: #808080; font-style: italic;">#~ Check if date is out of range</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> checkdate<span style="color: black;">&#40;</span>d<span style="color: #66cc66;">,</span> m<span style="color: #66cc66;">,</span> y<span style="color: #66cc66;">,</span> ed<span style="color: #66cc66;">,</span> em<span style="color: #66cc66;">,</span> ey<span style="color: #66cc66;">,</span> sd<span style="color: #66cc66;">,</span> sm<span style="color: #66cc66;">,</span> sy<span style="color: black;">&#41;</span>:  <span style="color: #808080; font-style: italic;"># end date is ed, em, ey</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> y &amp;gt<span style="color: #66cc66;">;</span> ey <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: black;">&#40;</span>y <span style="color: #66cc66;">==</span> ey <span style="color: #ff7700;font-weight:bold;">and</span> m &amp;gt<span style="color: #66cc66;">;</span> em<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: black;">&#40;</span>y <span style="color: #66cc66;">==</span> ey <span style="color: #ff7700;font-weight:bold;">and</span> m <span style="color: #66cc66;">==</span> em <span style="color: #ff7700;font-weight:bold;">and</span> d &amp;gt<span style="color: #66cc66;">;</span> ed<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #ff4500;">0</span>  <span style="color: #808080; font-style: italic;"># date over date range</span>
    <span style="color: #ff7700;font-weight:bold;">elif</span> y &amp;lt<span style="color: #66cc66;">;</span> sy <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: black;">&#40;</span>y <span style="color: #66cc66;">==</span> sy <span style="color: #ff7700;font-weight:bold;">and</span> m &amp;lt<span style="color: #66cc66;">;</span> sm<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: black;">&#40;</span>y <span style="color: #66cc66;">==</span> sy <span style="color: #ff7700;font-weight:bold;">and</span> m <span style="color: #66cc66;">==</span> sm <span style="color: #ff7700;font-weight:bold;">and</span> d &amp;lt<span style="color: #66cc66;">;</span> sd<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #ff4500;">0</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #ff4500;">1</span>  <span style="color: #808080; font-style: italic;"># date below end date and above start date</span>
<span style="color: #808080; font-style: italic;">#~ make the file name teh sae format than sinfest server</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> getfilename<span style="color: black;">&#40;</span>y<span style="color: #66cc66;">,</span> m<span style="color: #66cc66;">,</span> d<span style="color: #66cc66;">,</span> IMGEXT<span style="color: black;">&#41;</span>:
    M <span style="color: #66cc66;">=</span>`m`
    D <span style="color: #66cc66;">=</span>`d`
    Y <span style="color: #66cc66;">=</span>`y`
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>M<span style="color: black;">&#41;</span> &amp;lt<span style="color: #66cc66;">;</span> <span style="color: #ff4500;">2</span>:
        M <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'0'</span> + M
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>D<span style="color: black;">&#41;</span> &amp;lt<span style="color: #66cc66;">;</span> <span style="color: #ff4500;">2</span>:
        D <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'0'</span> + D
    filename <span style="color: #66cc66;">=</span> Y + <span style="color: #483d8b;">'-'</span> + M + <span style="color: #483d8b;">'-'</span> + D + IMGEXT
    <span style="color: #ff7700;font-weight:bold;">return</span> filename
<span style="color: #808080; font-style: italic;">#~ run the loop</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;">isdir</span><span style="color: black;">&#40;</span>ROOTDIR<span style="color: black;">&#41;</span>:
    <span style="color: #dc143c;">os</span>.<span style="color: black;">mkdir</span><span style="color: black;">&#40;</span>ROOTDIR<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> y <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span>STARTYEAR<span style="color: #66cc66;">,</span> ENDYEAR + <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">for</span> m <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;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">13</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">for</span> d <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;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">32</span><span style="color: black;">&#41;</span>:
            filename <span style="color: #66cc66;">=</span> getfilename<span style="color: black;">&#40;</span>y<span style="color: #66cc66;">,</span> m<span style="color: #66cc66;">,</span> d<span style="color: #66cc66;">,</span> IMGEXT<span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> checkdate<span style="color: black;">&#40;</span>d<span style="color: #66cc66;">,</span> m<span style="color: #66cc66;">,</span> y<span style="color: #66cc66;">,</span> ENDDAY<span style="color: #66cc66;">,</span> ENDMONTH<span style="color: #66cc66;">,</span> ENDYEAR<span style="color: #66cc66;">,</span>
                         STARTDAY<span style="color: #66cc66;">,</span> STARTMONTH<span style="color: #66cc66;">,</span> STARTYEAR<span style="color: black;">&#41;</span>:
                <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">isfile</span><span style="color: black;">&#40;</span>ROOTDIR + <span style="color: #483d8b;">'/'</span> + filename<span style="color: black;">&#41;</span>:
                    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'['</span> + filename + <span style="color: #483d8b;">'] already exists'</span>
                <span style="color: #ff7700;font-weight:bold;">else</span>:
                    src <span style="color: #66cc66;">=</span> urlopen<span style="color: black;">&#40;</span>ROOTURL + filename<span style="color: black;">&#41;</span>
                    <span style="color: #ff7700;font-weight:bold;">if</span> src.<span style="color: black;">info</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">gettype</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">'image/gif'</span>:
                        dst <span style="color: #66cc66;">=</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>ROOTDIR + <span style="color: #483d8b;">'/'</span> + filename<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'wb'</span><span style="color: black;">&#41;</span>
                        dst.<span style="color: black;">write</span><span style="color: black;">&#40;</span>src.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
                        dst.<span style="color: black;">close</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: #483d8b;">'['</span> + filename + <span style="color: #483d8b;">']'</span> + <span style="color: #483d8b;">' copied'</span>
                    <span style="color: #ff7700;font-weight:bold;">else</span>:
                        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;MIMETYPE ERROR (probably ERROR 404) ignored&quot;</span>
                    src.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>On remarquera l&#8217;arrogance du jeune codeur fier de lui dans certains commentaires. Ils étaient à mon intention, en vrai, et montraient surtout que je ne savais pas trop ce que je faisais.</p>
<p>En vrac, parmi les choses qui me font sourire aujourd&#8217;hui :</p>
<ul>
<li>la fonction <code>checkdate</code> qui prend 9 paramètres pour vérifier si une date est entre deux autres,</li>
<li>les grosses constantes au début</li>
<li>la portabilité nulle du script qui doit être lancé au bon endroit</li>
<li>la date codée avec 3 boucles pour l&#8217;année, le mois, le jour.</li>
<li>Je ne parle même pas de la pep008, elle n&#8217;avait même pas un an, d&#8217;abord, et puis visiblement on était loin des questions de style&#8230;</li>
</ul>
<p>Bon, il y a prescription, et puis je suis pas mal autodidacte, c&#8217;était pas si mal : ça fonctionnait ! Ça m&#8217;a quand même servi, de temps en temps, jusque 2012, pour remettre à jour mes dossiers d&#8217;images.</p>
<hr />
<p>Et puis je l&#8217;ai relu et j&#8217;ai décidé de le reprendre avec ce que je savais de nouveau :</p>
<ul>
<li>le module <code>datetime</code>,</li>
<li>la construction <code>if __name__ == '__main__'</code>,</li>
<li>les exceptions,</li>
</ul>
<p>et ça a donné ça :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
<span style="color: #808080; font-style: italic;">#! /usr/bin/python</span>
<span style="color: #808080; font-style: italic;"># Script to DL all sinfest webcomics</span>
<span style="color: #808080; font-style: italic;"># one can edit the START and END parameters to DL a subset</span>
<span style="color: #808080; font-style: italic;">#-------------------------------------------------------------------------------</span>
<span style="color: #808080; font-style: italic;"># Name:        getSinfest</span>
<span style="color: #808080; font-style: italic;"># Purpose:</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># Author:      Atrament</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># Created:     12/04/2013</span>
<span style="color: #808080; font-style: italic;"># Copyright:   (c) Atrament 2013</span>
<span style="color: #808080; font-style: italic;"># Licence:     </span>
<span style="color: #808080; font-style: italic;">#-------------------------------------------------------------------------------</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">datetime</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">urllib</span>.<span style="color: black;">request</span> <span style="color: #ff7700;font-weight:bold;">import</span> urlopen
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">urllib</span>.<span style="color: black;">error</span> <span style="color: #ff7700;font-weight:bold;">import</span> HTTPError
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    debut<span style="color: #66cc66;">=</span><span style="color: #dc143c;">datetime</span>.<span style="color: black;">date</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2000</span><span style="color: #66cc66;">,</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span><span style="color: #ff4500;">17</span><span style="color: black;">&#41;</span>
    curGif<span style="color: #66cc66;">=</span>debut
    <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;">isdir</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Sinfest&quot;</span><span style="color: black;">&#41;</span>:
        <span style="color: #dc143c;">os</span>.<span style="color: black;">mkdir</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Sinfest&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">while</span> curGif&amp;lt<span style="color: #66cc66;">;=</span><span style="color: #dc143c;">datetime</span>.<span style="color: black;">date</span>.<span style="color: black;">today</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">isfile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Sinfest/&quot;</span>+curGif.<span style="color: black;">isoformat</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>+<span style="color: #483d8b;">&quot;.gif&quot;</span><span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">try</span>:
                src<span style="color: #66cc66;">=</span>urlopen<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;http://www.sinfest.net/comikaze/comics/&quot;</span>+curGif.<span style="color: black;">isoformat</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>+<span style="color: #483d8b;">&quot;.gif&quot;</span><span style="color: black;">&#41;</span>
                dst<span style="color: #66cc66;">=</span><span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Sinfest/&quot;</span>+curGif.<span style="color: black;">isoformat</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>+<span style="color: #483d8b;">&quot;.gif&quot;</span><span style="color: #66cc66;">,</span><span style="color: #483d8b;">'wb'</span><span style="color: black;">&#41;</span>
                dst.<span style="color: black;">write</span><span style="color: black;">&#40;</span>src.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
                dst.<span style="color: black;">close</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;    &quot;</span>+curGif.<span style="color: black;">isoformat</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>+<span style="color: #483d8b;">&quot;.gif : fetched.&quot;</span><span style="color: black;">&#41;</span>
                src.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">except</span> HTTPError <span style="color: #ff7700;font-weight:bold;">as</span> e:
                <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;on &quot;</span>+curGif.<span style="color: black;">isoformat</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>+<span style="color: #483d8b;">&quot; error happened. So is life.&quot;</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>curGif.<span style="color: black;">isoformat</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>+<span style="color: #483d8b;">&quot; : ok&quot;</span><span style="color: black;">&#41;</span>
        curGif+<span style="color: #66cc66;">=</span><span style="color: #dc143c;">datetime</span>.<span style="color: black;">timedelta</span><span style="color: black;">&#40;</span>days<span style="color: #66cc66;">=</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">'__main__'</span>:
    main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Et honnêtement ça s&#8217;améliore (un peu): un shebang (pas tout à fait en haut du fichier, mais j&#8217;apprendrai plus tard), bien que je code à l&#8217;époque uniquement sous windows avec pyscripter, qui me fournit les commentaires de début de fichier, qui ne servent à rien, mais à l&#8217;époque m&#8217;éclatent. Ben oui, à ce moment là, je suis à peine adulte, et avec les heures que j&#8217;ai passé sur IDLE à tâtonnner, c&#8217;est une victoire pour moi.</p>
<hr />
<p>C&#8217;est un peu plus tard encore que j&#8217;apprends que les requêtes internet qui prennent des heures, c&#8217;est pas obligatoire, parce qu&#8217;on peut faire du <em>multi thread</em>, et continuer de tourner pendant qu&#8217;on attend qu&#8217;une autre tâche s&#8217;accomplisse. Voilà de quoi faire rêver un jeune programmeur : la puissance du multi-coeurs à la portée de mon code ! (non, je ne savais pas que c&#8217;est faux). En conséquence, mon script évolue, pour devenir&#8230; ça. Attention, ça pique les yeux.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># -*- coding: UTF-8 -*-</span>
<span style="color: #808080; font-style: italic;"># ---------------------------------------------------------------------</span>
<span style="color: #808080; font-style: italic;"># Author:      Atrament</span>
<span style="color: #808080; font-style: italic;"># Licence:     CC-BY-SA https://creativecommons.org/licenses/by-sa/4.0/</span>
<span style="color: #808080; font-style: italic;"># ---------------------------------------------------------------------</span>
<span style="color: #808080; font-style: italic;"># All libs are part of standard distribution for python 3.4</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">imghdr</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> queue
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">threading</span> <span style="color: #ff7700;font-weight:bold;">import</span> Thread
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">datetime</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">urllib</span>.<span style="color: black;">error</span> <span style="color: #ff7700;font-weight:bold;">import</span> HTTPError<span style="color: #66cc66;">,</span> URLError
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">urllib</span>.<span style="color: black;">request</span> <span style="color: #ff7700;font-weight:bold;">import</span> urlopen
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">zipfile</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;"># Useful functions</span>
<span style="color: #ff7700;font-weight:bold;">def</span> make_cbz<span style="color: black;">&#40;</span>directory<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">for</span> year <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;">2000</span><span style="color: #66cc66;">,</span> <span style="color: #dc143c;">datetime</span>.<span style="color: black;">date</span>.<span style="color: black;">today</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">year</span> + <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #dc143c;">zipfile</span>.<span style="color: black;">ZipFile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Sinfest-{}.cbz&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>year<span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;w&quot;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> archive:
            <span style="color: #ff7700;font-weight:bold;">for</span> gif_file <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#91;</span>x <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">listdir</span><span style="color: black;">&#40;</span>directory<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> x.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;-&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span> <span style="color: #66cc66;">==</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>year<span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>:
                archive.<span style="color: black;">write</span><span style="color: black;">&#40;</span>directory + <span style="color: #483d8b;">'/'</span> + gif_file<span style="color: #66cc66;">,</span> arcname<span style="color: #66cc66;">=</span>gif_file<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;Sinfest-{}.cbz has been generated&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>year<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> confirm<span style="color: black;">&#40;</span>prompt<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">input</span><span style="color: black;">&#40;</span>prompt + <span style="color: #483d8b;">&quot; (y/n)&quot;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #483d8b;">&quot;yY&quot;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">True</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">False</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> file_needs_download<span style="color: black;">&#40;</span>filename<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Checks whether a file exists, is corrupt, so has to be downloaded again
    also cleans garbage if detected&quot;&quot;&quot;</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>filename<span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;"># many comics are *supposed* to be missing,</span>
        <span style="color: #808080; font-style: italic;"># no need to output for these (uncomment for debug)</span>
        <span style="color: #808080; font-style: italic;"># print(&quot;IS NOT FILE :&quot;, filename)</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">True</span>
    <span style="color: #ff7700;font-weight:bold;">elif</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">getsize</span><span style="color: black;">&#40;</span>filename<span style="color: black;">&#41;</span> <span style="color: #66cc66;">==</span> <span style="color: #ff4500;">0</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;WRONG SIZE for&quot;</span><span style="color: #66cc66;">,</span> filename<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">True</span>
    <span style="color: #ff7700;font-weight:bold;">elif</span> filename.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;.&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span>-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span> <span style="color: #66cc66;">!=</span> <span style="color: #483d8b;">&quot;gif&quot;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>filename<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;IS NOT GIF&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">True</span>
    <span style="color: #ff7700;font-weight:bold;">elif</span> filename.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;.&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span>-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;jpg&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;gif&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;png&quot;</span><span style="color: black;">&#125;</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #dc143c;">imghdr</span>.<span style="color: black;">what</span><span style="color: black;">&#40;</span>filename<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">None</span>:
        <span style="color: #808080; font-style: italic;"># Encoding error...</span>
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;WRONG FILE STRUCTURE for&quot;</span><span style="color: #66cc66;">,</span> filename<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">True</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">False</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> conditional_download<span style="color: black;">&#40;</span>filename<span style="color: #66cc66;">,</span> base_url<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> file_needs_download<span style="color: black;">&#40;</span>filename<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">try</span>:
            src <span style="color: #66cc66;">=</span> urlopen<span style="color: black;">&#40;</span>base_url + filename<span style="color: black;">&#41;</span>
            dst <span style="color: #66cc66;">=</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>filename<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'wb'</span><span style="color: black;">&#41;</span>
            dst.<span style="color: black;">write</span><span style="color: black;">&#40;</span>src.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            <span style="color: #808080; font-style: italic;"># gracefully close theses accesses.</span>
            dst.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            src.<span style="color: black;">close</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;<span style="color: #000099; font-weight: bold;">\t</span>&quot;</span> + filename + <span style="color: #483d8b;">&quot; : fetched.&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">except</span> HTTPError:
            <span style="color: #808080; font-style: italic;"># many days do not have a comic published.</span>
            <span style="color: #808080; font-style: italic;"># no need to flood the console for this.</span>
            <span style="color: #ff7700;font-weight:bold;">pass</span>
        <span style="color: #ff7700;font-weight:bold;">except</span> URLError:
            <span style="color: #ff7700;font-weight:bold;">pass</span>
            <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;network error on &quot;</span> + filename<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">finally</span>:
            <span style="color: #808080; font-style: italic;"># clean garbage on disk, useful if failure occurred.</span>
            file_needs_download<span style="color: black;">&#40;</span>filename<span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> ThreadedWorker<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> function<span style="color: #66cc66;">=</span><span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> number_of_threads<span style="color: #66cc66;">=</span><span style="color: #ff4500;">8</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">queue</span> <span style="color: #66cc66;">=</span> queue.<span style="color: #dc143c;">Queue</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">def</span> func<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:
                item <span style="color: #66cc66;">=</span> <span style="color: #008000;">self</span>.<span style="color: black;">queue</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
                <span style="color: #ff7700;font-weight:bold;">if</span> function:
                    function<span style="color: black;">&#40;</span>item<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>item<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;is being processed.&quot;</span><span style="color: black;">&#41;</span>
                <span style="color: #008000;">self</span>.<span style="color: black;">queue</span>.<span style="color: black;">task_done</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #008000;">self</span>.<span style="color: black;">function</span> <span style="color: #66cc66;">=</span> func
&nbsp;
        <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>number_of_threads<span style="color: black;">&#41;</span>:
            t <span style="color: #66cc66;">=</span> Thread<span style="color: black;">&#40;</span>target<span style="color: #66cc66;">=</span><span style="color: #008000;">self</span>.<span style="color: black;">function</span><span style="color: #66cc66;">,</span> name<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;Thread-{:03}&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            t.<span style="color: black;">daemon</span> <span style="color: #66cc66;">=</span> <span style="color: #008000;">True</span>
            t.<span style="color: black;">start</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> put<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> object_to_queue<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">queue</span>.<span style="color: black;">put</span><span style="color: black;">&#40;</span>object_to_queue<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> join<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">queue</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> feed<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> iterator<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">for</span> task <span style="color: #ff7700;font-weight:bold;">in</span> iterator:
            <span style="color: #008000;">self</span>.<span style="color: black;">queue</span>.<span style="color: black;">put</span><span style="color: black;">&#40;</span>task<span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> download_sinfest<span style="color: black;">&#40;</span>target_folder<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
    Creates a directory and fetches Sinfest comics to populate it in full.
    &quot;&quot;&quot;</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;">isdir</span><span style="color: black;">&#40;</span>target_folder<span style="color: black;">&#41;</span>:
        <span style="color: #dc143c;">os</span>.<span style="color: black;">makedirs</span><span style="color: black;">&#40;</span>target_folder<span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">os</span>.<span style="color: black;">chdir</span><span style="color: black;">&#40;</span>target_folder<span style="color: black;">&#41;</span>
&nbsp;
    f <span style="color: #66cc66;">=</span> <span style="color: #ff7700;font-weight:bold;">lambda</span> filename: conditional_download<span style="color: black;">&#40;</span>filename<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;http://www.sinfest.net/btphp/comics/&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># Make a worker with this function and run it</span>
    t <span style="color: #66cc66;">=</span> ThreadedWorker<span style="color: black;">&#40;</span>function<span style="color: #66cc66;">=</span>f<span style="color: #66cc66;">,</span> number_of_threads<span style="color: #66cc66;">=</span><span style="color: #ff4500;">20</span><span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># structure of comprehended list is a bit complex to generate all file names</span>
    files <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">datetime</span>.<span style="color: black;">date</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2000</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">17</span><span style="color: black;">&#41;</span> + <span style="color: #dc143c;">datetime</span>.<span style="color: black;">timedelta</span><span style="color: black;">&#40;</span>days<span style="color: #66cc66;">=</span>x<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>.<span style="color: black;">isoformat</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> + <span style="color: #483d8b;">&quot;.gif&quot;</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: black;">&#40;</span><span style="color: #dc143c;">datetime</span>.<span style="color: black;">date</span>.<span style="color: black;">today</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> - <span style="color: #dc143c;">datetime</span>.<span style="color: black;">date</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2000</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">17</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>.<span style="color: black;">days</span> + <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
    t.<span style="color: black;">feed</span><span style="color: black;">&#40;</span>files<span style="color: black;">&#41;</span>
    t.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">any</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;y&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;Y&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;-y&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;-Y&quot;</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
        folder <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">expanduser</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;~/Pictures/Sinfest/&quot;</span><span style="color: black;">&#41;</span>.<span style="color: black;">replace</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\\</span>&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;/&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>proceeding to download...&quot;</span><span style="color: black;">&#41;</span>
        download_sinfest<span style="color: black;">&#40;</span>folder<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;<span style="color: #000099; font-weight: bold;">\n</span>generating comic book files (.cbz)...&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">os</span>.<span style="color: black;">chdir</span><span style="color: black;">&#40;</span>folder<span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">os</span>.<span style="color: black;">chdir</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;..&quot;</span><span style="color: black;">&#41;</span>
        make_cbz<span style="color: black;">&#40;</span>folder<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        folder <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">expanduser</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;~/Pictures/Sinfest/&quot;</span><span style="color: black;">&#41;</span>.<span style="color: black;">replace</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\\</span>&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;/&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff7700;font-weight:bold;">not</span> confirm<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Target to downloads is {} ?&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>folder<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
            folder <span style="color: #66cc66;">=</span> <span style="color: #008000;">input</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Please enter new folder (N to abort) :&quot;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> folder <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #483d8b;">&quot;nN&quot;</span>:
                exit<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> confirm<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Proceed to download ?&quot;</span><span style="color: black;">&#41;</span>:
            download_sinfest<span style="color: black;">&#40;</span>folder<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> confirm<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Do you want to generate cbz (comic books) files ?&quot;</span><span style="color: black;">&#41;</span>:
            <span style="color: #dc143c;">os</span>.<span style="color: black;">chdir</span><span style="color: black;">&#40;</span>folder<span style="color: black;">&#41;</span>
            <span style="color: #dc143c;">os</span>.<span style="color: black;">chdir</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;..&quot;</span><span style="color: black;">&#41;</span>
            make_cbz<span style="color: black;">&#40;</span>folder<span style="color: black;">&#41;</span>
        <span style="color: #008000;">input</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Finished. Please press Enter&quot;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>C&#8217;est une horreur. Si vous êtes de ces perfectionnistes qui lisent le code et font la code review par habitude, je suis désolé, vous avez du pleurer.  Le commentaire sur la lib standard &#8220;en intro&#8221; montre que à ce moment là, j&#8217;ai un peu conscience qu&#8217;on peut accéder à d&#8217;autres modules, mais on est loin de pip pour moi. Je tente maladroitement d&#8217;exploiter <code>sys.argv</code> (avec des erreurs qui pourraient être catastrophiques),  et l&#8217;input à défaut. Une fonctionnalité neuve est apparue : faire des archives comic book en zip. Je suis fier.</p>
<p>Mais le côté comique de ce code, c&#8217;est la classe <code>ThreadedWorker</code>. C&#8217;est ptêt bien ma première &#8216;vraie&#8217; classe, mais j&#8217;implémente moi-même un dispatcheur de jobs sur des threads. Il y a de quoi être fier, mais on n&#8217;est pas du tout dans du python propre, là. C&#8217;est ballot, la version précédente était pas si mal, niveau clarté.</p>
<p>et dire que la lib standard en fournit un, de dispacheur de jobs&#8230;</p>
<hr />
<p>Je passe quelques itérations sur des détails, aujourd&#8217;hui il en est là, ce script.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#! /usr/bin/env python3.5</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">imghdr</span>
<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;">datetime</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">zipfile</span>
<span style="color: #ff7700;font-weight:bold;">from</span> concurrent.<span style="color: black;">futures</span> <span style="color: #ff7700;font-weight:bold;">import</span> ThreadPoolExecutor
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> requests
<span style="color: #ff7700;font-weight:bold;">import</span> begin
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;"># Useful functions</span>
<span style="color: #ff7700;font-weight:bold;">def</span> make_cbz<span style="color: black;">&#40;</span>dst_directory<span style="color: #66cc66;">,</span> src_directory<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">for</span> year <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;">2000</span><span style="color: #66cc66;">,</span> <span style="color: #dc143c;">datetime</span>.<span style="color: black;">date</span>.<span style="color: black;">today</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">year</span> + <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #dc143c;">zipfile</span>.<span style="color: black;">ZipFile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Sinfest-{}.cbz&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>year<span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;w&quot;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> archive:
            <span style="color: #ff7700;font-weight:bold;">for</span> filename <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">listdir</span><span style="color: black;">&#40;</span>src_directory<span style="color: black;">&#41;</span>:
                <span style="color: #ff7700;font-weight:bold;">if</span> filename.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#40;</span>year<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
                    archive.<span style="color: black;">write</span><span style="color: black;">&#40;</span>src_directory + <span style="color: #483d8b;">&quot;/&quot;</span> + filename<span style="color: #66cc66;">,</span> arcname<span style="color: #66cc66;">=</span>filename<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;Sinfest-{}.cbz has been generated&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>year<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> file_needs_download<span style="color: black;">&#40;</span>filename<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Checks whether a file exists, is corrupt, so has to be downloaded again
    also cleans garbage if detected&quot;&quot;&quot;</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>filename<span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;"># many comics are *supposed* to be missing,</span>
        <span style="color: #808080; font-style: italic;"># no need to output for these (uncomment for debug)</span>
        <span style="color: #808080; font-style: italic;"># print(&quot;IS NOT FILE :&quot;, filename)</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">True</span>
    <span style="color: #ff7700;font-weight:bold;">elif</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">getsize</span><span style="color: black;">&#40;</span>filename<span style="color: black;">&#41;</span> <span style="color: #66cc66;">==</span> <span style="color: #ff4500;">0</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;WRONG SIZE for&quot;</span><span style="color: #66cc66;">,</span> filename<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">True</span>
    <span style="color: #ff7700;font-weight:bold;">elif</span> filename.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;.&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span>-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span> <span style="color: #66cc66;">!=</span> <span style="color: #483d8b;">&quot;gif&quot;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>filename<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;IS NOT GIF&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">True</span>
    <span style="color: #ff7700;font-weight:bold;">elif</span> filename.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;.&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span>-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;jpg&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;gif&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;png&quot;</span><span style="color: black;">&#125;</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #dc143c;">imghdr</span>.<span style="color: black;">what</span><span style="color: black;">&#40;</span>filename<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">None</span>:
        <span style="color: #808080; font-style: italic;"># Encoding error...</span>
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;WRONG FILE STRUCTURE for&quot;</span><span style="color: #66cc66;">,</span> filename<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">True</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">False</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> conditional_download<span style="color: black;">&#40;</span>filename<span style="color: #66cc66;">,</span> base_url<span style="color: #66cc66;">,</span> caller<span style="color: #66cc66;">=</span><span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> file_needs_download<span style="color: black;">&#40;</span>filename<span style="color: black;">&#41;</span>:
        src <span style="color: #66cc66;">=</span> requests.<span style="color: black;">get</span><span style="color: black;">&#40;</span>base_url + filename<span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># manage failure to download</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> src.<span style="color: black;">status_code</span> <span style="color: #66cc66;">==</span> <span style="color: #ff4500;">404</span>:
            src.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">return</span>  <span style="color: #808080; font-style: italic;"># ignore it, that file is simply missing.</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> src.<span style="color: black;">status_code</span> <span style="color: #66cc66;">!=</span> <span style="color: #ff4500;">200</span>:  <span style="color: #808080; font-style: italic;"># an error other than 404 occurred</span>
            <span style="color: #808080; font-style: italic;"># print(&quot;Error {} on {}&quot;.format(src.status_code, filename))</span>
            src.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> caller:  <span style="color: #808080; font-style: italic;"># retry that file later</span>
                caller.<span style="color: black;">submit</span><span style="color: black;">&#40;</span>conditional_download<span style="color: #66cc66;">,</span> filename<span style="color: #66cc66;">,</span> base_url<span style="color: #66cc66;">,</span> caller<span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># actually copy that file</span>
        dst <span style="color: #66cc66;">=</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>filename<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'wb'</span><span style="color: black;">&#41;</span>
        dst.<span style="color: black;">write</span><span style="color: black;">&#40;</span>src.<span style="color: black;">content</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># gracefully close theses accesses.</span>
        dst.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        src.<span style="color: black;">close</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;<span style="color: #000099; font-weight: bold;">\t</span>{} : fetched.&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>filename<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> download_sinfest<span style="color: black;">&#40;</span>target_folder<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
    Source function for the process
    Creates a directory and fetches Sinfest comics to populate it in full.
    &quot;&quot;&quot;</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;">isdir</span><span style="color: black;">&#40;</span>target_folder<span style="color: black;">&#41;</span>:
        <span style="color: #dc143c;">os</span>.<span style="color: black;">makedirs</span><span style="color: black;">&#40;</span>target_folder<span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">os</span>.<span style="color: black;">chdir</span><span style="color: black;">&#40;</span>target_folder<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">with</span> ThreadPoolExecutor<span style="color: black;">&#40;</span>max_workers<span style="color: #66cc66;">=</span><span style="color: #ff4500;">64</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> executor:
        <span style="color: #ff7700;font-weight:bold;">for</span> <span style="color: #008000;">file</span> <span style="color: #ff7700;font-weight:bold;">in</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: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">datetime</span>.<span style="color: black;">date</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2000</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">17</span><span style="color: black;">&#41;</span> + <span style="color: #dc143c;">datetime</span>.<span style="color: black;">timedelta</span><span style="color: black;">&#40;</span>days<span style="color: #66cc66;">=</span>x<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>.<span style="color: black;">isoformat</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;.gif&quot;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
                     <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">datetime</span>.<span style="color: black;">date</span>.<span style="color: black;">today</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> - <span style="color: #dc143c;">datetime</span>.<span style="color: black;">date</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2000</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">17</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>.<span style="color: black;">days</span> + <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
            executor.<span style="color: black;">submit</span><span style="color: black;">&#40;</span>conditional_download<span style="color: #66cc66;">,</span> <span style="color: #008000;">file</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;http://www.sinfest.net/btphp/comics/&quot;</span><span style="color: #66cc66;">,</span> executor<span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #66cc66;">@</span>begin.<span style="color: black;">start</span>
<span style="color: #ff7700;font-weight:bold;">def</span> run<span style="color: black;">&#40;</span>path: <span style="color: #483d8b;">&quot;folder in which the comics must be downloaded&quot;</span> <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">expanduser</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;~/Sinfest/&quot;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span>
        makecbz: <span style="color: #483d8b;">&quot;Compile CBZ comic book archives&quot;</span> <span style="color: #66cc66;">=</span> <span style="color: #008000;">False</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Download the Sinfest WebComics&quot;&quot;&quot;</span>
    download_sinfest<span style="color: black;">&#40;</span>path<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> makecbz:
        dst <span style="color: #66cc66;">=</span> path<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;">if</span> path.<span style="color: black;">endswith</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;">else</span> path
        dst <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;/&quot;</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>dst.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;/&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span>:-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        make_cbz<span style="color: black;">&#40;</span>dst<span style="color: #66cc66;">,</span> path<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;Finished. Goodbye.&quot;</span><span style="color: black;">&#41;</span>
    exit<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Enfin je m&#8217;autorise à utiliser des modules tierces. Alors, ça marche, même plutôt vite et bien. Mais c&#8217;est largement perfectible : si c&#8217;est mieux que par le passé, ça ne correspond pas à ce que je code aujourd&#8217;hui : il y a beaucoup de code hérité des anciennes versions et la prochaine évolution serait de le réécrire entièrement. Mais je ne lis plus vraiment Sinfest.</p>
<hr />
<p>&nbsp;</p>
<p>Mais à écrire ce texte, j&#8217;ai pris les nerfs, et j&#8217;ai refait tout ça. J&#8217;ai fait un effort, et <a href="https://github.com/AlbericC/comics-downloader">j&#8217;ai tout jeté à github</a>.</p>
<p>Encore un pas de mieux : les fichiers ont du sens, il y a une classe abstraite pour faire une pseudo-API, c&#8217;est devenu pratiquement évolutif.</p>
<p>&nbsp;</p>
<p>La conclusion à l&#8217;attention du débutant : chacun voit et juge son code et celui des autres selon son niveau e compétence à l&#8217;instant T. On a tous été fiers comme Artaban de bouts de code laids à nos yeux d&#8217;aujourd&#8217;hui. Débutant qui m&#8217;a lu (merci, t&#8217;as bien du courage), garde tes scripts à travers les années, reprends les, tu te rendras compte de tous les progrès que tu fais au fil du temps. Quand un type te dis sur internet que ce que tu fais n&#8217;est pas &#8220;pythonique&#8221;, il a sûrement raison, de son point de vue, et il y a sans doute un autre gars qui lui dira la même chose demain. La courbe d&#8217;apprentissage est longue comme la vie.</p>


feed_id: http://sametmax.com/?p=18144
title: Les interpréteurs alternatifs de python Recently updated !
uri: Les-interpréteurs-alternatifs-de-python-Recently-updated
url: http://sametmax.com/les-interpreteurs-alternatifs-de-python/
content:
<blockquote><p>Ceci est un post invité de <a href="http://sametmax.com/author/deronnax/">deronnax </a>posté sous licence <a href="http://creativecommons.org/licenses/by/3.0/" target="_blank">creative common 3.0 unported</a>.</p></blockquote>
<p>Bonjour, tous.<br />
Vu qu&#8217;un des derniers posts de Sam&#038;Max parlait de vitesse et des implémentation alternatives de Python, je propose un article sur l&#8217;état de ces différentes implémentations justement, et leur rapport à la vitesse.</p>
<p>Je commence par un petit rappel, pour nos lecteurs les moins aguerris avec l&#8217;écosystème Python : Python est un langage et aussi un interpréteur de référence, dont le vrai nom est CPython, écrit en C, qui livre également la bibliothèque standard Python (les modules datetime, urllib, collections, etc). CPython a des performances typiques de langage de script comme PHP ou Ruby, c&#8217;est à dire pas terribles, et a une conception assez simple, qui utilise des solutions simples pour répondre aux problèmes de langages de script. Celles qui font le plus parler d&#8217;elles (en mal évidement) étant la gestion de la mémoire par comptage de références (references counting), considérée moins performant qu&#8217;un vrai ramasse-miette (garbage collector) et assez limitée, et un verrou global de l&#8217;interpréteur, dont vous avez déjà dû entendre parler, le très mal-aimé GIL (Global Interpreter Lock), qui empêche entre autre à CPython d&#8217;avoir de vrai threads, c&#8217;est à dire des portions de code s&#8217;exécutant en réellement en même temps, concurremment, sur des cœurs processeurs différents. Néanmoins, rappelons-le encore : ces solutions permettent d&#8217;avoir une interpréteur simple et clair, pour lequel écrire des modules d&#8217;extensions en C est simple, ce qui est considéré actuellement comme plus important. De plus, CPython lui-même n&#8217;ayant pas des performances significatives, du vrai multithread n&#8217;est pas un besoin pertinent. Si vous avez besoin de faire des traitements lourds, 9 fois sur 10 une bibliothèque spécialisée en C s&#8217;en occupe et fait elle même le traitement lourds en C dans ses threads, tel qu&#8217;OpenCV ou NumPy. En général vous avez très rarement besoin de vrai thread Python, et donc le GIL est relativement un faux problème.<br />
La communauté Python s&#8217;est adapté à cet absence de vrai concurrence, et différentes solutions sont apparus pour contourner le problème, je pense par exemple à l&#8217;excellent module multiprocessing, qui vous permet d&#8217;instancier différents interpréteurs et de les faire communiquer entre eux de manière transparente comme si c&#8217;était des threads.<br />
D&#8217;une manière générale, quand il sera question d&#8217;un interpréteur alternatif, quatre points intéresseront la communauté :</p>
<ul>
<li>a-t-il de meilleures performances que CPython ?</li>
<li>il y a-t-il un GIL/des vrais threads ?</li>
<li>il y a-t-il un vrai ramasse-miette ?</li>
<li>supporte-il les modules en C codés pour CPython ?</li>
</ul>
<p>Je ne parlerai ici que des interpréteurs se voulant concurrents de CPython et remplissant la même niche. Les interpréteurs remplissant une tache un peu différentes, et/ou nécessitant des modifications significative de la manière d&#8217;écrire du code Python, ou n&#8217;ayant pas un niveau d&#8217;aboutissement significatif ne seront pas abordés, comme Cython ou Stackless Python. Voici <a href="https://en.wikipedia.org/wiki/List_of_Python_software#Python_implementations">une liste complète des implémentations de python</a>.</p>
<p>Déjà, niveau implémentations alternatives, parlons des historiques Jython et IronPython ; ces deux projets sont des interpréteurs python tournant dans la JVM existante d’un autre langage, respectivement la JVM Java d&#8217;IBM et le CLR/.Net C# de Microsoft, apportant ainsi différents bénéfices, entre autre un vrai ramasse-miette et aussi des vrai threads qui carburent. Ils ont aussi en commun d’avoir été peu adoptés (très peu dans le cas d’IronPython) et qu’ils ne sont plus très vivants (très peu dans le cas d’IronPython, déjà lâché par Microsoft en 2010) : dernière release de Jython: mai 2015 ; IronPython: juin 2014. Ça fait mal. De plus, si à leur sortie ils donnaient par moment de meilleures performances que CPython, ce dernier s’est beaucoup amélioré et maintenant ils se valent au mieux. De plus, tous les deux sont très lourds, avec une empreinte mémoire beaucoup plus grosse et un temps de démarrage sans comparaison avec CPython. À déployer, c’est complètement la mort aussi, rien à voir avec apt-get install python/pypy. Très beaucoup la mort pour obtenir un IronPython qui tourne sous Mono sous Ubuntu. Ces projets sont bien partis pour disparaître s’ils ne changent pas. Et le support de python3 est inexistant pour tous les deux. Et vos modules codés en C, vous pouvez vous asseoir dessus.</p>
<p>Pour la petite histoire (anecdote à recaser en soirée pour briller), Jim Hugunin, le créateur de Jython, a commencé à écrire IronPython pour démontrer aux gens que la plateforme .Net était mauvaise et biens moins bonne que la JVM pour écrire une implémentation de langage. Jim a commencé à écrire une implémentation de Python en .Net, et à sa grande surprise a réussi à faire une implémentation très aboutie en peu de temps et a trouvé la plateforme .Net tellement géniale qu&#8217;il a quitté le projet Jython pour lancer IronPython.</p>
<p>Ensuite vient Pypy, l’interpréteur Python en python orienté vitesse. Pypy existe depuis une dizaine d&#8217;année et vise à être un drop-in remplacement de CPython, c’est à dire qu’ils suffit de l’installer et de changer les commandes “python truc” par “pypy truc” et hop ça marche. Ça fonctionne, à condition de ne pas utiliser de modules compilés en C. Si c’est néanmoins le cas, Pypy peut utiliser les modules en C de CPython moyennant recompilation, mais attention, les perfs sont moins bonne qu’avec CPython, dû au fait que l’API vient de CPython et impose à Pypy, un interfaçage/fonctionnement qui n’est pas le sien et ne supporte pas toute l&#8217;API. <a href="http://speed.pypy.org/">Pypy délivre actuellement des performances en moyenne sept fois supérieures à Cpython sur leur suite de tests</a>, ce qui est assez bluffant. Après, à chacun de considérer si la suite de test de Pypy est représentative d&#8217;une utilisation réelle, ce qui est le problème existentielle de chaque implémentation Python alternative qui vous met sous le nez un graphe montrant qu&#8217;elle est X fois plus rapide que CPython sur SA suite de tests. Pypy utilise également un GIL, donc ne fourni pas de vrais threads, mais a dans un coin <a href="http://doc.pypy.org/en/latest/faq.html#does-pypy-have-a-gil-why">un projet de passer à un modèle de concurrence qui permettrait de s&#8217;affranchir du GIL</a>, et dispose par contre d&#8217;un vrai ramasse-miette. Le support de Python 3 est minimum, <a href="http://doc.pypy.org/en/latest/release-2.4.0.html">en juin 2014 est sorti Pypy 2.4 supportant python version 3.2</a>,<a href="http://pypy.org/download.html"> l&#8217;équipe informant qu&#8217;il est néanmoins plus lent que Pypy visant python 2.7</a>, autant vous dire qu’on est pas en avance.</p>
<p>Vous avez pu tomber sur des noms genre Unladden Swallow et Stackless Python : Unladen Swallow était un Pypy-like antérieur par des ingénieurs de Google qui voulait générer du JIT avec LLVM en promettant des performances 5 fois supérieurs à CPython. Le projet a échoué à tenir ses promesses et a fini par mourir doucement lors que Google a retiré son financement. Ce qui a pu être sauvé a été mergé dans Pypy (des améliorations au module Pickle). Stackless  est un interpréteur modifié qui intègre les coroutines de base et d&#8217;autres trucs parallèles/asynchrone, il n&#8217;est d&#8217;un drop-in remplacement et demande d&#8217;écrire du python qui ne tournera que sur et pour lui.</p>
<p>Ensuite est venu il y a un an le “Pypy” de Dropbox, Pyston. Tout le monde a tapé sur Dropbox pour avoir réinventé sa roue carrée avec Pyston, Dropbox a répondu qu’ils utilisent une approche différente de Pypy, ils utilisent un method-at-a-time JIT au lieu d’un tracing JIT, méthode qui a donné de si bons résultats avec le moteur javascript de Google, V8, en s&#8217;appuyant sur la célèbre LLVM, la “machine virtuelle pour le bas-niveau” . LLVM étant par ailleurs soutenue par des grands noms genre Apple et Intel, si Dropbox ne merde pas, ça pourrait donner un truc intéressant. De plus, contrairement à Pypy qui a choisi de peu supportter l&#8217;API C de CPython pour les modules, Pyston vise une compatibilité absolue avec l&#8217;API C, c&#8217;est une de ses priorité fondamentale . Nous pouvons en déduire que Dropbox a beaucoup de modules d&#8217;extension en C auxquels ils tiennent beaucoup. Pypy utilise un ramasse miette et un GIL. Un point fait néanmoins tousser avec Pyston, c’est que les créateurs déclarent ne vouloir que viser Python 2.7 et ne pas envisager de supporter python3. On a du mal à croire que Guido van Rossum travaille pour cette boite. Toutes ces informations viennent de la <a href="https://github.com/dropbox/pyston/wiki/FAQ">FAQ de Pyston</a>. Le blog de Pyston, intéressant, explique leurs choix technique et rend compte de leur avancée : http://blog.pyston.org/.</p>
<p>Pyston a fait plusieurs chose intelligemment, notamment au lieu de réécrire un interpréteur, ils ont forké CPython et branché leurs systèmes de JIT dedans, ce qui leur a permis de sortir en moins d&#8217;un an une release de Pyston plutôt viable qui fait tourner beaucoup de choses et passe beaucoup de tests. <a href="http://blog.pyston.org/2015/11/03/102/">Leur interpréteur est déjà 25% plus rapide que CPython sur leur suite de test, face à un Pypy 50% plus performant</a>. C&#8217;est un petit tour de force.</p>
<p>Un énorme écueil d’écrire un interpréteur alternatif à CPython étaient les modules en C de la bibliothèque standard ; une partie significative des modules de la bibliothèque standard étaient écrits en C, donc si vous faisiez un interpréteur alternatif, il fallait aussi vous recoder dans le langage de votre interpréteur tous les modules de la bibliothèque standard que vous ne pouviez utiliser, ce qui implique de faire 10.000 tests pour s’assurer qu’ils ont exactement le même comportement que ceux de la bibliothèque standard, ce qui est extrêmement fastidieux et pénible. Depuis Python 3.3 en septembre 2012 , <a href="https://www.python.org/dev/peps/pep-0399/">CPython fourni un recode en Python de tous ses module en C qui passent exactement la même suite de test</a> et qui sont donc “garantis” (modulo erreur humaine, c’est une vaste et dure tâche) de se comporter exactement comme leurs congénères en C. C’est une énorme charge de travail en moins pour les développeurs d’interpréteurs alternatifs. Également, depuis Python 3.1 , l&#8217;import de modules, qui auparavant était une machinerie interne un peu obscure de l&#8217;interpréteur CPython, et donc qu&#8217;il fallait recoder en croisant les doigts pour que ça reproduise exactement le comportement de CPython sous peine de tout voir exploser, <a href="https://docs.python.org/3/library/importlib.html#module-importlib">a été recodé en Python et est livré avec CPython</a>, donc fini de revoir recoder un système d&#8217;import, vous pouvez juste le reprendre et l&#8217;utiliser, ouf.</p>
<p>De tous, Pypy est le seul qui s’approche actuellement vaguement d’un “concurrent” sérieux à CPython, talonné par Pyston pour un futur proche. Et encore, ce n’est pas encore le drop-in remplacement parfait. Et tous ont un support de Python3 inexistant, sauf Pypy qui en a un insuffisant :). Et tous, en tant que VM complète (donc lourde) ou interpréteur-optimiseur visant à optimiser le code (et donc analyser), ont des temps de démarrage et d’atteinte de l’efficacité sans commune mesure avec CPython. Ils ne sont intéressants qu’en cas de long-running (genre, vos sites Django). Et tous utilisent un ramasse-miette, ce qui donne un comportement différents sur les objets &#8220;finalisés&#8221;. Alors que CPython a un comportement déterministe et détruit immédiatement les objets qui ne sont plus utilisés, les ramasse-miettes reportent leur destruction à un moment où il sera plus opportun de les détruire, potentiellement très longtemps ou jamais au pire des cas. C&#8217;est pour ça que par hygiène, il faut toujours libérer explicitement les ressources des objets représentants des ressources tel que les files-like objets représentants fichiers ou socket en utilisant leur méthode &#8220;close()&#8221; ou le manager &#8220;with&#8221; même si ça fonctionne très bien sans sous CPython. Pour les objets représentant des ressources limitées comme les fichiers, les sockets ou n&#8217;importe quel lien vers une ressource limitée procurée par l&#8217;OS, ça signifie se prendre rapidement un stop de l&#8217;OS. D&#8217;une manière générale, CPython applique des solutions simples et déterministes qui offrent pas mal de garanties sympathiques (gestion des ressources, atomicité, alignement mémoire, adresse des objets en mémoire fixe, etc) qui sont maintenant considérées comme acquise et immuables par beaucoup de programmes python, malheureusement gênantes pour faire un interpréteur optimisant vraiment agressivement (là j&#8217;ai pas de sources mais c&#8217;est une complainte qui revient régulièrement dans les discussions des autres interpréteurs, surtout Pypy).</p>
<p>Parmi les news relatives à la vitesse de Python que l’article de S&amp;M ne mentionne pas, la nouvelle release de la JVM vient avec un meilleur découplage des éléments la composant, et du coup il devient facile de l’utiliser pour un autre langage. IBM a fait un proof-of-concept en faisant un interpréteur python, qu’ils vont open-sourcer (et faire pareil avec Ruby). Pas d’altruisme là-dedans, c’est pour montrer au monde que leur VM est bien fichue. Ça pourrait être le nouveau Jython : http://www.infoworld.com/article/3014128/open-source-tools/ibms-open-source-jvm-project-could-also-speed-ruby-python.html.</p>
<p>Aussi, Microsoft s’étant visiblement, dernièrement, un peu amouraché de Python, on peut s’attendre que leur coopération à Python aille un peu plus loin. Ou pas.</p>
<p>Après, la triste vérité est que les langages dynamiques sont très durs à optimiser, parce qu’ils sont justement dynamiques, surtout Python où tout est modifiable, et donc interpréteur/VM ne peut être sûr de rien et ne peut pas supprimer pleins de tests/résolutions/recherches, et que Python, malgré toutes ses implémentations pleines de bonne volonté, ne sera jamais aussi rapide que le C, ni même que Java. La dernière fois que j’ai regardé (~3 ans), le benchmark game donnait python 20x plus lent que le C, contre 2x pour le Java. Ça fait réfléchir. Tous les efforts poussés à fond, on tapera peut être le 5x plus lent que le C :)</p>
<p>Actuellement, un core-contributeur de CPython (français, cocorico !) travaille sur différents sujets visant à améliorer significativement les performances de CPython. C&#8217;est la première fois qu&#8217;un chantier aussi vaste est lancé visant à sérieusement améliorer les performances de CPython. Le site sur le sujet : <a href="http://faster-cpython.readthedocs.org/">http://faster-cpython.readthedocs.org/</a></p>
<p>Ces différents projets acceptent les dons. Je vous encourage évidemment vivement à donner. La vitesse de Python est l&#8217;un dernier écueil qui pourraient faire choisir à un décideur technique pressé un autre langage plutôt que Python. Des meilleurs interpréteurs Python, c&#8217;est plus de tâches accomplies en Python, donc plus de postes pour les développeurs Python, donc plus de demande, et donc de meilleurs salaires. Quand vous donnez à des projets Python, vous vous versez de l&#8217;argent à vous-même dans le futur. De plus, ça aide à faire reculer les parts de marché de cette horreur qu&#8217;est PHP et de la concurrence de Ruby et Go, et ça, c&#8217;est toujours ça de pris :)<br />
Même une petite somme est significative. Avec l&#8217;euro fort, vous avez un grand pouvoir. Et un grand pouvoir implique de grandes responsabilités.<br />
Donner à Cpython : <a href="https://www.python.org/psf/donations/">https://www.python.org/psf/donations/</a><br />
Donner à Pypy : <a href="http://pypy.org/">http://pypy.org/</a></p>
<p>Voila, vous savez tout sur l’histoire des différents interpréteurs Python. Avec ça, vous pourrez vous la pétez en soirée et niquer des tonnes de meufs. Ou pas.</p>


feed_id: http://sametmax.com/?p=18505
title: Comment tu as appelé ton utilisateur ? Recently updated !
uri: Comment-tu-as-appelé-ton-utilisateur-Recently-updated
url: http://sametmax.com/comment-tu-as-appele-ton-utilisateur/
content:
<p>Je travaillais pour un client dont l&#8217;infrastructure m&#8217;avait pris quelques jours à prendre en main. Avec l&#8217;aide de toute l&#8217;équipe et de la patience, victoire, j&#8217;avais l&#8217;env de prod sur ma machine, et je pouvais faire tourner le produit&#8230;</p>
<h2>Previouly, on Sam and Max</h2>
<p>Je me rend sur la page d&#8217;accueil, qui me redirige instantanément sur l&#8217;admin du site Django.</p>
<p>Ceci n&#8217;avait aucun sens. Je regarde les requêtes HTTP, j&#8217;ai une 302 qui sort de nulle part. Je suis authentifié, ma conf nginx est pas déconnante, et dans le routing défini du urls.py, le pattern pour l&#8217;admin est le classique <code>http://domain.tld/admin</code>.</p>
<p>Rien de fou.</p>
<p>Alors après m&#8217;être arraché les cheveux, je vais voir un techos et lui demande si à tout hasard il a une idée.</p>
<blockquote><p>- Il me dit &#8220;tu as appelé ton user comment ?&#8221;</p>
<p>&#8211; Oh, j&#8217;ai fait un <code>./manage.py createsuperuser</code> vite fait pour tester en local avec username:admin, password:admin.</p>
<p>&#8211; Ben c&#8217;est ça, on peut pas créer un user qui s&#8217;appelle &#8220;admin&#8221;.</p>
<p>&#8211; Ah ?</p>
<p>&#8211; Oui on a un url pattern pour la page du profile utilisateur qui fait:</p>
<p><code>http://domain.tld/&lt;username&gt;</code></p>
<p>Quand tu arrives sur /, on redirige dessus automatiquement.</p>
<p>Du coup si tu l&#8217;appelles admin, tu as plus accès à ton profile&#8230;</p></blockquote>
<h2>And now&#8230;</h2>
<p>Aujourd&#8217;hui, en explorant la base de code, je tombe sur ça:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> RegistrationForm<span style="color: black;">&#40;</span>forms.<span style="color: black;">Form</span><span style="color: black;">&#41;</span>:
&nbsp;
    _reserved_usernames <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span>
        <span style="color: #483d8b;">'accounts'</span><span style="color: #66cc66;">,</span>
        <span style="color: #483d8b;">'about'</span><span style="color: #66cc66;">,</span>
        <span style="color: #483d8b;">'admin'</span><span style="color: #66cc66;">,</span>
        <span style="color: #483d8b;">'clients'</span><span style="color: #66cc66;">,</span>
        <span style="color: #483d8b;">'data'</span><span style="color: #66cc66;">,</span>
        <span style="color: #483d8b;">'forms'</span><span style="color: #66cc66;">,</span>
        <span style="color: #483d8b;">'maps'</span><span style="color: #66cc66;">,</span>
        ... + <span style="color: #ff4500;">50</span>
    <span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>J&#8217;ai de quoi écrire un bouquin avec le contenu des fichiers que je vois, je sens que ça va me faire quelques articles :)</p>


feed_id: http://sametmax.com/?p=18526
title: Se faciliter la vie quand on utilise asyncio dans le shell 2
uri: Se-faciliter-la-vie-quand-on-utilise-asyncio-dans-le-shell-2
url: http://sametmax.com/se-faciliter-la-vie-quand-on-utilise-asyncio-dans-le-shell/
content:
<p>Dernièrement j&#8217;ai mis les fonctions suivantes dans mon <a href="http://sametmax.com/nouveau-fichier-de-start-up-python/">script PYTHONSTARTUP</a>&#8230;</p>
<p>Toujours choper une event loop toute fraiche, et ouverte:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> asyncio
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> aloop<span style="color: black;">&#40;</span>*args<span style="color: #66cc66;">,</span> **kargs<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; Ensure they is an opened event loop available and return it&quot;&quot;&quot;</span>
    loop <span style="color: #66cc66;">=</span> asyncio.<span style="color: black;">get_event_loop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> loop.<span style="color: black;">is_closed</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        policy <span style="color: #66cc66;">=</span> asyncio.<span style="color: black;">get_event_loop_policy</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        loop <span style="color: #66cc66;">=</span> policy.<span style="color: black;">new_event_loop</span><span style="color: black;">&#40;</span>*args<span style="color: #66cc66;">,</span> **kargs<span style="color: black;">&#41;</span>
        policy.<span style="color: black;">set_event_loop</span><span style="color: black;">&#40;</span>loop<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> loop</pre></td></tr></table></div>

<p>Lancer une coroutine dans une event loop jusqu&#8217;à ce qu&#8217;elle se termine:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">inspect</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> arun<span style="color: black;">&#40;</span>coro<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; Run this in a event loop &quot;&quot;&quot;</span>
    loop <span style="color: #66cc66;">=</span> aloop<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #dc143c;">inspect</span>.<span style="color: black;">isawaitable</span><span style="color: black;">&#40;</span>coro<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #dc143c;">inspect</span>.<span style="color: black;">iscoroutinefunction</span><span style="color: black;">&#40;</span>coro<span style="color: black;">&#41;</span>:
            coro <span style="color: #66cc66;">=</span> asyncio.<span style="color: black;">coroutine</span><span style="color: black;">&#40;</span>coro<span style="color: black;">&#41;</span>
        coro <span style="color: #66cc66;">=</span> coro<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    future <span style="color: #66cc66;">=</span> asyncio.<span style="color: black;">ensure_future</span><span style="color: black;">&#40;</span>coro<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> loop.<span style="color: black;">run_until_complete</span><span style="color: black;">&#40;</span>future<span style="color: black;">&#41;</span></pre></td></tr></table></div>

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

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">async <span style="color: #ff7700;font-weight:bold;">def</span> foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    await asyncio.<span style="color: black;">sleep</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</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;">'bar'</span><span style="color: black;">&#41;</span>
&nbsp;
arun<span style="color: black;">&#40;</span>coro<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Ca me fait gagner pas mal de temps.</p>
<p>J&#8217;utilise aussi <a href="https://github.com/ipython/ipython/issues/9166#issuecomment-174483773">cette commande magique</a> dans iPython qui permet de balancer des await en plein milieu du shell. Je suis <a href="https://github.com/jonathanslenders/ptpython/issues/99#issuecomment-187417579">en train de voir</a> pour ajouter un truc similaire à ptpyhon.</p>
<p>Je me suis fait aussi un petit script pour lancer vite fait n&#8217;importe quel script dans une boucle asyncio de manière transparente, mais j&#8217;ai pas le temps de poster ça aujourd&#8217;hui donc ça sera pour la prochaine fois.</p>


feed_id: http://sametmax.com/?p=18545
title: Look it up 1 Recently updated !
uri: Look-it-up-1-Recently-updated
url: http://sametmax.com/look-it-up/
content:
<p>Je travaille sur <a href="http://sametmax.com/comment-tu-as-appele-ton-utilisateur/">un projet magique</a>. Chaque jour est une nouvelle découverte, une aventure !</p>
<p>Par exemple, c&#8217;est un projet utilisant l&#8217;exellent <a href="www.django-rest-framework.org/">Django Rest Framework</a>, une app Django très puissante qui permet de créer des API succulentes.</p>
<p>DRF est très flexible, et permet de régler tout un tas de paramètres à l&#8217;aide de classes de configuration. Par exemple, il extrait automatiquement tout champ <code>lookup_field</code> sur ses classes <code>Serializer</code> afin de choisir sur quel champ filtrer les données.</p>
<p>L&#8217;auteur du code que j&#8217;ai sous les yeux, je crois, a voulu être vraiment, mais alors vraiment sur d&#8217;avoir un look up:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> FooViewSet<span style="color: black;">&#40;</span>ModelViewSet<span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">class</span> Meta:
        model <span style="color: #66cc66;">=</span> Foo
        lookup_field <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'pk'</span>
        lookup_fields <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'pk'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'data_id'</span><span style="color: black;">&#41;</span>
        extra_lookup_fields <span style="color: #66cc66;">=</span> <span style="color: #008000;">None</span></pre></td></tr></table></div>

<p>En soit, c&#8217;est très drôle.</p>
<p>Et je pourrais arrêter l&#8217;article ici.</p>
<p>Mais non.</p>
<p>En effet, y a pas un truc qui vous choque ?</p>
<p>Je veux dire, autre que la sainte trinité des lookup fields&#8230;</p>
<p>Allez, relisez l&#8217;article depuis le début, je vous laisse une chance.</p>
<p>&#8230;<br />
&#8230;</p>
<p>J&#8217;ai dis que DRF extraiyais un champ <code>lookup_field</code> sur les classes <code>Serializer</code>, et comme vous pouvez le constater, l&#8217;auteur ici hérite joyeusement de <code>ModelViewSet</code>, mais pas du tout de <code>Serializer</code>.</p>
<p>Oui, parce qu&#8217;on est en pleine exploration de Fistland (Au fond du fun !™), ces 3 champs ne sont en aucun cas exploités automatiquement par DRF&#8230; car sur les Viewset, lookup_field est utilisé pour générer des URLs, et mes prédécesseurs ont créé un router custo qui override ceci. Mais si on retire les champs, ça pête tout car ils y a des bouts de leur code qui supposent l&#8217;existence de ce champ.</p>
<p>Néanmoins, ne soyons pas complètement négatif, certaines classes héritent bien de <code>Serialiser</code>, et définissent aussi <code>lookup_field</code>. D&#8217;ailleurs une part de mon job est de migrer tout ça. Car la petite touche humoristique finale, c&#8217;est que <code>lookup_field</code> est deprecated depuis 3 releases dans DRF \o/ Mais deprecated sur les <code>Serializer</code> uniquement hein, pas les Viewset. Enfin je dis ça&#8230;</p>


feed_id: http://sametmax.com/?p=18627
title: Ce ne sont pas les services pirates qui ont une jambe de bois
uri: Ce-ne-sont-pas-les-services-pirates-qui-ont-une-jambe-de-bois
url: http://sametmax.com/ce-ne-sont-pas-les-services-pirates-qui-ont-une-jambe-de-bois/
content:
<p>Quand le Divx est sorti, il y a eu tout un débat sur la valeur du DVD. Le truc qui prend de la place, qui s&#8217;abime, qui est une plaie à sauvegarder, qui est zoné&#8230; En prime, quand tu payais un DVD, tu avais ça:</p>
<p><div id="attachment_18631" style="width: 801px" class="wp-caption aligncenter"><a href="media/375bcbd1.dvd-legal-illegal-pirate-consommateur.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2016/03/dvd-legal-illegal-pirate-consommateur.jpg" class="grouped_elements" rel="tc-fancybox-group18627"><img src="media/375bcbd1.dvd-legal-illegal-pirate-consommateur.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2016/03/dvd-legal-illegal-pirate-consommateur.jpg" alt="Dvd pirate vs légal" width="791" height="982" class="size-full wp-image-18631" /></a><p class="wp-caption-text">Attendez : il fallait aussi se déplacer pour acheter physiquement ce putain de DVD</p></div><br />
Mais les industriels ont tapé du pied sur le piratage depuis les K7 audio. Jamais, au grand jamais, ils ne se sont remis en question.</p>
<p>Et est venu l&#8217;ère du streaming.</p>
<p>Et on a eu le droit à une redite. </p>
<p>Limite par pays, peu de sous-titre, catalogue limité et gros délais entre certaines sortis selon les médias et/ou les zones. Or the pirate bay et pop corn time n&#8217;ont pas tous ces problèmes.</p>
<p>Mais alors qu&#8217;en est-il du livre numérique ?</p>
<p>Le livre, c&#8217;est fait par des gens qui utilisent leur cerveau, non ? </p>
<p>Je veux dire, ils lisent, en théorie&#8230;</p>
<p>Et bien, après avoir galéré pour trouvé certains titres légalement et perdu ma collection suite au bricage de ma première tablette, je n&#8217;étais déjà pas très convaincu. J&#8217;aime l&#8217;outil pour le voyage, mais le service laisse à désirer. Nénamoins, je suis un geek, peut etre que les gens moins attachés à la cause étaient moins sensibles à ces problématiques.</p>
<p>Il faut croire que non, puisque mon frère m&#8217;a écrit dernièrement ce mail bien rageux:</p>
<blockquote><p>ALORS j´ai acheté mon livre sur un site.</p>
<p>DRM ADOBE donc j´installe tout etc..1h30 à faire les inscriptions les mots de passe,<br />
les confirmations. Et je peux même pas lire mon livre&#8230;<br />
Les mecs sont les plus nazes de la terre ils se tirent un balle dans le pieds.</p>
<p>Du coup je vais devoir pirater mon propre livre que j´ai acheté légalement</p>
<p>Youpi.</p>
<p>Et du coup bah qu´ils aillent bien se faire mettre pour la suite ce sera le premier et le dernier livre avec DRM que achète et si je trouve pas mon livre en Epub sans DRM bah je le piraterai.</p>
<p>Dés que j´ai mon livre sans DRM je te l´envois.</p>
<p>Bisoux</p></blockquote>
<p>Notez que lui sait ce qu&#8217;est un DRM. Je n&#8217;ose pas imaginer Mme Michu.</p>


feed_id: http://sametmax.com/?p=18674
title: Nouvel alias pour Python et .bashrc
uri: Nouvel-alias-pour-Python-et-bashrc
url: http://sametmax.com/nouvel-alias-pour-python-et-bashrc/
content:
<p>J&#8217;en avais marre de taper Python en entier. Et surtout, je voulais lancer Python3.5 si il est dispo, et si possible ptpython, ou ipython. Sauf si je passe des arguments. Et que ça pete pas tout dans un virtualenv. </p>
<p>Bref:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">function p <span style="color: black;">&#123;</span>
    local SUFFIX<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;$@&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: black;">&#91;</span><span style="color: black;">&#91;</span> <span style="color: #483d8b;">&quot;$VIRTUAL_ENV&quot;</span> <span style="color: #66cc66;">!=</span> <span style="color: #483d8b;">&quot;&quot;</span> <span style="color: black;">&#93;</span><span style="color: black;">&#93;</span>
    then
      local PREFIX<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;$VIRTUAL_ENV&quot;</span>/bin
      COMMANDS<span style="color: #66cc66;">=</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;python&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>
      local PREFIX<span style="color: #66cc66;">=</span>/usr/bin
      COMMANDS<span style="color: #66cc66;">=</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;python3.5&quot;</span> <span style="color: #483d8b;">&quot;python&quot;</span><span style="color: black;">&#41;</span>
    fi
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: black;">&#91;</span><span style="color: black;">&#91;</span> <span style="color: #483d8b;">&quot;$#&quot;</span> -eq <span style="color: #ff4500;">0</span> <span style="color: black;">&#93;</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">;</span> then
        SUFFIX<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;&quot;</span>
        local COMMANDS<span style="color: #66cc66;">=</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;python3.5 -m ptpython&quot;</span>
                        <span style="color: #483d8b;">&quot;python3.5 -m ipython&quot;</span>
                        <span style="color: #483d8b;">&quot;python -m ptpython&quot;</span>
                        <span style="color: #483d8b;">&quot;python -m ipython&quot;</span>
                        <span style="color: #483d8b;">&quot;python&quot;</span><span style="color: black;">&#41;</span>
    fi
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #483d8b;">&quot;${COMMANDS[@]}&quot;</span>
    do
       $PREFIX<span style="color: #483d8b;">'/'</span>$i $SUFFIX<span style="color: #66cc66;">;</span>
       <span style="color: black;">&#91;</span> <span style="color: #483d8b;">&quot;$?&quot;</span> -eq <span style="color: #ff4500;">0</span> <span style="color: black;">&#93;</span> &amp;&amp; <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #ff4500;">0</span>
    done
&nbsp;
<span style="color: black;">&#125;</span></pre></td></tr></table></div>


feed_id: http://sametmax.com/?p=18724
title: Récupérer le premier et le dernier élément d’un OrderedDict
uri: Récupérer-le-premier-et-le-dernier-élément-d-un-OrderedDict
url: http://sametmax.com/recuperer-le-premier-et-le-dernier-element-dun-ordereddict/
content:
<p><code>collections.OrderedDict</code> est une structure de données que j&#8217;utilise de plus en plus, surtout que sa réécriture en C en 3.5 lui donne des performances décentes.</p>
<p>Néanmoins, il n&#8217;y a pas dans l&#8217;API de moyen de récupérer le premier ou le dernier élément inséré dans dico. Il y a bien <code>popitem()</code>, mais ça retire l&#8217;élément du dictionnaire, et c&#8217;est pas forcément ce qu&#8217;on veut.</p>
<p>Heureusement <code>OrderedDict</code> est un itérable, et implémente <code>__reversed__</code>, et on peut donc utiliser les outils suivant our récupérer les extrémités avec une perf 0(1):</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">collections</span> <span style="color: #ff7700;font-weight:bold;">import</span> OrderedDic
<span style="color: #66cc66;">&gt;&gt;&gt;</span> d <span style="color: #66cc66;">=</span> OrderedDict.<span style="color: black;">fromkeys</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'azerty'</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> next<span style="color: black;">&#40;</span><span style="color: #008000;">iter</span><span style="color: black;">&#40;</span>d.<span style="color: black;">items</span><span style="color: black;">&#40;</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;"># premier élément</span>
<span style="color: #483d8b;">'a'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> next<span style="color: black;">&#40;</span><span style="color: #008000;">reversed</span><span style="color: black;">&#40;</span>d.<span style="color: black;">items</span><span style="color: black;">&#40;</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;"># dernier élément</span>
<span style="color: #483d8b;">'y'</span></pre></td></tr></table></div>

<p>Après l&#8217;implémentation de <code>OrderedDict</code> reste une liste doublement chainée, et on ne peut donc pas récupérer un élément à un index arbitraire sans le parcourir à la main&#8230;</p>


feed_id: http://sametmax.com/?p=19982
title: L’ordre des choses 10 Recently updated !
uri: L-ordre-des-choses-10-Recently-updated
url: http://sametmax.com/lordre-des-choses/
content:
<p>Des mois et des mois que je n’ai pas écrit :) Je ne compte même pas Max, qui à l’heure où je vous parle est en train découvrir les joies de la sidérurgie et qui ne se souvient du blog que quand on en parle dans le jacuzzi d’un FKK. </p>
<p>Ça va faire 4 ans qu’on a ce truc.</p>
<p>Entre temps lui et moi avons déménagé plusieurs fois, séparément, puis réaménagé ensemble, on a pris des responsabilités comme l’achat d’une machine à glaçons et la culture de plantes carnivores (la mienne est morte, mais il a la main verte apparemment).</p>
<p>Je vais être franc avec vous, l’écriture ne m’a pas manqué. Pas du tout.</p>
<p>Et puis aujourd’hui, j’ai eu envie. Ça ne m’avait pas pris depuis pas mal de temps, mais c’est une bonne chose : le sens du devoir avait depuis longtemps perdu son influence sur ma motivation éditoriale.</p>
<p>Est-ce que ça va durer un article ? 10 ? Un an ?</p>
<p>On va voir.</p>
<p>Mais ce ne sont pas les sujets qui manquent. En fait Python 3.6 est droit devant nous, avec plein de trucs chouettes à la clé. J’ai aussi beaucoup joué avec asyncio, jusqu’à trouver des bugs dedans et les reporter aux core-dev direct.</p>
<p>Pour le cul par contre, je ne sais pas encore, je vais laisser traîner jusqu’à ce que, tel Rocco dans Omar et Fred, ma bite me parle.</p>
<p>Python pour commencer donc.</p>
<p>Plein de changements de perfs, en vitesse, occupation mémoire, etc, prévus pour la prochaine version. Parmi eux, un changement majeur sur <a href="https://bugs.python.org/issue27350">l’implémentation des dictionnaires</a> inspiré directement de Pypy, qui les rendront plus compacts et plus rapides.</p>
<p>Et surtout, ordonnés par défaut. </p>
<p>Yep, plus besoin de <a href="http://sametmax.com/ce-que-vous-ne-saviez-pas-sur-les-collections-en-python/">collections.OrderedDict</a>, qui restera malgré tout pour des raisons de compatibilité.</p>
<p>Enfin s’ils décident que ça fait maintenant partie de la specs et n’est pas juste un détail d’implémentation.</p>
<p>Ca veut dire aussi que <a href="http://sametmax.com/operateur-splat-ou-etoile-en-python/">**kwargs</a> et <code>__dict__</code> deviendront ordonnés, ce qui va arranger beaucoup de monde.</p>
<p>Mais l’article, en plus de prêcher la bonne nouvelle, est aussi là pour vous parler d’un petit hack sympa qui peut être pratique dans votre <a href="http://sametmax.com/variables-denvironnement-utilisees-par-python/">PYTHONSTARTUP</a> pour des sessions shellifiantes : donner l’impression d’avoir un <code>OrderedDict</code> builtin par défaut.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">textwrap</span> <span style="color: #ff7700;font-weight:bold;">import</span> dedent
<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> OrderedDictFactory<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;"># __getitem__ est la méthode magique appelée quand on fait objet[trucs]</span>
    <span style="color: #808080; font-style: italic;"># et keys contient la liste des trucs</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__getitem__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> keys<span style="color: black;">&#41;</span>:
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">for</span> key <span style="color: #ff7700;font-weight:bold;">in</span> keys:
&nbsp;
            <span style="color: #808080; font-style: italic;"># slice est un objet builtin fabriqué par Python quand on fait </span>
            <span style="color: #808080; font-style: italic;"># objet[debut:fin], qui contient le debut et la fin</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>key<span style="color: #66cc66;">,</span> <span style="color: #008000;">slice</span><span style="color: black;">&#41;</span>:
&nbsp;
                <span style="color: #808080; font-style: italic;"># on check qu’on a bien une liste de slices</span>
                <span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #008000;">SyntaxError</span><span style="color: black;">&#40;</span>dedent<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;&quot;&quot;
                    One element of the dict is not a key/value pair: {!r}.
&nbsp;
                    The syntax is d[&quot;key1&quot;: &quot;value&quot;, &quot;key2&quot;: &quot;value&quot;, ...].
                    Check if you haven't missed a semicolon somewhere.
                &quot;&quot;&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>key<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># et on retourne juste un ordered dict classique</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> OrderedDict<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#40;</span>k.<span style="color: black;">start</span><span style="color: #66cc66;">,</span> k.<span style="color: black;">stop</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> k <span style="color: #ff7700;font-weight:bold;">in</span> keys<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># instance de référence pour notre factory abrégé pour des raisons de </span>
<span style="color: #808080; font-style: italic;"># facilité</span>
d <span style="color: #66cc66;">=</span> OrderedDictFactory<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Et hop, on abuse la notation du slicing :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> menu <span style="color: #66cc66;">=</span> d<span style="color: black;">&#91;</span>
   <span style="color: #483d8b;">&quot;Samurai pizza cats&quot;</span> : <span style="color: #483d8b;">&quot;fruits de mer&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #808080; font-style: italic;"># un slice</span>
   <span style="color: #483d8b;">&quot;Tortue ninja&quot;</span> : <span style="color: #483d8b;">&quot;4 saisons&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #808080; font-style: italic;"># un autre slice </span>
   <span style="color: #483d8b;">'Max'</span>: <span style="color: #483d8b;">&quot;paysanne&quot;</span> <span style="color: #808080; font-style: italic;"># do you wanna slice ?</span>
<span style="color: black;">&#93;</span>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> menu
OrderedDict<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Samurai pizza cats'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'fruits de mer'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Tortues ninjsa'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'4 saisons'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Max'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'paysanne'</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Rien à voir avec la choucroute, mais certaines personnes m’ont parlé de faire un miroir SFW du blog. Je vous rappelle que le blog est sous creative common, alors faites-vous plaiz, vous pouvez tout réutiliser.</p>


feed_id: http://sametmax.com/?p=20037
title: Des astuces avec pytest Recently updated !
uri: Des-astuces-avec-pytest-Recently-updated
url: http://sametmax.com/des-astuces-avec-pytest/
content:
<p><a href="http://sametmax.com/se-simplifier-les-tests-python-avec-pytest/">Pytest</a> est fantastique. En fait si la lib n&#8217;est pas dispo je n&#8217;ai même plus la volonté d&#8217;écrire des <a href="http://sametmax.com/un-gros-guide-bien-gras-sur-les-tests-unitaires-en-python-partie-3/">tests unitaires</a> tellement je suis habitué aux facilités qu&#8217;elle offre.</p>
<p>Au fur et à mesure de son usage, j&#8217;ai noté quelques astuces qui, je le sais, vous serviront bien sur le long terme.</p>
<h2>Choper une exception avec un message particulier</h2>
<p>On peut <a href="http://doc.pytest.org/en/latest/assert.html">vérifier qu&#8217;une fonction lève bien une exception</a> avec la fonction <code>raises()</code>:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> pytest
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> test_truc<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">with</span> pytest.<span style="color: black;">raises</span><span style="color: black;">&#40;</span>MarchinError<span style="color: black;">&#41;</span>:
        foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Ce test réussira si <code>foo()</code> lève bien de manière consistante <code>MarchinError</code>. Mais parfois on a plein d&#8217;erreurs similaires, et on en veut une avec un message particulier. Dans ce cas, on peut matcher le message sur une regex:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> test_truc<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">with</span> pytest.<span style="color: black;">raises</span><span style="color: black;">&#40;</span>MarchinError<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> excinfo:
        foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
     excinfo.<span style="color: black;">match</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">&quot;votre regex du message d'erreur&quot;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<h2>Configurez, il en restera toujours quelque chose</h2>
<p>On peut mettre la config de votre projet dans un fichier pytest.ini (mais le fichier tox.ini ou setup.cfg marche aussi \o/). Parmi les options les plus pratiques:</p>
<p><code>addopts</code>, qui permet de forcer des options à la ligne de commande pytest pour ne pas les passer à chaque fois à la main.</p>
<p>Celles que j&#8217;active toujours:</p>
<p><code>--exitfirst</code> : le premier échec arrête les tests. Pas la peine de me mettre 22 mille erreurs.<br />
<code>--capture=no</code> : affiche les <code>print()</code> de mon code.<br />
<code>--ignore="virtualenv"</code> : permet de ne pas cherche les tests dans un dossier. Par exemple le virtualenv.<br />
<code>-vv</code> : bien verbeux. Je veux de l&#8217;info sur mes tests.<br />
<code>--showlocals</code> : montre les variables locales sur les tests qui foirent.</p>
<p>Par exemple:</p>
<p><code>[pytest]<br />
addopts = --exitfirst --capture=no -ignore="virtualenv" -vv --showlocals</code></p>
<p>Mais bon comme j&#8217;ai toujours ces trucs là activés, je force ces options dans mon .bashrc via la variable d&#8217;env:</p>
<p><code>export PYTEST_ADDOPTS="--exitfirst --capture=no -ignore="virtualenv" -vv --showlocals"</code></p>
<p>Autres options sympas:</p>
<p><code>testpaths</code> qui permet de choisir les chemins dans lesquels chercher les tests:</p>
<p>Ex:</p>
<pre>[pytest]
testpaths =
    tests
    foo
    bar
</pre>
<p>Si à l&#8217;intérieur de ces dossiers, il a un truc à ne pas choper, <code>norecursedirs</code> est là pour ça :</p>
<pre>
[pytest]
norecursedirs =
    tests/media
    tests/scripts
</pre>
<h2>Les options pratiques de tous les jours</h2>
<p>Il y a des options qu&#8217;on ne veut pas tout le temps, mais qui sont super utiles ponctuellement:</p>
<p><code>--failed-first</code> : relance tous les tests, mais ceux qui ont foiré en premier.<br />
<code>--pdb</code> : lance pdb juste après le premier échec.<br />
<code>-k</code> : lance uniquement les tests dont le nom matche cette regex.</p>
<p>Et souvenez-vous que vous pouvez lancer un seul test en spécifier son chemin avec la syntaxe <code>relative/file/path.py::test_func</code>. Par exemple:</p>
<p><code>pytest test/test_foo.py::test_bar</code></p>
<h2>Vive les plugins</h2>
<p>Pytest a une grosse communauté de plugins, il suffit de chercher sur google &#8220;pytest + techno&#8221; pour avoir tout de suite des <a href="https://github.com/manahl/pytest-plugins">helpers</a> qui popent.</p>
<p>Ceux que j&#8217;utilise très souvent:</p>
<p><a href="https://pypi.python.org/pypi/pytest-pythonpath">pytest-pythonpath</a> :</p>
<p>Permet d&#8217;avoir dans son conf file <code>python_paths = chemins</code> qui seront ajoutés au <a href="http://sametmax.com/les-imports-en-python/">PYTHON PATH</a>:</p>
<p>Ex:</p>
<pre>
[pytest]
python_paths =
    .
    libs
</pre>
<p><a href="https://pypi.python.org/pypi/pytest-flake8/">pytest-flake8</a> permet de lancer le linter flake8 pendant les tests et de considérer son échec comme un test qui foire. En plus flake8 peut mettre sa config dans les mêmes fichiers que pytest donc j&#8217;ai souvent ça:</p>
<pre>[flake8]
exclude = doc,build,.tox,.git,__pycache__,build # ignorer les dossiers inutiles
max-complexity = 10 # verifier que le code n'est pas trop complexe
max-line-length = 80 # pep8 for ever, mais noqa peut servir parfois
</pre>
<p>Après j&#8217;utilise souvent tox, donc ce plugin n&#8217;est plus aussi utile qu&#8217;avant.</p>
<p><a href="https://pypi.python.org/pypi/pytest-django">pytest-django</a> qui ajoute des setup et tear down avec la base de données Django, fourni des fixtures pour le client de test django et permet de configurer <code>DJANGO_SETTINGS_MODULE</code> dans son fichier ini.</p>
<p><a href="https://pypi.python.org/pypi/pytest-asyncio">pytest-asyncio</a> qui permet de gérer la loop, utiliser <code>await</code> dans les tests, etc.</p>
<h2>Gérer ses fixures</h2>
<p>Le système de fixtures est une des choses qui rend pytest si cool, particulièrement parce qu&#8217;on peut être très précis dans ce qu&#8217;on charge. Mais des fois on veut les fixtures pour tout le monde, ou tout un module. <code>autouse</code> fait exactement ça:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">@</span>pytest.<span style="color: black;">fixture</span><span style="color: black;">&#40;</span>autouse<span style="color: #66cc66;">=</span><span style="color: #008000;">True</span><span style="color: #66cc66;">,</span> scope<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;module&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> ma_fixture<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Et cette fixture sera instanciée une seule fois pour tout le module. On peut aussi avoir un score de <code>session</code> (une seule fois par lancement de pytest) ou de <code>class</code> (une fois par classe).</p>
<p>Si vous avez besoin de lancer un code avant toute session de tests, par exemple pour vous définir des fixtures qui sont dispo dans tous les tests, il suffit de le mettre dans un fichier conftest.py à la racine de vos tests. Ce fichier est automatiquement détecté par pytest, et lancé avant toute chose. Il permet également de faire des hooks complexes, créer ses propres plugins, etc. Mais je l&#8217;utilise surtout pour faire des fixtures globales et m&#8217;éviter de les importer.</p>


feed_id: http://sametmax.com/?p=20052
title: C’est le futur ! 2 Recently updated !
uri: C-est-le-futur-2-Recently-updated
url: http://sametmax.com/cest-le-futur/
content:
<p><em>J&#8217;ai twitté il y a quelque temps l&#8217;article hilarant <a href="https://circleci.com/blog/its-the-future/">It&#8217;s the future</a>. Mais j&#8217;ai bien conscience que plein de gens ne lisent pas l&#8217;anglais et ne peuvent profiter de cette perle. Comme on a ouvert le blog S&amp;M en français, car on voulait justement créer des bonnes ressources dans notre langue, je traduis de temps en temps ces trucs fantastiques, comme par exemple <a href="http://sametmax.com/le-bonheur-des-frameworks/">Le bonheur des frameworks</a>.</em></p>
<p>Donc voici la traduction de celui-ci. Faites-vous plaiz&#8217;</p>
<p>Hey, mon boss m&#8217;a dit de venir te voir. Il paraît que tu gères niveau web apps ?</p>
<p>&#8211; Ouais, je suis plus un spécialiste des systèmes distribués maintenant. Je reviens du ContainerCamp et de la Gluecon et je vais à la Dockercon la semaine prochaine. Je suis emballé par la direction que prend l&#8217;industrie &#8211; tout est plus simple et fiable. C&#8217;est le futur !</p>
<p>Cool. Je veux juste faire une simple Web app pour le moment &#8211; un <a href="https://fr.wikipedia.org/wiki/CRUD">CRUD</a> normal avec <a href="http://rubyonrails.org/">Rails</a>, que je vais déployer sur <a href="https://www.heroku.com/">Heroku</a>. C&#8217;est toujours d&#8217;actu ?</p>
<p>&#8211; Oh non. C&#8217;est old school. Heroku, c&#8217;est mort &#8211; plus personne ne l&#8217;utilise. Il te faut <a href="Je vais montrer aux gens ce que vous ne voulez pas qu'ils voient">Docker</a> maintenant. C&#8217;est le futur.</p>
<p>Oh, OK. Qu&#8217;est-ce que c&#8217;est ?</p>
<p>&#8211; Docker est la nouvelle façon de faire de la conteneurisation. Comme <a href="https://fr.wikipedia.org/wiki/LXC">LXC</a>, mais c&#8217;est aussi un format de package, une plateforme de distribution et des outils pour rendre la création de systèmes distribués très facile.</p>
<p>Conteneuri.. &#8211; Hein ? C&#8217;est quoi LXE ?</p>
<p>&#8211; LCX. C&#8217;est comme un <a href="https://doc.ubuntu-fr.org/chroot">chroot</a> aux stéroïdes.</p>
<p>C&#8217;est quoi cheroot ?</p>
<p>&#8211; Ok, regarde. Docker. Conteneurisation. C&#8217;est le futur. C&#8217;est comme la virtualisation, mais plus rapide et moins coûteux.</p>
<p>Oh, comme <a href="https://www.vagrantup.com/">Vagrant</a>.</p>
<p>&#8211; No, Vagrant c&#8217;est mort. Tout va être conteneurisé maintenant, c&#8217;est le futur.</p>
<p>Ok, donc je n&#8217;ai pas besoin de savoir quoi que ce soit sur la virtualisation ?</p>
<p>&#8211; Non, tu as quand même besoin de la virtualisation, parce que les conteneurs ne fournissent pas toutes les couches de sécurité pour le moment. Donc ce que tu veux, c&#8217;est faire tout tourner dans un environnement multitiers de telle sorte qu&#8217;on ne puisse s&#8217;échapper de la sandbox.</p>
<p>Ok, je suis un peu perdu là. On rembobine. Donc il y a un truc comme la virtualisation qu&#8217;on appelle les conteneurs. Et je peux l&#8217;utiliser sur Heroku ?</p>
<p>&#8211; Et bien, Heroku a un support pour docker, mais je viens de le dire : Heroku c&#8217;est mort. Ce que tu veux c&#8217;est faire tourner tes conteneurs sur <a href="https://coreos.com/">CoreOS</a>.</p>
<p>Ok, c&#8217;est quoi ?</p>
<p>&#8211; C&#8217;est un OS hôte très cool qu&#8217;on peut utiliser avec Docker. Tu n&#8217;as même pas besoin de Docker, tu peux utiliser <a href="https://github.com/coreos/rkt">rkt</a>.</p>
<p>Rocket ?</p>
<p>&#8211; No, rkt.</p>
<p>Ouais, Rocket.</p>
<p>&#8211; Non, ça s&#8217;appelle rkt maintenant. Rien à voir. C&#8217;est un format de conteneurisation alternatif qui n&#8217;est pas aussi intégré que Docker par défaut, et donc plus composable.</p>
<p>C&#8217;est une bonne chose.</p>
<p>&#8211; Bien entendu. La composabilité c&#8217;est le futur.</p>
<p>Ok, ça s&#8217;utilise comment ?</p>
<p>&#8211; Je ne sais pas. Je ne pense pas que qui que ce soit l&#8217;utilise.</p>
<p>Arf. Tu disais quoi à propos de CoreOS ?</p>
<p>&#8211; Ah oui, c&#8217;est un OS hôte pour Docker.</p>
<p>C&#8217;est quoi un OS hôte ?</p>
<p>&#8211; Un OS hôte fait tourner tous tes conteneurs.</p>
<p>Tourner mes conteneurs ?</p>
<p>&#8211; Ouais, tu dois avoir quelque chose pour faire tourner tes conteneurs. Donc tu te crées genre une instance <a href="https://aws.amazon.com/ec2/">EC2</a>, tu mets CoreOS dessus, tu lances le daemon Docker, puis tu déploies tes images Docker dessus.</p>
<p>Quelle partie est le conteneur ?</p>
<p>&#8211; Tout. Écoute, tu prends ton app, écris un Dockerfile, tu en fais une image locale, puis tu la push sur n&#8217;importe quel hôte Docker.</p>
<p>Ah, comme Heroku ?</p>
<p>&#8211; Non, pas Heroku. Je te l&#8217;ai dit. Heroku c&#8217;est mort. Tu gères ton propre cloud en utilisant Docker.</p>
<p>Hein ?</p>
<p>&#8211; Ouais, c&#8217;est tout simple. Check #gifee.</p>
<p>Gify?</p>
<p>&#8211; <a href="http://www.nebulaworks.com/blog/2015/12/15/2016-the-year-of-gifee/">Google’s infrastructure for everyone else</a>. Tu prends les outils que tu veux, avec des conteneurs, et tu as la même infra que Google.</p>
<p>Pourquoi pas juste utiliser celles de Google ?</p>
<p>Tu crois que ça sera encore là dans 6 mois ?</p>
<p>OK, mais est-ce que quelqu&#8217;un fait du hosting pour ça ? J&#8217;ai pas la foi d&#8217;héberger mon bordel moi-même.</p>
<p>&#8211; Et bien, Amazon a ECS, mais il faut écrire du XML et 2, 3 merdes.</p>
<p>Et <a href="https://www.openstack.org/">OpenStack</a> ?</p>
<p>&#8211; Beurk.</p>
<p>Beurk ?</p>
<p>&#8211; Beurk.</p>
<p>Écoute, j&#8217;ai vraiment pas envie d&#8217;héberger tout ça.</p>
<p>&#8211; Na, c&#8217;est super simple. Tu te setup juste un cluster <a href="http://kubernetes.io/">Kubernetes</a>.</p>
<p>J&#8217;ai besoin d&#8217;un cluster ?</p>
<p>&#8211; Un cluster Kubernetes. Ça gère le déploiement de tous tes services.</p>
<p>J&#8217;ai seulement un service.</p>
<p>&#8211; Qu&#8217;est-ce que tu racontes. Tu as une app non? donc tu as bien au moins 8-12 services ?</p>
<p>Quoi ? Non. Juste une app. Service, on s&#8217;en branle. Juste un truc.</p>
<p>&#8211; Non, jette un coup d&#8217;oeil à la notion de <a href="https://fr.wikipedia.org/wiki/Microservices">microservices</a>. C&#8217;est le futur. C&#8217;est comme ça qu&#8217;on fait tout de nos jours. Tu prends ton app monolithique et tu la divises en quelque chose comme 12 services, un pour chaque tâche.</p>
<p>Ça semble excessif.</p>
<p>&#8211; C&#8217;est le seul moyen de s&#8217;assurer que c&#8217;est fiable. Ainsi si ton service authentification tombe&#8230;</p>
<p>Service authentification ? J&#8217;allais juste utiliser une <a href="https://rubygems.org/">gem</a> que j&#8217;avais déjà mis en place plusieurs fois avant.</p>
<p>&#8211; Super. Utilise la gem. Mets la dans son propre projet. Fous une <a href="http://sametmax.com/quest-ce-quune-api/">API RESTful</a> par dessus. Et fait en sorte que les autres services utilisent cette API et gèrent gracieusement les échecs. Mets ça dans un conteneur et push le bordel en déploiement continu.</p>
<p>Ok, donc là j&#8217;ai une douzaine de services ingérables, et maintenant ?</p>
<p>&#8211; Ouais, d&#8217;où Kubernetes. Il orchestre tes services.</p>
<p>Orchestre ?</p>
<p>&#8211; Ouais, donc tu as ces services, ils doivent être fiables donc il t&#8217;en faut plusieurs copies. Donc Kubernetes s&#8217;assure que tu en as assez, et qu&#8217;ils sont distribués à travers de multiples hôtes dans ta flotte de serveurs, afin qu&#8217;ils soient toujours disponibles.</p>
<p>Ah parce qu&#8217;il me faut une flotte maintenant ?</p>
<p>&#8211; Ouais, pour la fiabilité. Mais Kubernetes la gère pour toi. Et tu sais que Kubernetes ça marche vu que Google l&#8217;a fabriqué et que ça tourne sur <a href="https://github.com/coreos/etcd">etcd</a>.</p>
<p>C&#8217;est quoi etcd ?</p>
<p>&#8211; Une implémentation de <a href="https://raft.github.io/">Raft</a>.</p>
<p>OK, c&#8217;est quoi Raft.</p>
<p>&#8211; C&#8217;est comme <a href="https://fr.wikipedia.org/wiki/Paxos_(informatique)">Paxos</a>.</p>
<p>Putain, jusqu&#8217;où ça va le terrier du lapin blanc là ? Je veux juste lancer une app. Arf. Bordel, Ok, on respire. Fiou. Ok, donc Paxos c&#8217;est quoi ?</p>
<p>&#8211; Paxos c&#8217;est ce très vieux protocole de consensus distribué des années 70 que personne ne comprend ou n&#8217;utilise.</p>
<p>Super, merci de m&#8217;en avoir parlé. Et donc Raft ?</p>
<p>&#8211; Comme personne ne pige Paxos, y a ce mec, <a href="https://ongardie.net/diego/">Diego</a>&#8230;</p>
<p>Oh, tu le connais ?</p>
<p>&#8211; Non, il travaille a CoreOS. Bref, Diego a créé Raft pour sa thèse de doctorat, car Paxos était trop compliqué. Futé le gars. Et il a écrit etcd comme implémentation, et <a href="https://aphyr.com/posts/316-jepsen-etcd-and-consul">Aphyr a dit que c&#8217;était pas de la merde</a>.</p>
<p>C&#8217;est quoi Aphyr ?</p>
<p>&#8211; Aphyr est le mec qui a écrit <a href="https://aphyr.com/posts/322-call-me-maybe-mongodb-stale-reads">Call Me Maybe</a>. Tu vois, le mec spécialiste des systèmes distribués et du <a href="http://aphyr.tumblr.com/">BDSM</a> ?</p>
<p>WUT ? BDSM ?</p>
<p>&#8211; Ouais, BDSM. C&#8217;est San Francisco hein, tout le monde est à fond dans les systèmes distribués et le BDSM</p>
<p>Hum, OK. Donc il a écrit cette chanson de Katy Perry ?</p>
<p>&#8211; Nan, il a écrit des posts sur son blog comme quoi toutes les databases n&#8217;atteignaient jamais le <a href="https://fr.wikipedia.org/wiki/Th%C3%A9or%C3%A8me_CAP">CAP</a>.</p>
<p>C&#8217;est quoi le CAP ?</p>
<p>&#8211; Le théorème CAP. Ça dit que tu peux avoir des données consistantes, disponibles et tolérantes au partitionnement, mais qu&#8217;il faut choisir 2 de ces caractéristiques sur les 3.</p>
<p>Ok, et donc toutes les bases de données foirent CAP. C&#8217;est à dire ?</p>
<p>&#8211; Ça veut dire qu&#8217;elles sont à chier. Comme <a href="https://www.mongodb.com/">Mongo</a>.</p>
<p>Je pensais que Mongo scalait ?</p>
<p>&#8211; Ben personne d&#8217;autre ne le pensait.</p>
<p>Ok, et etcd.</p>
<p>&#8211; Ouais, etcd c&#8217;est un système de stockage de clé/valeur distribué.</p>
<p>Oh, comme <a href="http://redis.io">Redis</a>.</p>
<p>&#8211; Non, rien à voir. etcd est distribué. Redis perd la moitié de ce que tu écris en cas d&#8217;échec réseau.</p>
<p>Ok, donc c&#8217;est un système de stockage de clé/valeur distribué. Pourquoi c&#8217;est utile ?</p>
<p>&#8211; Kubernetes setup par défaut un cluster de 5 nodes et utilise etcd comme bus de transport de messages. En combinaison avec quelques services de Kubernetes lui-même, ça fournit un système d&#8217;orchestration assez résilient.</p>
<p>5 nodes ? J&#8217;ai une app. Combien de machines je vais devoir prendre pour tout ça ?</p>
<p>&#8211; Et bien tu vas avoir environ 12 services, et bien sûr il te faut des copies de chaque pour la redondance, quelques load balancers, le cluster etcd, ta base de données, et le cluster kubernetes. Je dirais peut-être 50 conteneurs.</p>
<p>WTF ?!</p>
<p>&#8211; Aucun problème ! Les conteneurs sont vraiment efficaces, donc tu peux les distribuer sur genre, 8 machines. C&#8217;est pas incroyable ?</p>
<p>C&#8217;est une manière de voir les choses. Et avec tout ça, je vais être capable de simplement déployer mon app ?</p>
<p>&#8211; Yep. Je veux dire, la question du stockage est toujours en suspend avec Docker et Kubernetes, et la partie réseau va demander un peu de travail, mais techniquement, tu es à 2m du bol de sangria.</p>
<p>Je vois. Ok, je pense que j&#8217;ai pigé.</p>
<p>&#8211; Super !</p>
<p>Merci pour l&#8217;explication.</p>
<p>&#8211; No problem.</p>
<p>Laisse-moi faire un résumé pour voir si j&#8217;ai bien tout compris.</p>
<p>&#8211; Bien sûr !</p>
<p>Donc j&#8217;ai besoin de diviser mon app CRUD toute simple, en 12 microservices, chacun avec leur propre API qui s&#8217;appellent les uns et les autres, mais qui gèrent les erreurs de manière résiliente, les mettre dans des conteneurs Docker, lancer une flotte de 8 machines qui sont des hôtes Docker tournant sous CoreOS, les orchestrer avec un petit cluster Kubernetes qui tourne avec etcd, me démerder avec la question du réseau et du stockage, et je fais tout ça en déploiement continu pour de multiples copies redondantes des microservices de ma flotte. J&#8217;ai bon ?</p>
<p>&#8211; Yep ! C&#8217;est pas fabuleux ?</p>
<p>Je retourne sous Heroku.</p>
<p><em>En relisant l&#8217;article, je réalise deux choses :</em></p>
<ul>
<li>Putain il en faut des références rien que pour comprendre la blague. Plein de devs ne savent même pas ce qu&#8217;est Heroku.</li>
<li>Et franchement cette parodie est vraiment gentille, dans la réalité cette stack pose beaucoup d&#8217;autres problèmes : il y a plus de trucs que ça, ça s’emboîte mal, les versions changent, la doc est merdique, faut former les nouveaux arrivants car personne ne connaît ces technos, y a plein de roues à réinventer, il faut un temps fou pour choisir les briques technos, etc. Mais on peut aussi utiliser Docker très simplement, avec un image, à la main, sous Ubuntu. C&#8217;est presque simple et pratique.</li>
</ul>
<p>&nbsp;</p>
<p><span class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='1170' height='689' src='http://www.youtube.com/embed/XbIaW_ZdJ0g?version=3&#038;rel=1&#038;fs=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' frameborder='0' allowfullscreen='true'></iframe></span></p>


feed_id: http://sametmax.com/?p=20169
title: Vérifier qu’un uuid est valide en Python 1
uri: Vérifier-qu-un-uuid-est-valide-en-Python-1
url: http://sametmax.com/verifier-quun-uuid-est-valide-en-python/
content:
<p>Si on teste du code qui utilise des <a href="http://sametmax.com/quest-ce-quun-uuid-et-a-quoi-ca-sert/">uuid</a>, on veut vérifier qu&#8217;on récupère bien des uuid valides là où on les attend.</p>
<p>Le plus simple est de déléguer cette vérification au module <code>uuid</code> qui est déjà celui qu&#8217;on utilise pour les produire.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> uuid <span style="color: #ff7700;font-weight:bold;">import</span> UUID
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> is_uuid<span style="color: black;">&#40;</span>uuid_string<span style="color: #66cc66;">,</span> version<span style="color: #66cc66;">=</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        <span style="color: #808080; font-style: italic;"># Si uuid_string est un code hex valide mais pas un uuid valid,</span>
        <span style="color: #808080; font-style: italic;"># UUID() va quand même le convertir en uuid valide. Pour se prévenir</span>
        <span style="color: #808080; font-style: italic;"># de se problème, on check la version original (sans les tirets) avec</span>
        <span style="color: #808080; font-style: italic;"># le code hex généré qui doivent être les mêmes.</span>
        uid <span style="color: #66cc66;">=</span> UUID<span style="color: black;">&#40;</span>uuid_string<span style="color: #66cc66;">,</span> version<span style="color: #66cc66;">=</span>version<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> uid.<span style="color: #008000;">hex</span> <span style="color: #66cc66;">==</span> uuid_string.<span style="color: black;">replace</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'-'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">''</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">ValueError</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">False</span></pre></td></tr></table></div>

<p>Et pouf:</p>

<div class="wp_syntax"><table><tr><td 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> uuid
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>uuid.<span style="color: black;">uuid4</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
1049d03f-6f45-<span style="color: #ff4500;">4637</span>-89ff-f57567f6d022
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> is_uuid<span style="color: black;">&#40;</span><span style="color: #483d8b;">'1049d03f-6f45-4637-89ff-f57567f6d022'</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">True</span>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> is_uuid<span style="color: black;">&#40;</span><span style="color: #483d8b;">'1049d03f6f45463789fff57567f6d022'</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">True</span>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> is_uuid<span style="color: black;">&#40;</span><span style="color: #483d8b;">'1049d03f6f45'</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">False</span></pre></td></tr></table></div>

<p>À chaque fois que j&#8217;utilise un uuid, j&#8217;ai un peu l&#8217;impression d&#8217;user la fabrique de l&#8217;univers, comme si je fabriquais quelque chose d&#8217;unique pour le mettre la poubelle, et qui n&#8217;existera plus jamais. Le gâchis d&#8217;un flocon de neige virtuel :)</p>


feed_id: http://sametmax.com/?p=20252
title: C’est pas pour tout de suite 3 Recently updated !
uri: C-est-pas-pour-tout-de-suite-3-Recently-updated
url: http://sametmax.com/cest-pas-pour-tout-de-suite/
content:
<p>J&#8217;ai envie de vous écrire un article sur les types hints, mais le tooling est encore incomplet. On vient juste d&#8217;avoir le support de <code>async</code> / <code>await</code> et le typage structurel <a href="https://github.com/python/mypy/issues/2136#issuecomment-247343342">n&#8217;est pas d&#8217;actualité</a>. Ennuyeux pour un langage qui aime autant les canards.</p>
<p>J&#8217;ai envie de vous écrire un article sur asyncio, mais je ne veux pas faire un article qui survole le sujet comme tout ce qu&#8217;il y a sur la toile. Je veux parler de cas concrets, et amener des solutions pour le debuggage, l&#8217;architecture, et du code pour les actions les plus communes. Et ça fait des mois que j&#8217;y travaille, mais comme vous pouvez le voir <a href="https://github.com/python/asyncio/issues/created_by/sametmax">y a encore du taff</a>.</p>
<p>J&#8217;ai envie de vous parler de la 3.6, mais tout est toujours en beta et la mailing list de Python <a href="https://mail.python.org/pipermail/python-ideas/2016-September/thread.html">est en ébullition</a>, difficile de savoir comment ça va se finir, même avec un feature freeze pas loin. <a href="https://mail.python.org/pipermail/python-ideas/2016-September/042287.html">Et c&#8217;est pas faute de participer</a>. je préfère attendre que ça se soit calmé.</p>
<p>Bref, y a des trucs sympas à écrire, mais des trucs pas prêts.</p>
<p>Du coup j&#8217;ai sous le coude des petits trucs comme un petit middleware django, le test coverage, etc.</p>
<p>Je dis ça parce que je me fais en ce moment tout le temps twitter pour que j&#8217;écrive sur ces sujets, mais c&#8217;est pas encore le bon moment.</p>


feed_id: http://sametmax.com/?p=20288
title: Mise à jour de l’article sur les middlewares Django
uri: Mise-à-jour-de-l-article-sur-les-middlewares-Django
url: http://sametmax.com/mise-a-jour-de-larticle-sur-les-middlewares-django/
content:
<p>Ça faisait un bout de temps que je n&#8217;avais pas mis à jour un article en Python 3.</p>
<p>Là je fais un Pierre deux couilles puisque les middlewares ont changé avec Django 1.10 et ça me permet de rafraîchir cette notion assez floue du framework.</p>
<p>Allez hop, <a href="http://sametmax.com/quest-ce-quun-middleware-django/">on va lire l&#8217;article</a>.</p>


feed_id: http://sametmax.com/?p=20305
title: Script Python qui installe ses dépendances 9 Recently updated !
uri: Script-Python-qui-installe-ses-dépendances-9-Recently-updated
url: http://sametmax.com/script-python-qui-installe-ses-dependances/
content:
<p>Quand on a un petit script, on ne veut pas forcément dire aux gens avec lesquels on le partage qu&#8217;il faut <a href="http://sametmax.com/votre-python-aime-les-pip/">pip</a> installer toutes les dépendances, ou faire un <a href="http://sametmax.com/creer-un-setup-py-et-mettre-sa-bibliotheque-python-en-ligne-sur-pypi/">setup.py</a> complet.</p>
<p>On peut évidemment se tourner vers des solutions de compilation type <a href="http://nuitka.net/">nuitka</a>, mais si on veut être KISS, on peut juste utiliser pip depuis le code Python:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> pip<span style="color: #66cc66;">,</span> <span style="color: #dc143c;">sys</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On essaye d'importer les dépendances, et si elles sont pas dispos on les installe </span>
<span style="color: #808080; font-style: italic;"># pour l'utilisateur courant.</span>
<span style="color: #ff7700;font-weight:bold;">def</span> require<span style="color: black;">&#40;</span>*packages<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">for</span> package <span style="color: #ff7700;font-weight:bold;">in</span> packages:
        <span style="color: #ff7700;font-weight:bold;">try</span>:
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">isinstance</span><span style="color: black;">&#40;</span>package<span style="color: #66cc66;">,</span> <span style="color: #008000;">str</span><span style="color: black;">&#41;</span>:
                import_name<span style="color: #66cc66;">,</span> install_name <span style="color: #66cc66;">=</span> package
            <span style="color: #ff7700;font-weight:bold;">else</span>:
                import_name <span style="color: #66cc66;">=</span> install_name <span style="color: #66cc66;">=</span> package
            <span style="color: #008000;">__import__</span><span style="color: black;">&#40;</span>import_name<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">ImportError</span>:
&nbsp;
            <span style="color: #dc143c;">cmd</span> <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">'install'</span><span style="color: #66cc66;">,</span> install_name<span style="color: black;">&#93;</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">hasattr</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'real_prefix'</span><span style="color: black;">&#41;</span>:
                <span style="color: #dc143c;">cmd</span>.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'--user'</span><span style="color: black;">&#41;</span>
            pip.<span style="color: black;">main</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">cmd</span><span style="color: black;">&#41;</span>
&nbsp;
require<span style="color: black;">&#40;</span><span style="color: #483d8b;">'arrow'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'requests'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'minibelt'</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'path'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'path.py'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Et votre script peut joyeusement utiliser ses dépendances</span>
<span style="color: #ff7700;font-weight:bold;">import</span> arrow
<span style="color: #ff7700;font-weight:bold;">import</span> requests
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> path <span style="color: #ff7700;font-weight:bold;">import</span> Path
<span style="color: #ff7700;font-weight:bold;">from</span> minibelt <span style="color: #ff7700;font-weight:bold;">import</span> window
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>Path<span style="color: black;">&#40;</span><span style="color: #483d8b;">'.'</span><span style="color: black;">&#41;</span>.<span style="color: black;">realpath</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>arrow.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #008000;">list</span><span style="color: black;">&#40;</span>window<span style="color: black;">&#40;</span>requests.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://sametmax.com'</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></pre></td></tr></table></div>

<p>Bien entendu, ça marche que pour les dépendances en pur Python, mais ça fait déjà un paquet de trucs.</p>
<p>N&#8217;oubliez pas qu&#8217;on reste dans une solution quick and dirty, ne commencez pas à me mettre ça partout.</p>


feed_id: http://sametmax.com/?p=20808
title: Puis-je copier/coller mon brave ? 4 Recently updated !
uri: Puis-je-copier-coller-mon-brave-4-Recently-updated
url: http://sametmax.com/20808/
content:
<p>Dans <a href="0bin.net">0bin</a> on utilise encore flash pour faire le copier/coller, et je pense qu&#8217;on va le virer. Plus de raison de supporter les navigateurs trop vieux, et après tout c&#8217;est pas grave de se voir refuser un raccourci pour copier/coller : le reste est utilisable.</p>
<p>Pourquoi je vous dis ça ?</p>
<p>Et bien parce que sebsauvage a partagé <a href="http://sebsauvage.net/links/?cKAfaQ">un snippet</a> pour utiliser l&#8217;API du clipboard en JS. Et j&#8217;ai donc voulu savoir comment détecter que cette functionalité est implémentée par le navivateur en cours. </p>
<p>Je suis donc allé voir <a href="https://github.com/Modernizr/Modernizr/pull/659/commits/7354ab3e0167ced43df9fae43c13c25a10f36fcf">les sources de mondernizr</a>, et il implémente en fait une combinaisons de 2 techniques.</p>
<p>D&#8217;abord, vérifier si l&#8217;objet <code>window</code> à un attribut <code>ClipboardEvent</code>. Si oui, c&#8217;est réglé. Si non, il créé un <code>div</code>, on check si il a il a un attribut <code>paste</code>. Le reste sont <a href="http://perfectionkills.com/detecting-event-support-without-browser-sniffing/">les hacks de compatibilé</a> avec les très vieux navs que je ne vais pas retranscrire ici.</p>
<p>Donc en gros, avant de faire un copier/coller en JS, vérifiez:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">function</span> implementClipboardAPI<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
   <span style="color: #000066; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
     <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!!</span>window.<span style="color: #660066;">ClipboardEvent</span> <span style="color: #339933;">||</span> <span style="color: #3366CC;">'onpaste'</span> <span style="color: #000066; font-weight: bold;">in</span> document.<span style="color: #660066;">createElement</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'div'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">catch</span><span style="color: #009900;">&#40;</span>e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
     <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
   <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>


feed_id: http://sametmax.com/?p=20922
title: Un tools d’itertour, ou l’inverse 1 Recently updated !
uri: Un-tools-d-itertour-ou-l-inverse-1-Recently-updated
url: http://sametmax.com/un-tools-ditertour-ou-linverse/
content:
<p>Ah, ça faisait longtemps que je ne vous avais pas fait un petit article bien long. Ca manquait d&#8217;opportunité de partager de la musique. Allez hop !</p>
<p><span class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='1170' height='689' src='http://www.youtube.com/embed/HTN6Du3MCgI?version=3&#038;rel=1&#038;fs=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' frameborder='0' allowfullscreen='true'></iframe></span></p>
<p>Python est un langage avec un &#8220;for&#8221; penchant pour l&#8217;itération si je puis dire. Et ce n&#8217;est que justice qu&#8217;il ait donc un module dédié pour les opérations d&#8217;itération : <a href="https://docs.python.org/3.5/library/itertools.html">itertools</a>.</p>
<p><code>itertools</code> est un peu impénétrable pour quelqu&#8217;un qui n&#8217;a pas l&#8217;habitude, alors je vais vous faire un petit tour du propriétaire.</p>
<h2>Principes de base</h2>
<p>Itertools a pour but de manipuler les itérables, et si vous voulez en savoir plus sur le concept d&#8217;itérabilité, je vous renvoie à l&#8217;article sur les <a href="http://sametmax.com/les-trucmuchables-en-python/">trucmuchables</a>. Pour faire court, les itérables sont tout ce sur quoi on peut appliquer une boucle <code>for</code>.</p>
<p>Le problème, c&#8217;est que tous les itérables ne se comportent pas de la même façon. En effet, certains ont une taille définis:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;abcd&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">4</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">3</span></pre></td></tr></table></div>

<p>D&#8217;autres non:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><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;">&#41;</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&lt;ipython-input-7-baed595d06b3&gt;&quot;</span><span style="color: #66cc66;">,</span> line <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</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;">len</span><span style="color: black;">&#40;</span><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;">&#41;</span>
<span style="color: #008000;">TypeError</span>: <span style="color: #008000;">object</span> of <span style="color: #008000;">type</span> <span style="color: #483d8b;">'_io.TextIOWrapper'</span> has no <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Certains, se terminent:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> a <span style="color: #66cc66;">=</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span><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;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span></pre></td></tr></table></div>

<p>D&#8217;autres sont infinis:</p>

<div class="wp_syntax"><table><tr><td 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> infinite_generator<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
...     <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:
...         <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #ff4500;">1</span>
...
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>infinite_generator<span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># bloque la VM jusqu'à crasher sur un MemoryError</span></pre></td></tr></table></div>

<p>Du coup, si vous voulez faire des opérations qui marchent sur tous les itérables, il faut écrire des algos spéciaux dit &#8220;paresseux&#8221; (en anglais, &#8220;lazy&#8221;), c&#8217;est à dire qui font le travail minimum. Ils se lancent à la dernière minute et ne lisent rien de plus que nécessaire.</p>
<p>Et c&#8217;est ce que contient <code>itertools</code>. Les fonctions de ce module marchent sur les fichiers, les générateurs, les sockets réseaux comme les listes, les tuples et les chaînes de caractères.</p>
<h2>chain</h2>
<p>Combine plusieurs itérables en un seul:</p>

<div class="wp_syntax"><table><tr><td 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;">itertools</span> <span style="color: #ff7700;font-weight:bold;">import</span> chain
<span style="color: #66cc66;">&gt;&gt;&gt;</span> generator <span style="color: #66cc66;">=</span> chain<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;abc&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#91;</span><span style="color: #008000;">True</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">False</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">None</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> generator
<span style="color: #66cc66;">&lt;</span><span style="color: #dc143c;">itertools</span>.<span style="color: black;">chain</span> <span style="color: #008000;">object</span> at <span style="color: #ff4500;">0x7f2ea903d550</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>generator<span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'b'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'c'</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">True</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">False</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">None</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Très utile pour boucle sur des itérables hétérogènes comme si c&#8217;était une seule et même structure. Chaîner des fichiers, des générateurs, etc.</p>
<h2>islice</h2>
<p>Comme la syntaxe de slicing <code>[::]</code>:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> carres_de_nombres_pairs <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span>x * x  <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;">100</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> x % <span style="color: #ff4500;">2</span> <span style="color: #66cc66;">==</span> <span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> carres_de_nombres_pairs<span style="color: black;">&#91;</span><span style="color: #ff4500;">3</span>:<span style="color: #ff4500;">11</span><span style="color: black;">&#93;</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">36</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">64</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">100</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">144</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">196</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">256</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">324</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">400</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Mais marche sur tous les itérables, même sur les générateurs:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> carres_de_nombres_pairs <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span>x * x  <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;">100</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> x % <span style="color: #ff4500;">2</span> <span style="color: #66cc66;">==</span> <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> carres_de_nombres_pairs
<span style="color: #66cc66;">&lt;</span>generator <span style="color: #008000;">object</span> <span style="color: #66cc66;">&lt;</span>genexpr<span style="color: #66cc66;">&gt;</span> at <span style="color: #ff4500;">0x7f2eab171a98</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">itertools</span> <span style="color: #ff7700;font-weight:bold;">import</span> islice
<span style="color: #66cc66;">&gt;&gt;&gt;</span> generator <span style="color: #66cc66;">=</span> islice<span style="color: black;">&#40;</span>carres_de_nombres_pairs<span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">11</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> generator
<span style="color: #66cc66;">&lt;</span><span style="color: #dc143c;">itertools</span>.<span style="color: black;">islice</span> <span style="color: #008000;">object</span> at <span style="color: #ff4500;">0x7f2eab1a26d8</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>generator<span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">36</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">64</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">100</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">144</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">196</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">256</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">324</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">400</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<h2>cycle</h2>
<p>Boucler de manière infinie sur un itérable. Quand on arrive à la fin, on revient au début.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> generator <span style="color: #66cc66;">=</span> cycle<span style="color: black;">&#40;</span><span style="color: #483d8b;">'abc'</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> generator
<span style="color: #66cc66;">&lt;</span><span style="color: #dc143c;">itertools</span>.<span style="color: black;">cycle</span> <span style="color: #008000;">object</span> at <span style="color: #ff4500;">0x7f2eab59a588</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> next<span style="color: black;">&#40;</span>generator<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'a'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> next<span style="color: black;">&#40;</span>generator<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'b'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> next<span style="color: black;">&#40;</span>generator<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'c'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> next<span style="color: black;">&#40;</span>generator<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'a'</span></pre></td></tr></table></div>

<p>C&#8217;est très pratique, mais assez dangereux donc faites des tests avant de l&#8217;utiliser. En effet si l&#8217;itérable génère les données à la volée, elles sont stockées dans un buffer, donc ça charge tout en mémoire. De plus, c&#8217;est une boucle infinie. Ne castez pas ça avec un tuple ou une liste :)</p>
<h2>repeat</h2>
<p>Prend n&#8217;importe quel élément, et le retourne encore et encore.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> generator <span style="color: #66cc66;">=</span> repeat<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;plop&quot;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># répète infiniment</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> next<span style="color: black;">&#40;</span>generator<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'plop'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> next<span style="color: black;">&#40;</span>generator<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'plop'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> next<span style="color: black;">&#40;</span>generator<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'plop'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> generator <span style="color: #66cc66;">=</span> repeat<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;plop&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># répète 2 fois</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> generator:
...     <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: black;">plop</span>
plop</pre></td></tr></table></div>

<p>On ne peut pas passer un <a href="http://sametmax.com/quest-ce-quun-callable-en-python/">callable</a>, mais <code>iter()</code> le fait déjà. La signature normale de cette dernière prend un iterable, mais si on lui passe deux paramètres, un callable et un sentinel, on obtient un générateur qui va appeler le callable jusqu&#8217;à ce qu&#8217;il retourne une valeur égale au sentinel.</p>
<p>Exemple, vous voulez lire un fichier 50 caractères à la fois. On passe une fonction qui retourne les 50 caractères suivants (le callable) et une chaîne de caractères vide (le sentinel):</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> f <span style="color: #66cc66;">=</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/etc/fstab'</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">def</span> read_50_chars<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
...     <span style="color: #ff7700;font-weight:bold;">return</span> f.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">50</span><span style="color: black;">&#41;</span>
...
<span style="color: #66cc66;">&gt;&gt;&gt;</span> generator <span style="color: #66cc66;">=</span> <span style="color: #008000;">iter</span><span style="color: black;">&#40;</span>read_50_chars<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">''</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># lit 50 caratères à la fois jusqu'à tomber sur ''</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> generator
<span style="color: #66cc66;">&lt;</span>callable_iterator <span style="color: #008000;">object</span> at <span style="color: #ff4500;">0x7f2eab5abef0</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> next<span style="color: black;">&#40;</span>generator<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'# /etc/fstab: static file system information.<span style="color: #000099; font-weight: bold;">\n</span>#<span style="color: #000099; font-weight: bold;">\n</span># '</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> next<span style="color: black;">&#40;</span>generator<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">&quot;Use 'blkid' to print the universally unique identi&quot;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> next<span style="color: black;">&#40;</span>generator<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'fier for a<span style="color: #000099; font-weight: bold;">\n</span># device; this may be used with UUID= a'</span></pre></td></tr></table></div>

<p><code>iter()</code> est un builtin, pas dans <code>itertools</code>, mais ça aurait été con de pas en parler.</p>
<h2>zip_longest</h2>
<p>Comme <code>zip()</code>, mais au lieu de s&#8217;arrêter quand le premier itérable est fini:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span><span style="color: #008000;">zip</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'abc'</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'b'</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'c'</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>On rempli les valeurs manquantes:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>zip_longest<span style="color: black;">&#40;</span><span style="color: #483d8b;">'abc'</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'b'</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'c'</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>zip_longest<span style="color: black;">&#40;</span><span style="color: #483d8b;">'abc'</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> fillvalue<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;Tada !&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'b'</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'c'</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Tada !'</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Tada !'</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<h2>starmap</h2>
<p>Comme <code>map()</code>, mais applique <a href="http://sametmax.com/operateur-splat-ou-etoile-en-python/">l&#8217;opérateur splat</a> sur les arguments avant.</p>
<p>Si <code>map()</code> ressemble (en mieux) à:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> map_en_moins_bien<span style="color: black;">&#40;</span><span style="color: #008000;">callable</span><span style="color: #66cc66;">,</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;">yield</span> <span style="color: #008000;">callable</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p><code>starmap()</code> fait:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> map_en_moins_bien<span style="color: black;">&#40;</span><span style="color: #008000;">callable</span><span style="color: #66cc66;">,</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;">yield</span> <span style="color: #008000;">callable</span><span style="color: black;">&#40;</span>*x<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Exemple:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> nombres <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">6</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">def</span> ajouter<span style="color: black;">&#40;</span>a<span style="color: #66cc66;">,</span> b<span style="color: black;">&#41;</span>:
...     <span style="color: #ff7700;font-weight:bold;">return</span> a + b
...
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">itertools</span> <span style="color: #ff7700;font-weight:bold;">import</span> starmap
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>starmap<span style="color: black;">&#40;</span>ajouter<span style="color: #66cc66;">,</span> nombres<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">3</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">7</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">11</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Ces fonctions sont moins utilisées à cause des <a href="http://sametmax.com/python-love-les-listes-en-intention-partie/">listes en intension</a>. Mais il y a des trucs rigolos comme:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>starmap<span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">print</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">zip</span><span style="color: black;">&#40;</span><span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">map</span><span style="color: black;">&#40;</span><span style="color: #008000;">int</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;123&quot;</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: #ff4500;">0</span> <span style="color: #ff4500;">1</span>
<span style="color: #ff4500;">1</span> <span style="color: #ff4500;">2</span>
<span style="color: #ff4500;">2</span> <span style="color: #ff4500;">3</span>
<span style="color: black;">&#91;</span><span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">None</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Ouai, vous allez pas utiliser ça tous les jours :)</p>
<h2>filterfalse</h2>
<p>Le contraire de <code>filter()</code>, garde les résultats négatifs au lieu des résultats positifs:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span><span style="color: #008000;">filter</span><span style="color: black;">&#40;</span>est_pair<span style="color: #66cc66;">,</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: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">5</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">7</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">9</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">itertools</span> <span style="color: #ff7700;font-weight:bold;">import</span> filterfalse
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>filterfalse<span style="color: black;">&#40;</span>est_pair<span style="color: #66cc66;">,</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: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">4</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">6</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">8</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Comme précédemment, aujourd&#8217;hui on utilise peu ces fonctions car on a les listes en intension. Mais certaines astuces sont sympas comme:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span><span style="color: #008000;">filter</span><span style="color: black;">&#40;</span><span style="color: #008000;">bool</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#91;</span><span style="color: #008000;">True</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">False</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'foo'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">''</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #008000;">True</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'foo'</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>filterfalse<span style="color: black;">&#40;</span><span style="color: #008000;">bool</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#91;</span><span style="color: #008000;">True</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">False</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'foo'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">''</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #008000;">False</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">''</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<h2>groupby</h2>
<p>Ah, <code>groupby()</code>, la fonction la moins facile à comprendre. D&#8217;abord, personne ne lit la doc, et la doc dit clairement qu&#8217;il faut trier les éléments de l&#8217;itérable AVANT d&#8217;appliquer groupby, sinon les résultats sont incohérents.</p>
<p>Ensuite, <code>groupby()</code> peut prendre un callback pour un usage avancé, et toutes les fonctions qui prennent un callback sont plus dures à comprendre. Mais pour que ça ait du sens, il faut que le tri préalable s&#8217;applique sur le même callack. Personne ne pige jamais ça.</p>
<p>Enfin, <code>groupby()</code> ne renvoie pas les éléments directement, mais des objets &#8220;groupers&#8221;, qui sont eux mêmes des générateurs. Tout est bien fait pour embrouiller le chaland, surtout pour une fonction qu&#8217;on utilise pas souvent.</p>
<p>Pour comprendre <code>groupby()</code>, le mieux est de commencer par l&#8217;entrée et la sortie. Vous avez un truc comme ça:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> noms <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">'Zebulon'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Léo'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Alice'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Bob'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Anaïs'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Adam'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Bernardo'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Io'</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Et vous voulez les grouper par un critère, un peu comme un <code>GROUP BY</code> en SQL. Ca peut être n&#8217;importe quoi:</p>
<ul>
<li>La valeur de la première lettre.</li>
<li>La position de la première voyelle.</li>
<li>Deux catégories: ceux qui contiennent des caractères non ascii  et les autres.</li>
</ul>
<p>Prenons un exemple simple, et groupons les par le nombre de lettres qu&#8217;ils contiennent. Ca donnerait quelque chose comme ça:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Io'</span><span style="color: #66cc66;">,</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span>
 <span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Léo'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Bob'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span>
 <span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Adam'</span><span style="color: #66cc66;">,</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span>
 <span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Alice'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Anaïs'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span>
 <span style="color: black;">&#40;</span><span style="color: #ff4500;">7</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Zebulon'</span><span style="color: #66cc66;">,</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span>
 <span style="color: black;">&#40;</span><span style="color: #ff4500;">8</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Bernardo'</span><span style="color: #66cc66;">,</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Pour obtenir ce résultat avec <code>groupby()</code>, il faut d&#8217;abord trier l&#8217;itérable (ici notre liste) par nombre de lettres:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> noms.<span style="color: black;">sort</span><span style="color: black;">&#40;</span>key<span style="color: #66cc66;">=</span><span style="color: #008000;">len</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> noms
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'Io'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Léo'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Bob'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Adam'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Alice'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Anaïs'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Zebulon'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Bernardo'</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Si vous ne vous souvenez plus comment fonctionne <a href="http://sametmax.com/ordonner-en-python/">le tri en Python,</a> particulièrement le paramètre <code>key</code>, allez vite lire l&#8217;article dédié du lien précédent. En effet le mécanisme est le même pour <code>groupby()</code> donc il faut comprendre ce fonctionnement de toute manière.</p>
<p>Ensuite on applique <code>groupby()</code>, <strong>avec la même fonction <code>key</code></strong>:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> noms <span style="color: #66cc66;">=</span> groupby<span style="color: black;">&#40;</span>noms<span style="color: #66cc66;">,</span> key<span style="color: #66cc66;">=</span><span style="color: #008000;">len</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> noms
<span style="color: #66cc66;">&lt;</span><span style="color: #dc143c;">itertools</span>.<span style="color: black;">groupby</span> <span style="color: #008000;">object</span> at <span style="color: #ff4500;">0x7f19c4461778</span><span style="color: #66cc66;">&gt;</span></pre></td></tr></table></div>

<p>A ce stade, on a un générateur qu&#8217;on peut parcourir, mais vous il ne contient pas le résultat tel que je vous l&#8217;ai montré. A la place, il yield des paires <code>(group, grouper)</code>:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> next<span style="color: black;">&#40;</span>noms<span style="color: black;">&#41;</span>
<span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #66cc66;">&lt;</span><span style="color: #dc143c;">itertools</span>._grouper <span style="color: #008000;">object</span> at <span style="color: #ff4500;">0x7f19c48c0080</span><span style="color: #66cc66;">&gt;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Le premier élément, le groupe, est ce que votre fonction <code>key</code> retourne, c&#8217;est à dire ce sur quoi vous vouliez grouper. Ici la taille du mot.</p>
<p>En second, un objet <code>grouper</code>, qui est un générateur yieldant la mots qui correspondent à ce groupe.</p>
<p>Donc pour vraiment voir le contenu de tout ça, il faut se taper une double boucle imbriquée:</p>

<div class="wp_syntax"><table><tr><td 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;">itertools</span> <span style="color: #ff7700;font-weight:bold;">import</span> groupby
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">for</span> groupe<span style="color: #66cc66;">,</span> groupeur <span style="color: #ff7700;font-weight:bold;">in</span> groupby<span style="color: black;">&#40;</span>noms<span style="color: #66cc66;">,</span> key<span style="color: #66cc66;">=</span><span style="color: #008000;">len</span><span style="color: black;">&#41;</span>:
...     <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>groupe<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;:&quot;</span><span style="color: black;">&#41;</span>
...     <span style="color: #ff7700;font-weight:bold;">for</span> mot <span style="color: #ff7700;font-weight:bold;">in</span> groupeur:
...         <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'-'</span><span style="color: #66cc66;">,</span> mot<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">2</span> :
- Io
<span style="color: #ff4500;">3</span> :
- Léo
- Bob
<span style="color: #ff4500;">4</span> :
- Adam
<span style="color: #ff4500;">5</span> :
- Alice
- Anaïs
<span style="color: #ff4500;">7</span> :
- Zebulon
<span style="color: #ff4500;">8</span> :
- Bernardo</pre></td></tr></table></div>

<p>La raison de ce manque d&#8217;intuitivité, c&#8217;est que théoriquement <code>groupby()</code> peut travailler de manière paraisseuse et donc les groupeurs sont des générateurs qui traitent l&#8217;arrivée des données au fur et à mesure. Mais c&#8217;est rare d&#8217;avoir des données lazy qui arrivent déjà pré-ordonnées. Ensuite ça suppose que vous voulez lire ces données au fur et à mesure, mais généralement le jeu de données groupé n&#8217;est pas suffisament grand pour que ça soit un vrai problème et on caste directement le groupe en tuple ou en liste.</p>
<p>Dans la pratique donc, <code>groupby()</code> fait parti de ces fonctions un peu overkill, car un usage typique ne bénéfiera pas du côté paresseux. En tout cas ça ne m&#8217;est jamais arrivé.</p>
<h2>dropwhile</h2>
<p><code>dropwhile()</code> prend un callable et un itérable. Le callable est appelé sur chaque élément, et tant qu&#8217;il retourne quelque chose de vrai, l&#8217;élément est ignoré. C&#8217;est un peu tordu car ça demande d&#8217;écrire sa fonction de filtre à l&#8217;inverse de ce qu&#8217;on veut.</p>
<p>Par exemple, si vous voulez commencer à lire un fichier à partir de la première ligne qui commence par un commentaire, il faut que votre fonction retourne <code>True</code>&#8230; si la ligne ligne ne commence PAS par un commentaire.</p>

<div class="wp_syntax"><table><tr><td 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> ne_commence_pas_par_un_commentaire<span style="color: black;">&#40;</span>element<span style="color: black;">&#41;</span>:
...     <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #ff7700;font-weight:bold;">not</span> element.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'#'</span><span style="color: black;">&#41;</span>
...
...
<span style="color: #66cc66;">&gt;&gt;&gt;</span> generator <span style="color: #66cc66;">=</span> dropwhile<span style="color: black;">&#40;</span>ne_commence_pas_par_un_commentaire<span style="color: #66cc66;">,</span> <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;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> generator
<span style="color: #66cc66;">&lt;</span><span style="color: #dc143c;">itertools</span>.<span style="color: black;">dropwhile</span> <span style="color: #008000;">object</span> at <span style="color: #ff4500;">0x7f19c450d688</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> next<span style="color: black;">&#40;</span>generator<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'# /etc/fstab: static file system information.<span style="color: #000099; font-weight: bold;">\n</span>'</span></pre></td></tr></table></div>

<p><code>dropwhile</code> veut dire &#8220;ignorer tant que&#8221;. Donc ici on ignore tant que la ligne ne commence pas par un commentaire.</p>
<h2>takewhile</h2>
<p><code>takewhile()</code> est le contraire de <code>dropwhile()</code>, on prend les éléments tant qu&#8217;une condition est vraie, et on s&#8217;arrête dès que la condition n&#8217;est plus vraie. On les utilise souvent en combinaison d&#8217;ailleurs, pour slicer les itérables en utilisant des conditions plutôt que des indexes.</p>
<p>Comme pour <code>dropwhile</code>, il faut penser à l&#8217;envers. Vous voulez vous arrêter quand un nombre dépasse 10000 ? Alors il faut faire une fonction qui retourne <code>True</code> tant que le nombre ne dépasse PAS 10000. Jusqu&#8217;ici j&#8217;ai utilisé des fonctions traditionnelles, mais bien entendu, une lambda marche aussi:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> nombres <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span>x * x <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;">1000000000000</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">itertools</span> <span style="color: #ff7700;font-weight:bold;">import</span> takewhile
<span style="color: #66cc66;">&gt;&gt;&gt;</span> generator <span style="color: #66cc66;">=</span> takewhile<span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> x: x <span style="color: #66cc66;">&lt;</span> <span style="color: #ff4500;">10000</span><span style="color: #66cc66;">,</span> nombres<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> next<span style="color: black;">&#40;</span>generator<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">0</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> next<span style="color: black;">&#40;</span>generator<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">1</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> next<span style="color: black;">&#40;</span>generator<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">4</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>generator<span style="color: black;">&#41;</span><span style="color: black;">&#91;</span>-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
<span style="color: #ff4500;">9801</span></pre></td></tr></table></div>

<h2>count</h2>
<p><code>count()</code> est une relique du passé, qui fait ce que fait <code>range()</code> maintenant, mais en moins bien. Vous pouvez l&#8217;ignorer.</p>
<h2>tee</h2>
<p><code>tee()</code> est une fonction très intéressante qui duplique votre itérable en autant de clones que vous le souhaitez. Pour ce faire, <code>tee()</code> garde en mémoire les derniers éléments générés, ce qui fait que si vous lisez les clones les uns après les autres, ça n&#8217;a aucun intérêt. Autant caster en liste et lire la liste plusieurs fois.</p>
<p>Non, l&#8217;interêt de <code>tee()</code> est si vous lisez les clones en parallèle. Car là, <code>tee()</code> ne garde en mémoire que les éléments qui n&#8217;ont pas été lus par le dernier clone utilisé.</p>
<p>Par exemple, ceci est inutile:</p>

<div class="wp_syntax"><table><tr><td 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;">itertools</span> <span style="color: #ff7700;font-weight:bold;">import</span> tee
<span style="color: #66cc66;">&gt;&gt;&gt;</span> clone1<span style="color: #66cc66;">,</span> clone2<span style="color: #66cc66;">,</span> clone3 <span style="color: #66cc66;">=</span> tee<span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>x <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;">100</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>clone1<span style="color: black;">&#41;</span><span style="color: black;">&#91;</span>:<span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>clone2<span style="color: black;">&#41;</span><span style="color: black;">&#91;</span>:<span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Par contre ceci économise pas mal de mémoire:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> clone1<span style="color: #66cc66;">,</span> clone2<span style="color: #66cc66;">,</span> clone3 <span style="color: #66cc66;">=</span> tee<span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>x <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;">100</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> next<span style="color: black;">&#40;</span>clone1<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">0</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> next<span style="color: black;">&#40;</span>clone2<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">0</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> next<span style="color: black;">&#40;</span>clone3<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">0</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> next<span style="color: black;">&#40;</span>clone1<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">1</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> next<span style="color: black;">&#40;</span>clone2<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">1</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> next<span style="color: black;">&#40;</span>clone3<span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># la valeur 0 n'est plus en mémoire après ça</span>
<span style="color: #ff4500;">1</span></pre></td></tr></table></div>

<h2>compress</h2>
<p><code>compress()</code> est une curiosité qui va surtout parler aux data-scientists et matheux, et d&#8217;une manière générale aux adeptes de <code>numpy</code>.</p>
<p>Cette fonction prend deux itérables, un avec des valeurs à filtrer, et un avec des valeurs qui indiquent si il faut filtrer l&#8217;élément ou non:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>compress<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'toto'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'tata'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'titi'</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#91;</span><span style="color: #008000;">True</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">False</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">True</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'toto'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'titi'</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Je n&#8217;ai pas trouvé de use case pour cette fonction dans ma vie de tous les jours. Si quelqu&#8217;un est inspiré en commentaire, je mettrai l&#8217;article à jour.</p>
<h2>accumulate</h2>
<p><code>accumulate()</code> est un pur produit de la programmation fonctionnelle. C&#8217;est un peu comme un <code>map()</code>, mais au lieu de passer chaque élément au callable, on lui passe l&#8217;élément, et le résultat du dernier appel.</p>
<p>Par exemple, vous voulez multiplier tout une liste : <code>[1, 2, 3, 4]</code></p>
<p>Vous allez faire:</p>
<p><code>(((1 * 2) * 3) * 4)</code></p>
<p>C&#8217;est typiquement pour ce genre de chose qu&#8217;on utiliserait la fonction <code>reduce()</code>:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">reduce</span><span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> x<span style="color: #66cc66;">,</span> y: x * y<span style="color: #66cc66;">,</span> <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">24</span></pre></td></tr></table></div>

<p><code>accumulate()</code> fait cela, mais en plus vous yield tous les résultats intermédiaires:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>accumulate<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span> <span style="color: #ff7700;font-weight:bold;">lambda</span> x<span style="color: #66cc66;">,</span> y: x * y<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">6</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">24</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>La signature est inversée par rapport à <code>reduce()</code>, c&#8217;est ballot. Dans d&#8217;autres langages vous trouverez ce genre de fonction sous le nom <code>fold()</code> ou <code>scan()</code>, mais c&#8217;est le même principe.</p>
<h2>product</h2>
<p><code>product()</code> prend des itérables, et vous balances toutes les combinaisons des éléments de ces itérables. On s&#8217;en sert surtout pour éviter les boucles for imbriquées. Par exemple au lieu de faire:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> lettres <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;abcd&quot;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> chiffres <span style="color: #66cc66;">=</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">for</span> lettre <span style="color: #ff7700;font-weight:bold;">in</span> lettres:
...     <span style="color: #ff7700;font-weight:bold;">for</span> chiffre <span style="color: #ff7700;font-weight:bold;">in</span> chiffres:
...         <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>lettre<span style="color: #66cc66;">,</span> chiffre<span style="color: black;">&#41;</span>
...
<span style="color: black;">a</span> <span style="color: #ff4500;">0</span>
a <span style="color: #ff4500;">1</span>
a <span style="color: #ff4500;">2</span>
b <span style="color: #ff4500;">0</span>
b <span style="color: #ff4500;">1</span>
b <span style="color: #ff4500;">2</span>
c <span style="color: #ff4500;">0</span>
c <span style="color: #ff4500;">1</span>
c <span style="color: #ff4500;">2</span>
d <span style="color: #ff4500;">0</span>
d <span style="color: #ff4500;">1</span>
d <span style="color: #ff4500;">2</span></pre></td></tr></table></div>

<p>On va faire:</p>

<div class="wp_syntax"><table><tr><td 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;">itertools</span> <span style="color: #ff7700;font-weight:bold;">import</span> product
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">for</span> lettre<span style="color: #66cc66;">,</span> chiffre <span style="color: #ff7700;font-weight:bold;">in</span> product<span style="color: black;">&#40;</span>lettres<span style="color: #66cc66;">,</span> chiffres<span style="color: black;">&#41;</span>:
...     <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>lettre<span style="color: #66cc66;">,</span> chiffre<span style="color: black;">&#41;</span>
...
<span style="color: black;">a</span> <span style="color: #ff4500;">0</span>
a <span style="color: #ff4500;">1</span>
a <span style="color: #ff4500;">2</span>
b <span style="color: #ff4500;">0</span>
b <span style="color: #ff4500;">1</span>
b <span style="color: #ff4500;">2</span>
c <span style="color: #ff4500;">0</span>
c <span style="color: #ff4500;">1</span>
c <span style="color: #ff4500;">2</span>
d <span style="color: #ff4500;">0</span>
d <span style="color: #ff4500;">1</span>
d <span style="color: #ff4500;">2</span></pre></td></tr></table></div>

<h2>combinations</h2>
<p>Génère tous les combinaisons possibles des éléments d&#8217;un itérable:</p>

<div class="wp_syntax"><table><tr><td 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;">itertools</span> <span style="color: #ff7700;font-weight:bold;">import</span> combinations
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>combinations<span style="color: black;">&#40;</span><span style="color: #483d8b;">'abcd'</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'b'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'c'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'d'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'b'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'c'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'b'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'d'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'c'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'d'</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>combinations<span style="color: black;">&#40;</span><span style="color: #483d8b;">'abcd'</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'b'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'c'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'b'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'d'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'c'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'d'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'b'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'c'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'d'</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<h2>combinations_with_replacement</h2>
<p>Pareil, mais autorise les doublons:</p>

<div class="wp_syntax"><table><tr><td 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;">itertools</span> <span style="color: #ff7700;font-weight:bold;">import</span> combinations_with_replacement
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>combinations_with_replacement<span style="color: black;">&#40;</span><span style="color: #483d8b;">'abcd'</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'a'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'b'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'c'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'d'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'b'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'b'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'b'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'c'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'b'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'d'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'c'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'c'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'c'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'d'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'d'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'d'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'b'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'b'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'b'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'b'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'b'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'c'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'b'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'b'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'d'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'b'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'c'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'c'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'b'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'c'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'d'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'b'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'d'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'d'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'c'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'c'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'c'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'c'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'c'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'d'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'c'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'d'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'d'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'d'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'d'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'d'</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<h2>permutations</h2>
<p>Comme <code>combinations</code>, mais en générant aussi les mêmes combinaisons dans un ordre différent:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">list</span><span style="color: black;">&#40;</span>permutations<span style="color: black;">&#40;</span><span style="color: #483d8b;">'abc'</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'b'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'c'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'c'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'b'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'b'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'c'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'b'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'c'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'a'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'c'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'a'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'b'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'c'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'b'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'a'</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>


feed_id: http://sametmax.com/?p=21963
title: Le formatage des strings en long et en large 15 Recently updated !
uri: Le-formatage-des-strings-en-long-et-en-large-15-Recently-updated
url: http://sametmax.com/le-formatage-des-strings-en-long-et-en-large/
content:
<p>Un bon article bien long. Je sens que ça vous avait manqué :) Musique ?</p>
<p><span class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='1170' height='689' src='http://www.youtube.com/embed/DOF_3WwzF8E?version=3&#038;rel=1&#038;fs=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' frameborder='0' allowfullscreen='true'></iframe></span></p>
<p>Un problème qui se retrouve souvent, c&#8217;est le besoin d&#8217;afficher un message qui contient des valeurs de variables. Or, si en Python on privilégie généralement &#8220;il y a une seule manière de faire quelque chose&#8221;, cela ne s&#8217;applique malheureusement pas au formatage de chaînes qui a accumulé bien des outils au fil des années.</p>
<h2>TL;DR</h2>
<p>Si c&#8217;est juste pour afficher 2, 3 bricoles dans le terminal, utilisez <code>print()</code> directement:</p>

<div class="wp_syntax"><table><tr><td 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;">&quot;J'ai&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;ans&quot;</span><span style="color: black;">&#41;</span>
J<span style="color: #483d8b;">'ai 3 ans
&gt;&gt;&gt; print(3, 2, 1, sep='</span>-<span style="color: #483d8b;">')
3-2-1</span></pre></td></tr></table></div>

<p>Si vous avez besoin d&#8217;un formatage plus complexe ou que le texte n&#8217;est pas que pour afficher dans le terminal&#8230;</p>
<p>Python 3.6+, utilisez les f-strings:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> produit <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;nipple clamps&quot;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> prix <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">13</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>f<span style="color: #483d8b;">&quot;Les {produit} coutent {prix:.2f} euros&quot;</span><span style="color: black;">&#41;</span>
Les nipple clamps coutent <span style="color: #ff4500;">13.00</span> euros</pre></td></tr></table></div>

<p>Sinon utilisez <code>format()</code>:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> produit <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;nipple clamps&quot;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> prix <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">13</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: #483d8b;">&quot;Les {} coutent {:.2f} euros&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>produit<span style="color: #66cc66;">,</span> prix<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
Les nipple clamps coutent <span style="color: #ff4500;">13.00</span> euros</pre></td></tr></table></div>

<p>Si vous êtes dans le shell, que vous voulez aller vite, ou que vous manipulez des bytes, vous pouvez utiliser &#8220;%&#8221;, mais si ça ne vous arrive jamais, personne ne vous en voudra:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> produit <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;nipple clamps&quot;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> prix <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">13</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: #483d8b;">&quot;Les %s coutent %.2f euros&quot;</span> % <span style="color: black;">&#40;</span>produit<span style="color: #66cc66;">,</span> prix<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
Les nipple clamps coutent <span style="color: #ff4500;">13.00</span> euros</pre></td></tr></table></div>

<p>N&#8217;utilisez jamais <code>string.Template</code>.</p>
<p>Si vous avez un gros morceau de texte ou besoin de logique avancée, utilisez un moteur de template comme <a href="http://jinja.pocoo.org/">jinja2</a> ou <a href="http://www.makotemplates.org/">mako</a>. Pour l&#8217;i18n et la l10n, choisissez une lib comme <a href="http://babel.pocoo.org/en/latest/">babel</a>.</p>
<h2>Avec print()</h2>
<p>Par exemple, si j&#8217;ai :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">produit <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;nipple clamps&quot;</span>
prix <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">13</span></pre></td></tr></table></div>

<p>Et je veux afficher :</p>
<pre>"Les nipple clamps coutent 13 euros"</pre>
<p>La manière la plus simple de faire cela est d&#8217;utiliser <code>print()</code>:</p>

<div class="wp_syntax"><table><tr><td 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;">&quot;Les&quot;</span><span style="color: #66cc66;">,</span> produit<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;coutent&quot;</span><span style="color: #66cc66;">,</span> prix<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;euros&quot;</span><span style="color: black;">&#41;</span>
Les nipple clamps coutent <span style="color: #ff4500;">13</span> euros</pre></td></tr></table></div>

<p>Mais déjà un problème se pose : cette fonction insère des espaces entre chaque argument qu&#8217;elle affiche. Cela est ennuyeux si par exemple je veux utiliser le signe <code>€</code> et le coller pour obtenir :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">Les nipple clamps coutent <span style="color: #ff4500;">13</span>€</pre></td></tr></table></div>

<p><code>print()</code> possède un paramètre spécial pour cela : <code>sep</code>. Il contient le séparateur, c&#8217;est à dire le caractère qui va être utilisé pour séparé les différents arguments affichés. Par défaut, <code>sep</code> est égal à un espace.</p>
<p> Si je change ma phrase et que j&#8217;ai besoin d&#8217;espaces à certains endroits et pas d&#8217;autres il me faut définir un séparateur &#8211; ici une chaîne vide &#8211; et jouer un peu avec le texte :</p>

<div class="wp_syntax"><table><tr><td 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;">&quot;Les &quot;</span><span style="color: #66cc66;">,</span> produit<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot; coutent &quot;</span><span style="color: #66cc66;">,</span> prix<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;€&quot;</span><span style="color: #66cc66;">,</span> sep<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;&quot;</span><span style="color: black;">&#41;</span>
Les nipple clamps coutent <span style="color: #ff4500;">13</span>€</pre></td></tr></table></div>

<p>C&#8217;est mieux. Mais, ça commence à devenir moins lisible.</p>
<p>Maintenant que se passe-t-il si je veux utiliser une valeur numérique mais que j&#8217;ai besoin de la formater ?</p>
<p>Par exemple :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">produit <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;nipple clamps&quot;</span>
prix <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">13</span>
exo_taxe <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">0.011</span></pre></td></tr></table></div>

<p>Et je veux tronquer le prix au centime de telle sorte que j&#8217;obtienne :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">Les nipple clamps coutent <span style="color: #ff4500;">13.01</span>€</pre></td></tr></table></div>

<p>Arf, ça va demander un peu plus de travail.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> total <span style="color: #66cc66;">=</span> <span style="color: #008000;">round</span><span style="color: black;">&#40;</span>prix + exo_taxe<span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Les &quot;</span><span style="color: #66cc66;">,</span> produit<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot; coutent &quot;</span><span style="color: #66cc66;">,</span> total<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;€&quot;</span><span style="color: #66cc66;">,</span> sep<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;&quot;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Bon, mais admettons que je veuille sauvegarder ce texte dans une variable ? Par exemple pour le passer à une fonction qui vérifie l&#8217;orthographe ou met la phrase en jaune fluo&#8230;</p>
<p>Dans ce cas ça devient burlesque, il faut intercepter stdout et récupérer le résultat :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> faux_terminal <span style="color: #66cc66;">=</span> io.<span style="color: #dc143c;">StringIO</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><span style="color: #483d8b;">&quot;Les &quot;</span><span style="color: #66cc66;">,</span> produit<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot; coutent &quot;</span><span style="color: #66cc66;">,</span> total<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;€&quot;</span><span style="color: #66cc66;">,</span> sep<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">file</span><span style="color: #66cc66;">=</span>faux_terminal<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> faux_terminal.<span style="color: black;">seek</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> msg <span style="color: #66cc66;">=</span> faux_terminal.<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: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>msg<span style="color: black;">&#41;</span>
Les nipple clamps coutent <span style="color: #ff4500;">13.01</span>€</pre></td></tr></table></div>

<p>Vous l&#8217;avez compris, <code>print()</code> est fantastique pour les cas simples, mais devient rapidement peu pratique pour les cas complexes : <strong>son rôle est d&#8217;être bon à afficher, pas à formater.</strong></p>
<h2>Avec +</h2>
<p>A ce stade, un débutant va généralement taper &#8220;concaténation string python&#8221; sur son moteur de recherche et tomber sur l&#8217;opérateur <code>+</code>. Il essaye alors ça :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;Les &quot;</span> + produit + <span style="color: #483d8b;">&quot; coutent &quot;</span> + total + <span style="color: #483d8b;">&quot;€&quot;</span>
---------------------------------------------------------------------------
<span style="color: #008000;">TypeError</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;">19</span>-126b156e23bd<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: #483d8b;">&quot;Les &quot;</span> + produit + <span style="color: #483d8b;">&quot; coutent &quot;</span> + total + <span style="color: #483d8b;">&quot;€&quot;</span>
&nbsp;
<span style="color: #008000;">TypeError</span>: Can<span style="color: #483d8b;">'t convert '</span><span style="color: #008000;">float</span><span style="color: #483d8b;">' object to str implicitly</span></pre></td></tr></table></div>

<p>Et il apprend par la même occasion que Python est fortement typé. On ne peut pas additionner des choux et des carottes disait ma prof de CE1, et donc on ne peut pas additionner <code>"coutent"</code> (type <code>str</code>) et <code>total</code> (type <code>float</code>).</p>
<p>Il faut donc convertir total :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;Les &quot;</span> + produit + <span style="color: #483d8b;">&quot; coutent &quot;</span> + <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>total<span style="color: black;">&#41;</span> + <span style="color: #483d8b;">&quot;€&quot;</span>
    <span style="color: #483d8b;">'Les nipple clamps coutent 13.01€'</span></pre></td></tr></table></div>

<p>C&#8217;est mieux que notre version avec <code>print()</code>, d&#8217;autant qu&#8217;on peut sauvegarde facilement tout ça dans une variable :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> total <span style="color: #66cc66;">=</span> <span style="color: #008000;">round</span><span style="color: black;">&#40;</span>prix + exo_taxe<span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> msg <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;Les &quot;</span> + produit + <span style="color: #483d8b;">&quot; coutent &quot;</span> + <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>total<span style="color: black;">&#41;</span> + <span style="color: #483d8b;">&quot;€&quot;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>msg<span style="color: black;">&#41;</span>
Les nipple clamps coutent <span style="color: #ff4500;">13.01</span>€</pre></td></tr></table></div>

<p>Mais ça reste chiant à taper, et encore plus à modifier. Si je veux insérer quelque chose là dedans, il me faut faire très attention en déplaçant mes <code>+</code> et mes <code>"</code> sans compter calculer ma gestion des espaces.</p>
<p>La raison est simple : il est difficile de voir la phrase que j&#8217;essaye d&#8217;afficher sans bien étudier mon expression.</p>
<p>Par ailleurs, je suis toujours obligé de faire mon arrondi.</p>
<p>Pour cette raison, je recommande de ne pas utiliser <code>+</code> pour formatter son texte, car il existe de bien meilleurs outils en Python.</p>
<h2>Avec %</h2>
<p>Là, on arrive à quelque chose de plus sympa !</p>
<p>L&#8217;opérateur <code>%</code> appliqué aux chaînes de caractères permet de définir un texte à trou, et ensuite de dire quoi mettre dans les trous. C&#8217;est une logique de template.</p>
<p>Elle est courte et pratique : c&#8217;est la méthode que j&#8217;utilise le plus actuellement dans un shell ou sur les chaînes courtes.</p>
<p>Par exemple, si je veux créer la chaîne:</p>
<pre>Les nipple clamps coutent 13€</pre>
<p>Alors mon texte à trou va ressembler à :</p>
<pre>Les [insérer ici le nom du produit] coutent [insérer ici le prix du produit]€</pre>
<p>Avec l&#8217;opérateur <code>%</code>, le texte à trou s&#8217;écrit :</p>
<pre>Les %s coutent %s€</pre>
<p><code>%s</code> marque les trous.</p>
<p>Pour remplir, on met les variables à droite, dans l&#8217;ordre des trous à remplir :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> total <span style="color: #66cc66;">=</span> <span style="color: #008000;">round</span><span style="color: black;">&#40;</span>prix + exo_taxe<span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;Les %s coutent %s€&quot;</span> % <span style="color: black;">&#40;</span>produit<span style="color: #66cc66;">,</span> total<span style="color: black;">&#41;</span>
    <span style="color: #483d8b;">'Les nipple clamps coutent 13.01€'</span></pre></td></tr></table></div>

<p>Pas besoin de convertir total en <code>str</code>, et la phrase qu&#8217;on souhaite obtenir est facile à deviner en lisant l&#8217;expression.</p>
<p><code>%s</code> veut dire &#8220;met moi ici la conversion en <code>str</code> de cet objet&#8221;. C&#8217;est comme si on appelait <code>str(total)</code>.</p>
<p>Il existe d&#8217;autres marqueurs :</p>
<ul>
<li><code>%d</code> est comme si faisait int() sur la valeur.</li>
<li><code>%f</code> est comme si faisait float() sur la valeur.</li>
<li><code>%x</code> est comme si on faisait hex()[2:]</li>
<li>etc</li>
</ul>
<p>Ex:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;%d&quot;</span> % <span style="color: #ff4500;">28.01</span>
    <span style="color: #483d8b;">'28'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;%f&quot;</span> % <span style="color: #ff4500;">28</span>
    <span style="color: #483d8b;">'28.000000'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;%x&quot;</span> % <span style="color: #ff4500;">28</span>
    <span style="color: #483d8b;">'1c'</span></pre></td></tr></table></div>

<p>La liste des marqueurs est disponible <a href="https://docs.python.org/3.1/library/string.html#formatspec">sur cette page de la doc</a>.</p>
<p>En plus des marqueurs qui permettent de savoir où insérer la valeur et quel format lui donner, on peut aussi donner des précisions sur l&#8217;opération de formattage. On peut par ainsi décider de combien de chiffres après la virgule on souhaite, ou obliger la valeur à avoir une certaine taille :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;%4d&quot;</span> % <span style="color: #ff4500;">28</span> <span style="color: #808080; font-style: italic;"># au moins 4 caratères</span>
    <span style="color: #483d8b;">'  28'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;%04d&quot;</span> % <span style="color: #ff4500;">28</span> <span style="color: #808080; font-style: italic;"># au moins 4 chiffres</span>
    <span style="color: #483d8b;">'0028'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;%.2f&quot;</span> % <span style="color: #ff4500;">28</span> <span style="color: #808080; font-style: italic;"># 2 chiffres après la virgule</span>
    <span style="color: #483d8b;">'28.00'</span></pre></td></tr></table></div>

<p>Ainsi notre exemple:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> total <span style="color: #66cc66;">=</span> <span style="color: #008000;">round</span><span style="color: black;">&#40;</span>prix + exo_taxe<span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;Les %s coutent %s€&quot;</span> % <span style="color: black;">&#40;</span>produit<span style="color: #66cc66;">,</span> total<span style="color: black;">&#41;</span>
    <span style="color: #483d8b;">'Les nipple clamps coutent 13.01€'</span></pre></td></tr></table></div>

<p>Peut maintenant être réduit à :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> total <span style="color: #66cc66;">=</span> prix + exo_taxe
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;Les %s coutent %.2f€&quot;</span> % <span style="color: black;">&#40;</span>produit<span style="color: #66cc66;">,</span> total<span style="color: black;">&#41;</span>
    <span style="color: #483d8b;">'Les nipple clamps coutent 13.01€'</span></pre></td></tr></table></div>

<p>Néanmoins un des défauts de <code>%</code> est qu&#8217;il n&#8217;accepte qu&#8217;un tuple, ou une valeur seule. Impossible de passer un itérable arbitraire:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;Les %s coutent %.2f€&quot;</span> % <span style="color: black;">&#91;</span>produit<span style="color: #66cc66;">,</span> total<span style="color: black;">&#93;</span>
---------------------------------------------------------------------------
<span style="color: #008000;">TypeError</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;">5</span>-bb9b7acda392<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: #483d8b;">&quot;Les %s coutent %.2f€&quot;</span> % <span style="color: black;">&#91;</span>produit<span style="color: #66cc66;">,</span> total<span style="color: black;">&#93;</span>
&nbsp;
<span style="color: #008000;">TypeError</span>: <span style="color: #ff7700;font-weight:bold;">not</span> enough arguments <span style="color: #ff7700;font-weight:bold;">for</span> format <span style="color: #dc143c;">string</span></pre></td></tr></table></div>

<p>Et si vous voulez formatter un tuple, il faut le mettre dans un tuple d&#8217;un seul élément, source de plantage :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;Les données sont %s&quot;</span> % data
---------------------------------------------------------------------------
<span style="color: #008000;">TypeError</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;">10</span>-4e21e97b8a3f<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: #483d8b;">&quot;Les données sont %s&quot;</span> % data
&nbsp;
<span style="color: #008000;">TypeError</span>: <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">all</span> arguments converted during <span style="color: #dc143c;">string</span> formatting
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;Les données sont %s&quot;</span> % <span style="color: black;">&#40;</span>data<span style="color: #66cc66;">,</span> <span style="color: black;">&#41;</span>
    <span style="color: #483d8b;">&quot;Les données sont ('nipple clamps', 13.01)&quot;</span></pre></td></tr></table></div>

<p>Tout codeur Python s&#8217;est retrouvé un jour devant ce cas et s&#8217;est gratté la tête.</p>
<p>Par ailleurs, dès qu&#8217;il y a beaucoup de trous à combler dans le texte, ça devient vite difficile de savoir ce qui va où :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"> <span style="color: #483d8b;">&quot;[%s] %s%s %s(%s) - %s%s%s&quot;</span>  % <span style="color: black;">&#40;</span>
        <span style="color: #dc143c;">datetime</span>.<span style="color: #dc143c;">datetime</span>.<span style="color: black;">now</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span>
        res<span style="color: #66cc66;">,</span>
        unit<span style="color: #66cc66;">,</span>
        <span style="color: #008000;">type</span><span style="color: #66cc66;">,</span>
        variant<span style="color: #66cc66;">,</span>
        testers<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span>
        testers<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span>
        testers<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span>
  <span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Pour pallier ce problème, <code>%</code> peut accepter aussi un dictionnaire et avoir des trous nommés :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"> <span style="color: #483d8b;">&quot;[%(date)s] %(value)s%(unit)s %(type)s(%(variant)s) - %(tester1)s%(tester2)s%(tester3)s&quot;</span>  % <span style="color: black;">&#40;</span>
        <span style="color: #483d8b;">&quot;date&quot;</span>: <span style="color: #dc143c;">datetime</span>.<span style="color: #dc143c;">datetime</span>.<span style="color: black;">now</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span>
        <span style="color: #483d8b;">&quot;value&quot;</span>: res<span style="color: #66cc66;">,</span>
        <span style="color: #483d8b;">&quot;unit&quot;</span>: <span style="color: #483d8b;">&quot;m&quot;</span>
        <span style="color: #483d8b;">&quot;type&quot;</span>: <span style="color: #483d8b;">&quot;3&quot;</span><span style="color: #66cc66;">,</span>
        <span style="color: #483d8b;">&quot;variant&quot;</span>: <span style="color: #483d8b;">&quot;beta&quot;</span><span style="color: #66cc66;">,</span>
        <span style="color: #483d8b;">&quot;tester1&quot;</span>: testers<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span>
        <span style="color: #483d8b;">&quot;tester1&quot;</span>: testers<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span>
        <span style="color: #483d8b;">&quot;tester1&quot;</span>: testers<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span>
  <span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>On peut voir néanmoins que le pari n&#8217;est pas tout à fait gagné. Et on ne gagne pas tant que ça en lisibilité. Pour cette raison, les formatages complexes sont plus intéressants à faire avec <code>format()</code> que nous verrons plus loin.</p>
<p>Rappelez-vous néanmoins que depuis Python 3, <code>format()</code> ne fonctionne plus sur les bytes. <code>%</code> reste donc la seule option pour formater des paquets réseaux, des headers de jpeg et tout autre format binaire.</p>
<h2>Formatter les dates</h2>
<p>Même si il est toujours recommandé d&#8217;utiliser <a href="https://pendulum.eustace.io/docs/#string-formatting">une bonne lib</a> pour manipuler les dates, Python permet déjà de faire pas mal de choses avec la lib standard.</p>
<p>En effet, certaines notions, comme le temps, ont une forme très différente entre celle utilisée pour les manipuler, et celles utilisees pour les représenter.</p>
<p>Pour cette raison, l&#8217;objet <code>date</code> de Python propose deux méthodes, <code>strptime</code> et <code>strftime</code>, pour gérer le format des dates.</p>
<p>La procédure pour gérer les dates se fait donc toujours en 3 parties, un peu comme l&#8217;encoding d&#8217;un texte :</p>
<ol>
<li>Créer une nouvelle date, soit à la main, soit à partir de données existantes.</li>
<li>Manipuler les dates pour obtenir ce qu&#8217;on souhaite (un autre date, un durée, un intervalle, etc.</li>
<li>Formater le résultat pour le présenter à l&#8217;utilisateur ou le sauvegarder à nouveau.</li>
</ol>
<p>Pour récupérer une date existante, on va utiliser <code>strptime</code> (&#8220;str&#8221; pour string, &#8220;p&#8221; pour parse) :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&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 <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">datetime</span>.<span style="color: black;">strptime</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;1/4/2017&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;%d/%m/%Y&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> date.<span style="color: black;">year</span>
    <span style="color: #ff4500;">2017</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> date.<span style="color: black;">day</span>
    <span style="color: #ff4500;">1</span></pre></td></tr></table></div>

<p>Le deuxième paramètre contient le motif à extraire de la chaine de gauche : c&#8217;est l&#8217;inverse d&#8217;un texte à trou ! On dit &#8220;dans la chaîne de gauche, j&#8217;ai le jour là, le mois là et l&#8217;année là, maintenant extrait les&#8221;.</p>
<p>Pour formater une date, c&#8217;est la même chose, mais dans l&#8217;autre sens, avec strftime (&#8220;f&#8221; pour format) :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> date <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">datetime</span>.<span style="color: black;">now</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> date.<span style="color: black;">strp</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> date.<span style="color: black;">strftime</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'%m-%d-%y'</span><span style="color: black;">&#41;</span>
    <span style="color: #483d8b;">'04-01-17'</span></pre></td></tr></table></div>

<p>Le mini-langage pour formater les dates est <a href="https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior">documenté ici</a>, et vous pouvez en apprendre plus sur les dates sur <a href="http://sametmax.com/manipuler-les-dates-et-les-durees-en-python/">une petite intro dédiée</a>.</p>
<h2>Avec format()</h2>
<p><code>%</code> a ses limites. C&#8217;est un opérateur pratique pour les petites chaînes et les cas de tous les jours, mais si on a beaucoup de valeurs à formafter, cela peut devenir vite un problème. Il possède aussi quelques cas d&#8217;utilisation qui causes des erreurs inatendues puis qu&#8217;il n&#8217;accepte que les tuples.</p>
<p><code>format()</code> a été créé pour remédier à cela. Dans sa forme la plus simple, il s&#8217;utilise presque comme <code>%</code>, mais les marqueurs sont des <code>{}</code> et non des <code>%s</code> :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;Les {} coutent {}€&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>produit<span style="color: #66cc66;">,</span> prix<span style="color: black;">&#41;</span>
    <span style="color: #483d8b;">'Les nipple clamps coutent 13€'</span></pre></td></tr></table></div>

<p>Mais déjà, <code>format()</code> se distingue du lot car il permet de choisir l&#8217;ordre d&#8217;insertion :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;Les {1} coutent {0}€&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>prix<span style="color: #66cc66;">,</span> produit<span style="color: black;">&#41;</span>
    <span style="color: #483d8b;">'Les nipple clamps coutent 13€'</span></pre></td></tr></table></div>

<p>La méthode accepte également n&#8217;importe quel itérable grace à l&#8217;unpacking :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;Les {} coutent {}€&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>*<span style="color: black;">&#91;</span>produit<span style="color: #66cc66;">,</span> prix<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    <span style="color: #483d8b;">'Les nipple clamps coutent 13€'</span></pre></td></tr></table></div>

<p>Formatter un tuple seul est aussi très simple :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;Les données sont {}&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>data<span style="color: black;">&#41;</span>
    <span style="color: #483d8b;">&quot;Les données sont ('nipple clamps', 13.01)&quot;</span></pre></td></tr></table></div>

<p>Mais là où <code>format()</code> est bien plus pratique, c&#8217;est quand on a beaucoup de données et qu&#8217;on veut nommer ses trous :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"> <span style="color: #483d8b;">&quot;[{date}] {value}{unit} {type}({variant}) - {testers[0]}{testers[1]}{testers[2]}&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>
        date<span style="color: #66cc66;">=</span><span style="color: #dc143c;">datetime</span>.<span style="color: #dc143c;">datetime</span>.<span style="color: black;">now</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span>
        value<span style="color: #66cc66;">=</span>res<span style="color: #66cc66;">,</span>
        unit<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;m&quot;</span>
        <span style="color: #008000;">type</span><span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;3&quot;</span><span style="color: #66cc66;">,</span>
        variant<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;beta&quot;</span><span style="color: #66cc66;">,</span>
        testers<span style="color: #66cc66;">=</span>testers
  <span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Le texte à trou est plus clair, et on peut utiliser l&#8217;index d&#8217;une liste directement dedans.</p>
<p>Un autre avantage non négligeable, est que <code>format()</code> n&#8217;utilise pas de nombreux marqueurs différents comme <code>%f</code>, <code>%d</code>, <code>%s</code>&#8230;</p>
<p>A la place, il n&#8217;y a que <code>{}</code>, et <code>format()</code> appelle en fait pour chaque valeur sa méthode &#8230; <code>__format__</code>, ou en l&#8217;absence de celle-ci appelle <code>str()</code>.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> a <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">42</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> a.__format__<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #483d8b;">'42'</span></pre></td></tr></table></div>

<p>Chaque objet peut définir <code>__format__</code>, et accepter ses propres options:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> a.__format__<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;.2f&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #483d8b;">'42.00'</span>
<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> datetimes
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">datetime</span>.<span style="color: black;">now</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.__format__<span style="color: black;">&#40;</span><span style="color: #483d8b;">'%d %h'</span><span style="color: black;">&#41;</span>  <span style="color: #808080; font-style: italic;"># pas besoin de strftime !</span>
    <span style="color: #483d8b;">'20 Sep'</span></pre></td></tr></table></div>

<p>Et format utilise tout ce qui est après : dans un trou pour le passer à <code>__format__</code>:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">&quot;{foo:.2f} {bar:%d %h}&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>foo<span style="color: #66cc66;">=</span><span style="color: #ff4500;">42</span><span style="color: #66cc66;">,</span> bar<span style="color: #66cc66;">=</span><span style="color: #dc143c;">datetime</span>.<span style="color: black;">now</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Cela permet des formatages très poussés.</p>
<h2>Les f-strings</h2>
<p>Les f-strings sont une nouvelle fonctionnalité de Python 3.6, et elles sont merveilleuses, combinant les avantages de <code>.format()</code> et <code>%</code>, sans les inconvénients :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> produit <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;nipple clamps&quot;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> prix <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">13</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>f<span style="color: #483d8b;">&quot;Les {produit} coutent {prix:.2f} euros&quot;</span><span style="color: black;">&#41;</span>
Les nipple clamps coutent <span style="color: #ff4500;">13.00</span> euros</pre></td></tr></table></div>

<p>En gros, c&#8217;est la syntaxe de <code>format()</code>, mais dans sa verbosité.</p>
<p>En prime, on peut utiliser des expressions arbitraires dedans:</p>

<div class="wp_syntax"><table><tr><td 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>f<span style="color: #483d8b;">&quot;Les {produit.upper()} coutent {prix:.2f} euros&quot;</span><span style="color: black;">&#41;</span>
Les NIPPLE CLAMPS coutent <span style="color: #ff4500;">13.00</span> euros</pre></td></tr></table></div>

<p>A première vue, ça ressemble a du exec, et donc a un parsing lent, doublé d&#8217;une une grosse faille de sécurité.</p>
<p>Et bien non !</p>
<p>C&#8217;est en fait du sucre syntaxique, et au parsing du code, Python va transformer l&#8217;expression en un truc du genre:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">&quot;Les &quot;</span> + <span style="color: #483d8b;">&quot;{}&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>produit.<span style="color: black;">upper</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> + <span style="color: #483d8b;">&quot; coutent &quot;</span> + <span style="color: #483d8b;">&quot;{:.2f}&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>prix<span style="color: black;">&#41;</span> + <span style="color: #483d8b;">&quot; euros&quot;</span></pre></td></tr></table></div>

<p>Mais en bytecode. Pas d&#8217;injection de code Python possible, et en prime, les f-strings sont aujourd&#8217;hui la méthode formattage <a href="https://cito.github.io/blog/f-strings/">la plus performante</a>.</p>
<p>En clair, si vous êtes en 3.6+, vous pouvez oublier toutes les autres.</p>
<h2>Méthodes de l&#8217;objet str</h2>
<p>Parfois, on ne veut pas remplir un texte à trou. Parfois on a déjà le texte et on veut le transformer. Pour cela, l&#8217;objet <code>str</code> possède de nombreuses méthodes qui permet de créer une nouvelle chaîne, qui possède des traits différents :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;    strip() retire les caractères en bouts de chaîne   &quot;</span>.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># espace par défaut</span>
    <span style="color: #483d8b;">'strip() retire les caractères en bouts de chaîne'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;##strip() retire les caractères en bouts de chaîne&quot;</span><span style="color: #808080; font-style: italic;">##&quot;.strip(&quot;#&quot;)</span>
    <span style="color: #483d8b;">'strip() retire les caractères en bouts de chaîne'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #808080; font-style: italic;">##strip() retire les caractères en bouts de chaîne&quot;##&quot;.lstrip(&quot;#&quot;)</span>
    <span style="color: #483d8b;">'strip() retire les caractères en bouts de chaîne&quot;##'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #808080; font-style: italic;">##strip() retire les caractères en bouts de chaîne&quot;##&quot;.rstrip(&quot;#&quot;)</span>
    <span style="color: #483d8b;">'&quot;##strip() retire les caractères en bouts de chaîne'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;wololo&quot;</span>.<span style="color: black;">replace</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'o'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'i'</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># remplacer des lettres</span>
    <span style="color: #483d8b;">'wilili'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;WOLOLO&quot;</span>.<span style="color: black;">lower</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># changer la casse</span>
    <span style="color: #483d8b;">'wololo'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;wololo&quot;</span>.<span style="color: black;">upper</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #483d8b;">'WOLOLO'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;wololo&quot;</span>.<span style="color: black;">title</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #483d8b;">'Wololo'</span></pre></td></tr></table></div>

<p>Notez bien que ces méthodes créent de nouvelles chaînes. L&#8217;objet initial n&#8217;est pas modifié, puisque les strings sont immutables en Python.</p>
<p>Parmi les plus intéressantes, il y a <code>split()</code> et <code>join()</code>, qui ont une caractéristique particulière : elles ne transforment pas une chaîne en une autre.</p>
<p><code>split()</code> prend une chaine, et retourne&#8230; une liste !</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;split() découpe une chaîne en petits bouts&quot;</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># défaut sur espaces</span>
    <span style="color: black;">&#91;</span><span style="color: #483d8b;">'split()'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'découpe'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'une'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'chaîne'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'en'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'petits'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'bouts'</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;split() découpe une chaîne en petits bouts&quot;</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;e&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: black;">&#91;</span><span style="color: #483d8b;">'split() découp'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">' un'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">' chaîn'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">' '</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'n p'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'tits bouts'</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p><code>join()</code> fait l&#8217;inverse, et prend un <a href="http://sametmax.com/les-trucmuchables-en-python/">itérable</a> (comme une liste), pour retourner&#8230; une chaîne :)</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;-&quot;</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'split()'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'recolle'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'une'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'chaîne'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'DEPUIS'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'des'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'petits'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'bouts'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    <span style="color: #483d8b;">'split()-recolle-une-chaîne-DEPUIS-des-petits-bouts'</span></pre></td></tr></table></div>

<p>Avec juste ces méthodes, on peut s&#8217;autoriser pas mal de fantaisies avec le texte, et le nombre de méthodes disponibles est assez large :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">dir</span><span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#41;</span>
    <span style="color: black;">&#91;</span>...
 <span style="color: #483d8b;">'capitalize'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'casefold'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'center'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'count'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'encode'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'endswith'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'expandtabs'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'find'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'format'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'format_map'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'index'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'isalnum'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'isalpha'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'isdecimal'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'isdigit'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'isidentifier'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'islower'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'isnumeric'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'isprintable'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'isspace'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'istitle'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'isupper'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'join'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'ljust'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'lower'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'lstrip'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'maketrans'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'partition'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'replace'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'rfind'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'rindex'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'rjust'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'rpartition'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'rsplit'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'rstrip'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'split'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'splitlines'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'startswith'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'strip'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'swapcase'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'title'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'translate'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'upper'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'zfill'</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p> Donc référez-vous <a href="https://docs.python.org/3/library/stdtypes.html#string-methods">à la doc</a>.</p>
<h2>Caractères spéciaux</h2>
<p>On vous a menti !</p>
<p>Quand on écrit <code>""</code> en Python on ne crée pas une chaîne. En fait, on écrit une instruction qui dit à Python comment créer une chaîne.</p>
<p>La différence est subtile, mais importante. <code>""</code> n&#8217;est PAS la chaîne, <code>""</code> est une instruction, une indication pour Python de comment il doit procéder pour créer une chaîne.</p>
<p>Et on peut donner des instructions plus précises à Python. Par exemple on peut dire, &#8220;insère moi ici un saut de ligne&#8221;. Cela se fait avec le marqueur <code>"\n"</code>.</p>

<div class="wp_syntax"><table><tr><td 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;">'un saut<span style="color: #000099; font-weight: bold;">\n</span> de ligne'</span><span style="color: black;">&#41;</span>
un saut
 de ligne</pre></td></tr></table></div>

<p><code>\n</code> n&#8217;est PAS un saut de ligne. C&#8217;est juste une indication donnée à Python pour lui dire qu&#8217;ici, il doit insérer un saut de ligne quand il créera la chaîne en mémoire.</p>
<p>Il existe plusieurs marqueurs de ce genre, les plus importants étant <code>\n</code> (saut de ligne) et <code>\t</code> (tabulation).</p>
<p>Pour rentrer les caratères <code>\t\n</code>, il faut donc dire à Python explicitement qu&#8217;on ne veut pas qu&#8217;il insère un saut de ligne ou une tabulation, mais plutôt ces caractères.</p>
<p>Cela peut se faire, soit avec le caractères d&#8217;échappement <code>\</code> :</p>

<div class="wp_syntax"><table><tr><td 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;">'pas un saut<span style="color: #000099; font-weight: bold;">\\</span>n de ligne'</span><span style="color: black;">&#41;</span>
pas un saut\n de ligne</pre></td></tr></table></div>

<p>Soit en désactivant cette fonctionalité avec le préfixe <code>r</code>, pour <a href="http://sametmax.com/comment-marchent-les-raw-strings-en-python/">raw string</a>:</p>

<div class="wp_syntax"><table><tr><td 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>r<span style="color: #483d8b;">'pas un saut<span style="color: #000099; font-weight: bold;">\n</span> de ligne'</span><span style="color: black;">&#41;</span>
pas un saut\n de ligne</pre></td></tr></table></div>

<p>Cette fonctionalité est très utilisée pour les noms de fichiers Windows et les expressions rationnelles car ils contiennent souvent <code>\t\n</code>.</p>
<h2>Bytes, strings et encoding</h2>
<p>Python fait une distinction très forte entre les octets (type <code>bytes</code>) et le texte (type <code>str</code>). La raison est qu&#8217;il n&#8217;existe pas de texte brut dans la vraie vie, et que tout ce que vous lisez : fichiers, base de données, socket réseau, et même votre code source (!) est un flux d&#8217;octets encodés dans un certain ordre pour représenter du texte.</p>
<p>En Python, on a donc le type <code>str</code> pour représenter du texte, une forme d&#8217;abtraction de toute forme d&#8217;encodage qui permet de manipuler ses données textuelles sans se soucier de comment il est représenté en mémoire.</p>
<p>En revanche, quand on importe du texte (lire, télécharge, parser, etc) ou qu&#8217;on exporte du texte (écrire, afficher, uploader, etc), il faut explicitement convertir son texte vers le type <code>bytes</code>, qui lui a un encoding en particulier.</p>
<p>Ce principe mérite un article à lui tout seul, et je vous renvoie donc à la <a href="http://sametmax.com/lencoding-en-python-une-bonne-fois-pour-toute/">page dédiée du blog.</a></p>
<h2>Templating</h2>
<p>Parfois on a beaucoup de texte à gérer. Par exemple, si vous faites un site Web, vous aurez beaucoup de HTML. Dans ce cas, faire tout le formatage dans son fichier Python n&#8217;est pas du tout pragmatique.</p>
<p>Pour cet usage particulier, on utilise ce qu&#8217;on appelle un moteur de template, c&#8217;est à dire une bibliothèque qui va vous permettre de mettre votre texte à trou dans un fichier à part. Les moteurs de templates sophistiqués vous permettent de faire quelques opérations logiques comme des boucles ou des conditions dans votre texte.</p>
<p>La première chose à savoir, c&#8217;est de ne PAS utiliser <a href="https://docs.python.org/3.4/library/string.html#string.Template">string.Template</a>. Cette classe ne permet d&#8217;utiliser aucune logique, n&#8217;est n&#8217;a aucun avantage par rapport à <code>.format()</code>.</p>
<p>Pour le templating, il vaut mieux se pencher vers une lib tièrce partie. Les deux principaux concurrents sont <a href="http://jinja.pocoo.org/">Jinja2</a>, le moteur de templating le plus populaire en Python, créé par l&#8217;auteur de Flask. Et <a href="https://docs.djangoproject.com/en/1.10/topics/templates/">le moteur de Django</a>, fourni par défaut par le framework.</li>
<p>Depuis Django 1.10, le framework supporte aussi jinja2, donc je vais vous donner un exemple avec ce dernier. Sachez qu&#8217;il existe bien d&#8217;autres moteurs (mako, cheetah, templite, TAL&#8230;) mais jinja2 a plus ou moins gagné la guerre.</p>
<p>Un coup de <a href="http://sametmax.com/votre-python-aime-les-pip/">pip</a> :</p>

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

<p>On fait son template dans un fichier à part, par exemple <em>wololo.txt</em>:</p>
<pre>Regardez je sais compter :
  {% for number in numbers %}
    - {{number}}
  {% endfor %}
</pre>
<p>Puis en Python:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> jinja2
&nbsp;
<span style="color: #808080; font-style: italic;"># On Définit où trouver les fichiers de template. Ex, le dossier courant:</span>
jinja_env <span style="color: #66cc66;">=</span> jinja2.<span style="color: black;">Environment</span><span style="color: black;">&#40;</span>loader<span style="color: #66cc66;">=</span>jinja2.<span style="color: black;">FileSystemLoader</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'.'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On dit à jinja de charger le template à partir de son chemin relatif</span>
template <span style="color: #66cc66;">=</span> jinja_env.<span style="color: black;">get_template</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'wololo.txt'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On crée un contexte, c'est à dire une collection d'objects qu'on veut rendre</span>
<span style="color: #808080; font-style: italic;"># accessibles dans le template. Généralement, c'est un dictionnaire dont les</span>
<span style="color: #808080; font-style: italic;"># clés sont les noms des variables telles qu'elle apparaitrons dans le template</span>
<span style="color: #808080; font-style: italic;"># et les valeurs ce que contiendrons ces variables.</span>
ctx <span style="color: #66cc66;">=</span> <span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;numbers&quot;</span>: <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span><span style="color: black;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On demande le &quot;rendu&quot; du template, c'est à dire le mélange du template</span>
<span style="color: #808080; font-style: italic;"># et du contexte.</span>
resultat <span style="color: #66cc66;">=</span> template.<span style="color: black;">render</span><span style="color: black;">&#40;</span>ctx<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>resultat<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Ce qui donne :</span>
<span style="color: #808080; font-style: italic;"># - 1</span>
<span style="color: #808080; font-style: italic;"># - 2</span>
<span style="color: #808080; font-style: italic;"># - 3</span></pre></td></tr></table></div>

<h2>i18n et l10n</h2>
<p>L&#8217;i18n, pour &#8216;internationalisation&#8217; (soit 18 lettres entre le i et le n) est le fait d&#8217;organiser votre code de telle sorte que son interface puisse s&#8217;adapter à plusieurs cultures. La l10n, pour &#8216;localisation&#8217; (soit 10 lettres en le l et le n), est le fait de fournir avec son code les données nécessaires pour une culture en particulier.</p>
<p>Par exemple, marquer toutes vos chaines de caractères comme étant traductibles et fournir un mécanisme de substitution de la chaine est de l&#8217;i18n. Fournir un fichier de traduction pour l&#8217;espagnol pour ces chaînes est de la l10n.</p>
<p>La combinaison des deux est parfois nommée g11n pour &#8220;globalization&#8221;.</p>
<p>La g11n peut inclure:</p>
<ul>
<li>La gestion de l&#8217;UI (traduction, sens de la lecture, formatage des nombres, devise&#8230;)</li>
<li>La gestion des dates (formatage, différences de type de calendriers, événements locaux, ordre des jours&#8230;). </li>
<li>La gestion du temps (zones horaires, heure d&#8217;été&#8230;)</li>
<li>La gestion de la géolocation (fournir des informations autour de soi, filtrer par la distance&#8230;).</li>
<li>La gestion polique et culturelle (symbolisme des couleurs, adaptation du contenu aux moeurs&#8230;).</li>
<li>La gestion légale (services et contenus selon la loi en vigueur, warnings obligatoires&#8230;)</li>
</ul>
<p>Plus qu&#8217;un article, c&#8217;est un dossier qu&#8217;il faudrait faire sur ces sujets car c&#8217;est très, très vaste.</p>
<p>La traduction de texte peut être faite directement avec le module <a href="https://docs.python.org/dev/library/gettext.html">gettext</a> fournit en Python. Certains formatages de nombres et de dates sont aussi faisables avec la stdlib grace au module <a href="https://docs.python.org/2/library/locale.html">locale</a>.</p>
<p>Néanmoins dès que vous voulez faire quelque chose de plus gros avec la g11n, je vous invite à vous tourner vers des libs externes. </p>
<p><a href="http://babel.pocoo.org/en/latest/">Babel</a> est la référence en Python pour le formatage du texte et des nombres, et il existe <a href="http://jinja.pocoo.org/docs/2.9/extensions/#i18n-extension">des extensions</a> pour les moteurs de template les plus populaires. La lib inclut une base de données aussi à jour que possible sur les devises, les noms de pays, les langues&#8230;</p>
<p><a href="https://pendulum.eustace.io/">pendulum</a> est idéal pour la manipulation des dates en général, et des fuseaux horaires en particulier, y compris pour le formatage. Et ça évite de manipuler <a href="http://pytz.sourceforge.net/">pytz</a> à la main.</p>
<p>Et pour le reste&#8230; bonne chance !</p>
<h2>Programmation orientée objet</h2>
<p>Souvenez-vous, Python <a href="http://sametmax.com/le-guide-ultime-et-definitif-sur-la-programmation-orientee-objet-en-python-a-lusage-des-debutants-qui-sont-rassures-par-les-textes-detailles-qui-prennent-le-temps-de-tout-expliquer-partie-1/">a des méthodes magiques</a>. 3 sont dédiées au formatages.</p>
<p><strong>__repr__</strong> est utilisé quand on appelle <code>repr()</code> sur un objet. Typiquement, c&#8217;est ce qui s&#8217;affiche dans le shell si on utilise pas <code>print()</code>. C&#8217;est aussi ce qui détermine la représentation d&#8217;un objet quand on affiche une collections qui le contient.</p>
<p><strong>__str__</strong> est utilisée quand on appelle <code>str()</code> sur un objet. Quand on fait <code>print()</code> dessus par exemple. Si <code>__str__</code> n&#8217;existe pas, <code>__repr__</code> est appelé.</p>
<p><strong>__format__</strong> est utilisé quand on passe cette objet à <code>format()</code>, ou que cet objet est utilisé dans une f-string.</p>
<p>Ex :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Foo:
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__repr__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;&lt;Everybody's kung foo fighting&gt;&quot;</span>
    <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;C'est l'histoire d'un foo qui rentre dans un bar&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> __format__<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> age<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>age <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">18</span>:
            <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;On s'en bat les couilles avec une tarte tatin. Tiède.&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;On s'en foo&quot;</span></pre></td></tr></table></div>

<p>Ce qui donne :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> Foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>Everybody<span style="color: #483d8b;">'s kung foo fighting&gt;
&gt;&gt;&gt; print(Foo())
C'</span>est l<span style="color: #483d8b;">'histoire d'</span>un foo qui rentre dans un bar
<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: black;">&#91;</span>Foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> Foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #66cc66;">&lt;</span>Everybody<span style="color: #483d8b;">'s kung foo fighting&gt;, &lt;Everybody'</span>s kung foo fighting<span style="color: #66cc66;">&gt;</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;J'ai envie de dire: {}&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>Foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">&quot;J'ai envie de dire: On s'en foo&quot;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> f<span style="color: #483d8b;">&quot;J'ai envie de dire: {Foo():19}&quot;</span>
<span style="color: #483d8b;">&quot;J'ai envie de dire: On s'en bat les couilles avec une tarte tatin. Tiède.&quot;</span></pre></td></tr></table></div>

<h2>Astuce de dernière minute</h2>
<p>Enfin pour conclure cet article dont la longueur n&#8217;a d&#8217;égale que celle de la période  entre deux publications sur le blog, une petite remarque.</p>
<p>S&#8217;il est certes courant de formatter une string, il est aussi possible de déformer un string. Ce sont des pièces plus résistantes qu&#8217;il n&#8217;y parait, et en cas d&#8217;empressement, le retrait total n&#8217;est pas nécessaire :</p>
<div id="attachment_21965" style="width: 650px" class="wp-caption aligncenter"><a href="media/7dc09002.CmNgtKeXIAAhU1z.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/01/CmNgtKeXIAAhU1z.jpg" class="grouped_elements" rel="tc-fancybox-group21963"><img src="media/7dc09002.CmNgtKeXIAAhU1z.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/01/CmNgtKeXIAAhU1z.jpg" alt="String en levrette" width="640" height="853" class="size-full wp-image-21965" /></a><p class="wp-caption-text">Ne pas porter de strings du tout évite aussi tout une classe de bugs</p></div>
<p>Assurez-vous juste que la partie ficelle soit suffisament éloignée pour éviter les frictions fort désagréables quand on entame un algo avec une grosse boucle.</p>
<p>Sinon, moins intéressant, mais toujours utile, les strings en Python peut êtres écrites sur plusieurs lignes de plusieurs manières:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> s <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Ceci est une chaine qui n'a pas &quot;</span> 
...      <span style="color: #483d8b;">&quot;de saut de ligne mais qui est &quot;</span>
...      <span style="color: #483d8b;">&quot;écrite sur plusieurs lignes&quot;</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>s<span style="color: black;">&#41;</span>
Ceci est une chaine qui n<span style="color: #483d8b;">'a pas de saut de ligne mais qui est écrite sur plusieurs lignes</span></pre></td></tr></table></div>

<p>Cela fonctionne car deux chaines litérales cote à cote en Python sont automatiquement concaténées au démarage du programme. Cela évite les <code>+ \</code> à chaque fin de ligne, pourvu qu&#8217;on ait des parenthèses de chaque côté de la chaîne.</p>
<p>L&#8217;alternative des triples quotes est assez connue:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> s <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;&quot;&quot;
...    Ceci est une chaine avec des sauts de lignes
...    écrite sur plusiers lignes.   
... &quot;&quot;&quot;</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>
&nbsp;
    Ceci est une chaine avec des sauts de lignes
    écrite sur plusiers lignes.</pre></td></tr></table></div>

<p>Pour éviter l&#8217;indentation et les espaces inutiles:</p>

<div class="wp_syntax"><table><tr><td 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;">textwrap</span> <span style="color: #ff7700;font-weight:bold;">import</span> dedent
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>dedent<span style="color: black;">&#40;</span>s<span style="color: black;">&#41;</span>.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
Ceci est une chaine avec des sauts de lignes
écrite sur plusiers lignes.</pre></td></tr></table></div>

<p>Perso j&#8217;ai un wrapper pour ça.</p>


feed_id: http://sametmax.com/?p=22032
title: Je peux faire un clone de Twitter en un week end 6 Recently updated !
uri: Je-peux-faire-un-clone-de-Twitter-en-un-week-end-6-Recently-updated
url: http://sametmax.com/je-peux-faire-un-clone-de-twitter-en-un-week-end/
content:
<p>Il ne se passe pas un mois sans que je ne lise le commentaire d&#8217;un abruti qui annonce être capable de réécrire service X en quelques jours. Des projets et des projets de <a href="https://encrypted.google.com/search?hl=en&#038;q=tweeter%20clone">clones</a> pour le prouver.</p>
<p>Twitter, Uber, Imgur, whatever.</p>
<p>Une variante est de <a href="https://news.ycombinator.com/item?id=13442846">juger la stack d&#8217;un service</a> en prétendant qu&#8217;on pourrait faire beaucoup mieux avec moins.</p>
<p>Je ne sais pas si c&#8217;est de la bêtise, de l&#8217;ignorance ou de l&#8217;arrogance. Probablement des trois.</p>
<p>Prenons par exemple Twitter. Easy non ? Des messages de 140 caractères, quelques tags.</p>
<p>Mais, mais, mais les amis. Ca c&#8217;était Twitter le premier week-end de sa sortie aussi.</p>
<p>Maintenant Twitter c&#8217;est beaucoup plus que ça:</p>
<ul>
<li>Suivi des messages en temps réel ou par historique complet.</li>
<li>Suivi par personne ou tag.</li>
<li>Possibilité de faire une recherche complexe sur des gens, tags ou du texte libre. Avec filtrage par settings comme la langue ou la date. Et obtenir les résultats en temps réel.</li>
<li>API complète pour accéder au service.</li>
<li>Analytics sur les tweets, personnes ou tags. Et l&#8217;auth, le bouton twitter, etc.</li>
<li>Auto-complétion partout.</li>
<li>UI responsive design, et compatible avec des dizaines de navigateurs.</li>
<li>Et une app mobile qui fonctionne sur 2 OS majeurs.</li>
<li>Upload de médias.</li>
<li>Minification d&#8217;URLs.</li>
<li>Instruments de modération et anti-spam.</li>
<li>Intégration de miniatures de contenus liés.</li>
<li>Intégrations avec services externes tels que Youtube, Slideshare, etc.</li>
<li>Comptes avec fonctionnalités professionnelles.</li>
</ul>
<p>Bien entendu avec son succès Twitter doit maintenant scaler et assurer:</p>
<ul>
<li>La connexion de centaines de millions d&#8217;utilisateurs chaque jour.</li>
<li>Qui postent et lisent des messages.</li>
<li>Qui peuvent être reçus par des millions d&#8217;utilisateurs. Et oui, c&#8217;est pas du chat. Un message ne va pas à une dizaine de destinataires.</li>
<li>Qui peuvent être reçus par des tags lus par des centaines de services en ligne. Et oui, en plus des abonnés, les messages sont aussi distribués par tag. Des millions de tags. Combinables arbitrairement.</li>
<li>L&#8217;historique de tous les tweets doit être accessible. Des milliards de tweet.</li>
<li>Gérer tout ce bordel alors que les messages sont un graphe. Et oui, entre les utilisateurs, les tags, les RT récursifs, les réponses et les likes, twitter n&#8217;est pas une timeline linéaire. C&#8217;est un graphe. Traité en quasi temps réel.</li>
<li>Se défendre contre les attaques, les abus du service, supporter le trending topics dûs à l&#8217;actualité.</li>
<li>Fournir le service dans des centaines de pays avec des langues, cultures, lois et situations politiques différentes.</li>
<li>Gérer la partie commerciale (faire de la thune) et marketing (préserver son image).</li>
<li>Gérer la boite : l&#8217;équipe, la thune, les locaux, les projets.</li>
<li>Gérer les incidents incongrus. Ben oui, si un truc à une chance de 0.0000000001% de se produire, sur un service qui a des centaines de millions de users qui s&#8217;activent comme les chimpanzés hystériques, ce truc arrive TOUS LES JOURS.</li>
</ul>
<p>Aujourd&#8217;hui ce service, c&#8217;est des millions de lignes de code.</p>
<p>En prime, un service à succès n&#8217;est pas que du code, c&#8217;est aussi une énorme infra. Une logistique de dingue. Et un effort marketing colossal.</p>
<p>Personne ne peut reproduire ce que fait X actuellement en un an de travail. Je ne parle pas d&#8217;un week-end.</p>
<p>Les projets que l&#8217;on voit sont des &#8220;représentation du concept clé de X&#8221;.</p>
<p>Ca ne veut pas dire qu&#8217;il ne faut pas essayer de copier, concurrencer, proposer des alternatives, etc. Faut juste pas prendre les gens pour des cons.</p>
<p>Bref, à tous les prétendants au &#8220;c&#8217;est super simple&#8221; présents, passés et futurs :</p>
<p><span class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='1170' height='689' src='http://www.youtube.com/embed/Ng2lqQlRkmA?version=3&#038;rel=1&#038;fs=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' frameborder='0' allowfullscreen='true'></iframe></span></p>


feed_id: http://sametmax.com/?p=22097
title: Augmenter son volume de sperme pour des super éjaculations faciales. 2 Recently updated !
uri: Augmenter-son-volume-de-sperme-pour-des-super-éjaculations-faciales
url: http://sametmax.com/augmenter-son-volume-de-sperme-pour-des-super-ejaculations-faciales/
content:
<p>Un sale titre putaclic comme je les aime :)</p>
<p>Comme tous les 2 mois je parts en mission spéciale pour m&#8217;adonner aux pratiques les plus salaces afin d&#8217;assouvir mes pulsions DSKniennes.</p>
<p>Et comme 99.99% des mecs j&#8217;adore les éjacs faciales mais aussi sur les pieds (fétichisme oblige) ou les fesses ou encore une bonne paire de nichons bien juteux.<br />
Il y a quelques années je m&#8217;étais renseigné sur des pilules pour augmenter le volume de sperme mais c&#8217;était du pipeau, j&#8217;ai donc regardé la composition du sperme et grosso modo la voici:</p>
<p><strong>Le sperme <a href="https://fr.wikipedia.org/wiki/Sperme">contient</a> de nombreux éléments nourriciers pour le spermatozoïde :</strong><br />
vitamines C et B12, sels minéraux comme le calcium, le magnésium, le phosphore, le potassium et le zinc, des sucres (fructose et sorbitol).</p>
<p>Je me suis penché sur les éléments les plus courants à trouver à savoir la vitamine C, B12, magnésium, zinc et fructose.</p>
<p>vitamine C = orange<br />
B12 = banane<br />
magnesium et zinc = cacao<br />
fructose = les fruits</p>
<p>Je me suis donc mis en tête d&#8217;ingurgiter quotidiennement ces ingrédients afin de tester une éventuelle augmentation du volume <em>spermique</em>.<br />
Mon test n&#8217;est basé sur absolument aucun étude scientifique, mais de toutes façons c&#8217;est que des produits naturels, et en plus ça file la pêche.</p>
<p>Bien évidement vous n&#8217;allez pas jouer au pompier du jour au lendemain mais j&#8217;ai pu noter une certaine augmentation du volume sans que ce soit non plus les chutes du niagara (le titre c&#8217;est juste pour être en premier dans les forums d&#8217;ados) mais je les trouves supérieures tout de même avec un certain avantage, une m&#8217;a dit que mon liquide séminal avait le goût de fruits, elle avait l&#8217;air d&#8217;en être plutôt contente.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><strong>Passons au cocktail !</strong></p>
<p><strong>2 fois par jour, en général 10h du math et 16/17h:</strong></p>
<p><strong><em>Dans un mixer versez:</em></strong></p>
<ul>
<li>1 banane</li>
<li>1 orange</li>
<li>une tête de menthe fraîche</li>
<li>un peu de lait d&#8217;amande</li>
<li>un mélange d&#8217;amandes pilées et de coco râpée (ça se trouve rayon patisserie)</li>
<li>du cacao en poudre</li>
<li>du miel</li>
<li>noix de cajou</li>
<li>cannelle</li>
</ul>
<p><strong>Mixez le tout pendant 5 minutes et servez frais !</strong></p>
<p>Faut faire ce &#8220;régime&#8221; pendant au moins quelques semaines et vous devriez voir les premiers résultats, madame sera ravie.<br />
Du 100% Bio ! Bon pour le teint.</p>
<div id="attachment_22098" style="width: 605px" class="wp-caption aligncenter"><img class="wp-image-22098 size-full" src="media/85ff8ac0.ban.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/01/ban.jpg" alt="ban" width="595" height="405" /><p class="wp-caption-text">chériiiiiiie, tes vitamines arrivent&#8230;</p></div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>PS: j&#8217;ai fait plusieurs tests et c&#8217;est celui qui me donne le plus de satisfaction, si vous avez des variantes ou des suggestions allez-y. A côté de ça j&#8217;ai une alimentation qui exclue tout produit surgelé ou transformé par l&#8217;industrie agro alimentaire, paraît qu&#8217;on appelle ça le régime paléo, perso je fais pas de régime, je bouffe comme ma grand-mère et mes parents, pas de junk food et je me sens bien.<br />
Je me gène pas me défoncer un plateau de fruits de mer à l&#8217;occas (au passage les huîtres sont blindées de zinc, B12, omega3 et ça a une texture de chatte alors pourquoi s&#8217;en priver ?!)</p>
<p>Pour les féministes défoulez-vous, mais n&#8217;oubliez pas vos cachets et le rendez-vous de demain chez le psy.</p>
<p>A poil les putes !</p>


feed_id: http://sametmax.com/?p=22144
title: Tout ce qui fait que Python 3 est meilleur que Python 2 21 Recently updated !
uri: Tout-ce-qui-fait-que-Python-3-est-meilleur-que-Python-2-21-Recently
url: http://sametmax.com/tout-ce-qui-fait-que-python-3-est-meilleur-que-python-2/
content:
<p>Avec de nombreuses distros Linux qui viennent avec Python 3 par défaut ainsi que Django et Pyramid qui annoncent bientôt ne plus supporter Python 2, il est temps de faire un point.</p>
<p>Python 3 est aujourd&#8217;hui majoritairement utilisé pour tout nouveau projet ou formation que j&#8217;ai pu rencontrer. Les plus importantes dépendances ont été <a href="https://python3wos.appspot.com/">portées</a> ou possèdent une alternative. <code>Six</code> et <code>Python-future</code> permettent d&#8217;écrire facilement un code compatible avec les deux versions dans le pire des cas.</p>
<p>Nous sommes donc bien arrivés à destination. Il reste quelques bases de code encore coincées, la vie est injuste, mais globalement on est enfin au bout de la migration. Mais ça en a mis du temps !</p>
<p>Il y a de nombreuses raisons qui ont conduit à la lenteur de la migration de la communauté :</p>
<ul>
<li>Python 2 est un très bon langage. On ne répare pas ce qui marche.</li>
<li>Il y a beaucoup de code legacy en Python 2 et ça coûte cher de migrer.</li>
<li>La PSF a été trop gentille avec la communauté et l&#8217;a chouchoutée. En JS et Ruby ils ont dit &#8220;migrez ou allez vous faire foutre&#8221; et tout le monde a migré très vite.</li>
</ul>
<p>Mais je pense que la raison principale c&#8217;est le manque de motivation pour le faire. Il n&#8217;y a pas un gros sticker jaune fluo d&#8217;un truc genre &#8220;gagnez 30% de perfs en plus&#8221; que les devs adorent même si ça n&#8217;influence pas tant leur vie que ça. Mais les codeurs ne sont pas rationnels contrairement à ce qu&#8217;ils disent. Ils aiment les one-liners, c&#8217;est pour dire.</p>
<p>Pourtant, il y a des tas de choses excellentes en Python 3. Simplement:</p>
<ul>
<li>Elles ne sont pas sexy.</li>
<li>Elles ne se voient pas instantanément.</li>
<li>Personne n&#8217;en parle.</li>
</ul>
<p>Après 2 ans de Python 3 quasi-fulltime, je peux vous le dire, je ne veux plus coder en Python 2. Et on va voir pourquoi.</p>
<h2>Unicode, mon bel unicode</h2>
<p>On a crié que c&#8217;était la raison principale. A mon avis c&#8217;est une erreur. Peu de gens peuvent vraiment voir ce que ça implique.</p>
<p>Mais en tant que formateur, voilà ce que je n&#8217;ai plus a expliquer:</p>
<ul>
<li>Pourquoi un accent dans un commentaire fait planter le programme. Et <code># coding: </code></li>
<li>Pourquoi il faut faire <code>from codecs import open</code> et non pas juste <code>open</code>.</li>
<li>Pourquoi<code>request.get().read() + 'é'</code> fait planter le programme. Et <code>encode()</code> et <code>decode()</code>.</li>
<li>Pourquoi <code>os.listdir()[0] + 'é'</code> fait afficher des trucs chelous.</li>
<li>Pourquoi <code>print(sql_row[0])</code> fait planter le programme ou affiche des trucs chelous. Ou les deux.</li>
</ul>
<p>Et je peux supprimer de chacun de mes fichiers:</p>
<ul>
<li>Tous les <code>u</code> ou les <code>from __future__/codecs</code></li>
<li>Les en-tête d&#8217;encoding.</li>
<li>La moitié des <code>encode</code>/<code>decode</code>.</li>
</ul>
<p>Et toutes les APIS ont un paramètre <code>encoding</code>, qui a pour valeur par défaut &#8216;UTF8&#8242;. </p>
<h2>Debuggage for the win</h2>
<p>Des centaines d&#8217;ajustements ont été faits pour faciliter la gestion des erreurs et le debuggage. Meilleures exceptions, plus de vérifications, meilleurs messages d&#8217;erreur, etc.</p>
<p>Quelques exemples&#8230;</p>
<p>En Python 2:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span> <span style="color: #66cc66;">&lt;</span> <span style="color: #483d8b;">&quot;abc&quot;</span>
<span style="color: #008000;">True</span></pre></td></tr></table></div>

<p>En Python 3 <code>TypeError: unorderable types: list() < str()</code> of course.</p>
<p>En Python 2, <code>IOError</code> pour tout:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/etc/postgresql/9.5/main/pg_hba.conf'</span><span style="color: black;">&#41;</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&lt;stdin&gt;&quot;</span><span style="color: #66cc66;">,</span> line <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</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;">IOError</span>: <span style="color: black;">&#91;</span>Errno <span style="color: #ff4500;">13</span><span style="color: black;">&#93;</span> Permission denied: <span style="color: #483d8b;">'/etc/postgresql/9.5/main/pg_hba.conf'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/etc/postgresql/9.5/main/'</span><span style="color: black;">&#41;</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&lt;stdin&gt;&quot;</span><span style="color: #66cc66;">,</span> line <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</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;">IOError</span>: <span style="color: black;">&#91;</span>Errno <span style="color: #ff4500;">21</span><span style="color: black;">&#93;</span> Is a directory: <span style="color: #483d8b;">'/etc/postgresql/9.5/main/'</span></pre></td></tr></table></div>

<p>En Python 3, c'est bien plus facile à gérer dans un <code>try</code>/<code>except</code> ou à debugger:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/etc/postgresql/9.5/main/pg_hba.conf'</span><span style="color: black;">&#41;</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&lt;stdin&gt;&quot;</span><span style="color: #66cc66;">,</span> line <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #66cc66;">&lt;</span>module<span style="color: #66cc66;">&gt;</span>
PermissionError: <span style="color: black;">&#91;</span>Errno <span style="color: #ff4500;">13</span><span style="color: black;">&#93;</span> Permission denied: <span style="color: #483d8b;">'/etc/postgresql/9.5/main/pg_hba.conf'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/etc/postgresql/9.5/main/'</span><span style="color: black;">&#41;</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&lt;stdin&gt;&quot;</span><span style="color: #66cc66;">,</span> line <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #66cc66;">&lt;</span>module<span style="color: #66cc66;">&gt;</span>
IsADirectoryError: <span style="color: black;">&#91;</span>Errno <span style="color: #ff4500;">21</span><span style="color: black;">&#93;</span> Is a directory: <span style="color: #483d8b;">'/etc/postgresql/9.5/main/'</span></pre></td></tr></table></div>

<p>Les cascades d'exceptions en Python 3 sont très claires:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">try</span>:
...     <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/'</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># Erreur, c'est un dossier:</span>
... <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">IOError</span>:
...     <span style="color: #ff4500;">1</span> / <span style="color: #ff4500;">0</span> <span style="color: #808080; font-style: italic;"># oui c'est stupide, c'est pour l'exemple</span>
... 
<span style="color: black;">Traceback</span> <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><span style="color: #66cc66;">,</span> line <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #66cc66;">&lt;</span>module<span style="color: #66cc66;">&gt;</span>
IsADirectoryError: <span style="color: black;">&#91;</span>Errno <span style="color: #ff4500;">21</span><span style="color: black;">&#93;</span> Is a directory: <span style="color: #483d8b;">'/'</span> 
&nbsp;
During handling of the above exception<span style="color: #66cc66;">,</span> another exception occurred:
&nbsp;
  File <span style="color: #483d8b;">&quot;&lt;stdin&gt;&quot;</span><span style="color: #66cc66;">,</span> line <span style="color: #ff4500;">4</span><span style="color: #66cc66;">,</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;">ZeroDivisionError</span>: division by zero</pre></td></tr></table></div>

<p>La même chose en Python 2:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&lt;stdin&gt;&quot;</span><span style="color: #66cc66;">,</span> line <span style="color: #ff4500;">4</span><span style="color: #66cc66;">,</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;">ZeroDivisionError</span>: integer division <span style="color: #ff7700;font-weight:bold;">or</span> modulo by zero</pre></td></tr></table></div>

<p>Bonne chance pour trouver l'erreur originale.</p>
<p>Plein de duplications ont été retirées.</p>
<p>En Python 2, un dev doit savoir la différence entre:</p>
<ul>
<li><code>range()</code> et <code>xrange()</code></li>
<li><code>map/filter</code> et <code>itertools.imap/itertools.ifilter</code></li>
<li><code>dict.items/keys/values</code>, <code>dict.iteritems/keys/values</code> et <code>dict.viewitems/keys/values</code></li>
<li><code>open</code> et <code>codecs.open</code></li>
<li>Et <code>md5</code> vs <code>hashlib.md5</code></li>
<li><code>getopt</code>, <code>optparse</code>, <code>argparse</code></li>
<li>Cette manipulation de fichier se fait avec <code>sys</code>, <code>os</code> ou <code>shutil</code> ?</li>
<li>On hérite de <code>UserDict</code> ou <code>dict</code> ? <code>UserList</code> ou <code>list</code> ?</li>
<li>...</li>
</ul>
<p>Sous peine de bugs ou de tuer ses perfs.</p>
<p>Certains bugs sont inévitables, et les modules <code>csv</code> et <code>re</code> sont par exemple pour toujours buggés en Python 2. </p>
<h2>Good bye boiler plate</h2>
<p>Faire un programme correct en Python 2 requière plus de code. Prenons l'exemple d'une suite de fichier qui contient des valeurs à récupérer sur chaque ligne, ou des commentaires (avec potentiellement des accents). Les fichiers font quelques centaines de méga, et je veux itérer sur leurs contenus.</p>
<p>Python 2:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># coding: utf8</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">__future__</span> <span style="color: #ff7700;font-weight:bold;">import</span> unicode_literals<span style="color: #66cc66;">,</span> division
&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> <span style="color: #dc143c;">math</span> <span style="color: #ff7700;font-weight:bold;">import</span> log
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">codecs</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #008000;">open</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">glob</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">glob</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">itertools</span> <span style="color: #ff7700;font-weight:bold;">import</span> imap  <span style="color: #808080; font-style: italic;"># pour ne pas charger 300 Mo en mémoire d'un coup</span>
&nbsp;
FS_ENCODING <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">sys</span>.<span style="color: black;">getfilesystemencoding</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
SIZE_SUFFIXES <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">'bytes'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'KiB'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'MiB'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'GiB'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'TiB'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'PiB'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'EiB'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'ZiB'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'YiB'</span><span style="color: black;">&#93;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> file_size<span style="color: black;">&#40;</span>size<span style="color: black;">&#41;</span>:
    order <span style="color: #66cc66;">=</span> <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>log<span style="color: black;">&#40;</span>size<span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span> / <span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> size <span style="color: #ff7700;font-weight:bold;">else</span> <span style="color: #ff4500;">0</span>  <span style="color: #808080; font-style: italic;"># potential bug with log2</span>
    size <span style="color: #66cc66;">=</span> size / <span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span> <span style="color: #66cc66;">&lt;&lt;</span> <span style="color: black;">&#40;</span>order * <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;">return</span> <span style="color: #483d8b;">'{:.4g} {}'</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>size<span style="color: #66cc66;">,</span> suffixes<span style="color: black;">&#91;</span>order<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> get_data<span style="color: black;">&#40;</span><span style="color: #008000;">dir</span><span style="color: #66cc66;">,</span> *patterns<span style="color: #66cc66;">,</span> **kwargs<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; Charge les données des fichiers  &quot;&quot;&quot;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># keyword only args</span>
    convert <span style="color: #66cc66;">=</span> kwargs.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'convert'</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">int</span><span style="color: black;">&#41;</span>
    encoding <span style="color: #66cc66;">=</span> kwargs.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'encoding'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'utf8'</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">for</span> p <span style="color: #ff7700;font-weight:bold;">in</span> patterns:
        <span style="color: #ff7700;font-weight:bold;">for</span> path <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">glob</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #008000;">dir</span><span style="color: #66cc66;">,</span> p<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">isfile</span><span style="color: black;">&#40;</span>path<span style="color: black;">&#41;</span>:
                upath <span style="color: #66cc66;">=</span> path.<span style="color: black;">decode</span><span style="color: black;">&#40;</span>FS_ENCODING<span style="color: #66cc66;">,</span> error<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;replace&quot;</span><span style="color: black;">&#41;</span>
                <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Trouvé: '</span><span style="color: #66cc66;">,</span> upath<span style="color: #66cc66;">,</span> file_size<span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: #dc143c;">stat</span><span style="color: black;">&#40;</span>path<span style="color: black;">&#41;</span>.<span style="color: black;">st_size</span><span style="color: black;">&#41;</span>
&nbsp;
                <span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>path<span style="color: #66cc66;">,</span> encoding<span style="color: #66cc66;">=</span>encoding<span style="color: #66cc66;">,</span> error<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;ignore&quot;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> f:
                    <span style="color: #808080; font-style: italic;"># retirer les commentaires</span>
                    lines <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span>l <span style="color: #ff7700;font-weight:bold;">for</span> l <span style="color: #ff7700;font-weight:bold;">in</span> f <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #483d8b;">&quot;#&quot;</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> l<span style="color: black;">&#41;</span>
                    <span style="color: #ff7700;font-weight:bold;">for</span> value <span style="color: #ff7700;font-weight:bold;">in</span> imap<span style="color: black;">&#40;</span>convert<span style="color: #66cc66;">,</span> f<span style="color: black;">&#41;</span>:
                        <span style="color: #ff7700;font-weight:bold;">yield</span> value</pre></td></tr></table></div>

<p>C'est déjà pas mal. On gère les caractères non ASCII dans les fichiers et le nom des fichiers, on affiche tout proprement sur le terminal, on itère en lazy pour ne pas saturer la RAM... Un code assez chouette, et pour obtenir ce résultat dans d'autres langages vous auriez plus dégueu (ou plus buggé).</p>
<p>Python 3:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># wow, so much space, much less import</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">math</span> <span style="color: #ff7700;font-weight:bold;">import</span> log2 <span style="color: #808080; font-style: italic;"># non buggy log2</span>
<span style="color: #ff7700;font-weight:bold;">from</span> pathlib <span style="color: #ff7700;font-weight:bold;">import</span> Path <span style="color: #808080; font-style: italic;"># plus de os.path bullshit</span>
&nbsp;
SIZE_SUFFIXES <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">'bytes'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'KiB'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'MiB'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'GiB'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'TiB'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'PiB'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'EiB'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'ZiB'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'YiB'</span><span style="color: black;">&#93;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> file_size<span style="color: black;">&#40;</span>size<span style="color: black;">&#41;</span>:
    order <span style="color: #66cc66;">=</span> <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>log2<span style="color: black;">&#40;</span>size<span style="color: black;">&#41;</span> / <span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> size <span style="color: #ff7700;font-weight:bold;">else</span> <span style="color: #ff4500;">0</span>   
    size <span style="color: #66cc66;">=</span> size / <span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span> <span style="color: #66cc66;">&lt;&lt;</span> <span style="color: black;">&#40;</span>order * <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;">return</span> f<span style="color: #483d8b;">'{size:.4g} {suffixes[order]}'</span> <span style="color: #808080; font-style: italic;"># fstring</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> get_data<span style="color: black;">&#40;</span><span style="color: #008000;">dir</span><span style="color: #66cc66;">,</span> *patterns<span style="color: #66cc66;">,</span> convert<span style="color: #66cc66;">=</span><span style="color: #008000;">int</span><span style="color: #66cc66;">,</span> encoding<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;utf8&quot;</span><span style="color: black;">&#41;</span>: <span style="color: #808080; font-style: italic;"># keyword only</span>
    <span style="color: #483d8b;">&quot;&quot;&quot; Charge les données des fichiers  &quot;&quot;&quot;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">for</span> p <span style="color: #ff7700;font-weight:bold;">in</span> patterns:
        <span style="color: #ff7700;font-weight:bold;">for</span> path <span style="color: #ff7700;font-weight:bold;">in</span> Path<span style="color: black;">&#40;</span><span style="color: #008000;">dir</span><span style="color: black;">&#41;</span>.<span style="color: #dc143c;">glob</span><span style="color: black;">&#40;</span>p<span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">if</span> path.<span style="color: black;">is_file</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;">'Trouvé: '</span><span style="color: #66cc66;">,</span> path<span style="color: #66cc66;">,</span> file_size<span style="color: black;">&#40;</span>path.<span style="color: #dc143c;">stat</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">st_size</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
                <span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>path<span style="color: #66cc66;">,</span> encoding<span style="color: #66cc66;">=</span>encoding<span style="color: #66cc66;">,</span> error<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;ignore&quot;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> f:
                    <span style="color: #808080; font-style: italic;"># retirer les commentaires</span>
                    lines <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span>l <span style="color: #ff7700;font-weight:bold;">for</span> l <span style="color: #ff7700;font-weight:bold;">in</span> f <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #483d8b;">&quot;#&quot;</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> l<span style="color: black;">&#41;</span>
                    <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #008000;">map</span><span style="color: black;">&#40;</span>convert<span style="color: #66cc66;">,</span> lines<span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># déroulage automatique</span></pre></td></tr></table></div>

<p>Oui, c'est tout. </p>
<p>Et ce n'est pas juste une question de taille du code. Notez tout ce que vous n'avez pas à savoir à l'avance pour que ça marche. Le code est plus lisible. La signature de la fonction mieux documentée. Et il marchera mieux sur une console Windows car le support a été amélioré en Python 3.</p>
<p>Et encore j'ai été sympa, je n'ai pas fait la gestion des erreurs de lecture des fichiers, sinon on en avait encore pour 3 ans.</p>
<p>Il y a des tas d'autres trucs.</p>
<p>L'unpacking généralisé:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> a<span style="color: #66cc66;">,</span> *rest<span style="color: #66cc66;">,</span> c <span style="color: #66cc66;">=</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: #808080; font-style: italic;"># récupérer la première et dernière valeur</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> foo<span style="color: black;">&#40;</span>*bar1<span style="color: #66cc66;">,</span> *bar2<span style="color: black;">&#41;</span>  <span style="color: #808080; font-style: italic;"># tout passer en arg</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: black;">&#123;</span>**dico1<span style="color: #66cc66;">,</span> **dico2<span style="color: black;">&#125;</span> <span style="color: #808080; font-style: italic;"># fusionner deux dico :)</span></pre></td></tr></table></div>

<p>Ou la POO simplifiée:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> FooFooFoo<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;">class</span> BarBarBar<span style="color: black;">&#40;</span>FooFooFoo<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> wololo<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">super</span><span style="color: black;">&#40;</span>BarBarBar<span style="color: #66cc66;">,</span> <span style="color: #008000;">self</span><span style="color: black;">&#41;</span>.<span style="color: black;">wololo</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Devient:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> FooFooFoo:
    ...
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> BarBarBar<span style="color: black;">&#40;</span>FooFooFoo<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> wololo<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">super</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">wololo</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Python 3 est tout simplement plus simple, et plus expressif.</p>
<h2>Bonus</h2>
<p>Evidement il y a plein de trucs qui n'intéresseront qu'une certaine catégorie de devs:</p>
<ul>
<li><code>ipaddress.ip_address</code> pour parser les adresses IP.</li>
<li><code>asyncio</code> pour faire de l'IO non blocante sans threads.</li>
<li><code>enum</code> des enum de toutes sortes.</li>
<li><code>functools.lru_cache</code> pour cacher le résultat de ses fonctions.</li>
<li>type hints pour vérifier la validité de son code.</li>
<li>l'opérateur <code>@</code> pour multiplier des matrices avec <code>numpy</code>.</li>
<li><code>concurrent.futures</code> pour faire des pools non blocantes propres.</li>
<li><code>statistics</code> stats performantes et correctes.</li>
<li><code>tracemalloc</code> trouver les fuites de mémoire.</li>
<li><code>faulthandler</code> gérer les crash du code C proprement.</li>
</ul>
<p>Si vous n'êtes pas concernés, ça n'est pas motivant. Mais si ça vous touche personnellement, c'est super cool.</p>
<p>Au passage, depuis la 3.6, Python 3 est enfin plus rapide que Python 2 pour la plupart des opérations :)</p>
<h2>Pour finir...</h2>
<p>Toutes ces choses là s'accumulent. Un code plus court, plus lisible, plus facile à débugger, plus juste, plus performant. Par un tas de petits détails.</p>
<p>Alors oui, la migration ne va pas restaurer instantanément votre érection et vous faire perdre du poids. Mais sur le long terme, tout ça compte énormément.</p>


feed_id: http://sametmax.com/?p=22198
title: La maison des horreurs de l’encoding 9 Recently updated !
uri: La-maison-des-horreurs-de-l-encoding-9-Recently-updated
url: http://sametmax.com/la-maison-des-horreurs-de-lencoding/
content:
<p>Ah, l&#8217;encoding, le truc que tout le monde veut mettre sous le tapis. Il faut dire que c&#8217;est dur à gérer. En fait tellement dur que:</p>
<ul>
<li>Les logiciels et pages web continuent parfois d&#8217;afficher des ?? en 2017. Tous les langages laxistes laissent des données corrompues plutôt que d&#8217;avertir le codeur qui du coup n&#8217;apprend jamais à faire les choses correctement.</li>
<li>PHP a littéralement <a href="http://www.slideshare.net/andreizm/the-good-the-bad-and-the-ugly-what-happened-to-unicode-and-php-6">abandonné la version 6</a> car impossible de trouver une solution propre avec leur design.</li>
<li>Perl a mis 10 ans à sortir la version 6 qui <a href="https://perl6advent.wordpress.com/2015/12/07/day-7-unicode-perl-6-and-you/">gère proprement l&#8217;unicode</a>.</li>
<li>NodeJS <a href="http://stackoverflow.com/questions/14551608/list-of-encodings-that-node-js-supports">ignore juste la question</a>, fout tout en utf8 et vous dit de télécharger une lib externe si vous voulez gérer autre chose.</li>
</ul>
<p>Tout ce bordel amène les devs à essayer d&#8217;ignorer le problème le plus longtemps possible. Ca marche assez bien pour les anglophones car leur environnement est assez homogène, orienté ASCII, et certains peuvent faire une très belle carrière en restant joyeusement ignorant.</p>
<p>Ca marche beaucoup moins bien pour les européens, et pas du tout pour le monde arabe et asiatique. Néanmoins, pas besoin de chercher bien loin pour trouver des échecs critiques.</p>
<p>Naviguez tranquillement sur <a href="http://www.airedefiesta.com/76-pinatas-y-chuches.html">un site espagnol</a> a priori joli, moderne, utilisant des tildes et tout ce qu&#8217;il faut. Maintenant regardez la requête HTTP, vous noterez que le serveur n&#8217;indique pas le charset du contenu. Fort heureusement dans le HTML vous trouvez:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="html" style="font-family:monospace;">&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;ISO-8859-1&quot;&gt;</pre></td></tr></table></div>

<p>Nickel, récupérons le texte du bouton &#8220;Ver más ideas&#8221;:</p>

<div class="wp_syntax"><table><tr><td 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> requests
<span style="color: #66cc66;">&gt;&gt;&gt;</span> res <span style="color: #66cc66;">=</span> requests.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://www.airedefiesta.com/76-pinatas-y-chuches.html'</span><span style="color: black;">&#41;</span> 
<span style="color: #66cc66;">&gt;&gt;&gt;</span> data <span style="color: #66cc66;">=</span> res.<span style="color: black;">content</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span>b<span style="color: #483d8b;">'http://www.airedefiesta.com/ideas.html?c=76&quot;&gt;'</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span>b<span style="color: #483d8b;">'&lt;/a&gt;'</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> data
b<span style="color: #483d8b;">'Ver m<span style="color: #000099; font-weight: bold;">\x</span>c3<span style="color: #000099; font-weight: bold;">\x</span>a1s ideas'</span></pre></td></tr></table></div>

<p>Une suite de bits comme maman les aime. On décode:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> data.<span style="color: black;">decode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'ISO-8859-1'</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'Ver mÃ¡s ideas'</span></pre></td></tr></table></div>

<div id="attachment_22201" style="width: 510px" class="wp-caption aligncenter"><a href="media/4cb7c7db.Dl28IBk.gif" data-original-source="http://sametmax.com/wp-content/uploads/2017/01/Dl28IBk.gif" class="grouped_elements" rel="tc-fancybox-group22198"><img src="media/4cb7c7db.Dl28IBk.gif" data-original-source="http://sametmax.com/wp-content/uploads/2017/01/Dl28IBk.gif" alt="Chenille dans labyrinthe" width="500" height="216" class="size-full wp-image-22201" /></a><p class="wp-caption-text">Et puis on ne voudrait pas que vous arriviez au château trop vite</p></div>
<p>Enfer et sodomie ! Le charset déclaré n&#8217;est pas celui utilisé. Tentons un truc au hasard:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> data.<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: #483d8b;">'Ver más ideas'</span></pre></td></tr></table></div>

<p>Bref, en 2017, on se touche la nouille pour savoir qui a son architecture multi-services load balancée web scale à base de NoSQL, de containers orchestrés et de serveurs asynchrones. Mais pour afficher du texte y a plus personne hein&#8230;</p>
<p>Vous croyez que ce ne sont que les amateurs qui font ces erreurs. Naaaaaaaaa. Par exemple le standard pour les fichiers zip a une vision <a href="https://marcosc.com/2008/12/zip-files-and-encoding-i-hate-you/">très&#8230; hum&#8230; personnelle</a> du traitement de l&#8217;encoding des noms de fichier.</p>
<p>L&#8217;encoding, c&#8217;est la raison majeur de l’incompatibilité de Python 2 et 3, mais aussi un signe de la bonne santé de la techno puisque c&#8217;est un des rares vieux langages (je rappelle que Python est plus vieux que Java) à gérer la chose correctement. A savoir:</p>
<ul>
<li>Avoir un type haut niveau qui fait abstraction de l&#8217;encoding pour le texte.</li>
<li>Forcer le développeur à spécifier l&#8217;encoding pour les entrées et les sorties.</li>
<li>Eviter toute conversion automatique.</li>
<li>Avoir de l&#8217;utf8 par défaut là où ça a du sens.</li>
<li>Lever des erreurs plutôt que de corrompre les données.</li>
<li>Avoir une API unifiée autour de la notion de &#8220;codec&#8221; qui marche pour le FS, le réseau, les chaînes internes, etc.</li>
</ul>
<p>Python n&#8217;est pas parfait pour autant. Par exemple il garantit un accès 0(1) indexing sur les strings, ce qui à mon sens est inutile. Swift a un meilleur design pour ce genre de choses. Mais globalement c&#8217;est quand même super bon.</p>
<p>Si ne savez toujours pas comment ça marche, on a évidement <a href="http://sametmax.com/lencoding-en-python-une-bonne-fois-pour-toute/">un tuto pour ça</a>.</p>
<p>Alors pourquoi l&#8217;encoding c&#8217;est un truc compliqué ? </p>
<p>Et bien parce que comme pour le temps ou l&#8217;<a href="http://sametmax.com/linternationalisation-cest-long-et-dur-et-ca-racle-le-fond/">i18n</a>, ça touche à la culture, au langage, à la politique, et on a accumulé les problèmes au fil des années. </p>
<div id="attachment_22203" style="width: 466px" class="wp-caption aligncenter"><a href="media/54bd02b5.SBygvL4.png" data-original-source="http://sametmax.com/wp-content/uploads/2017/01/SBygvL4.png" class="grouped_elements" rel="tc-fancybox-group22198"><img src="media/54bd02b5.SBygvL4.png" data-original-source="http://sametmax.com/wp-content/uploads/2017/01/SBygvL4.png" alt="A solid dick from an iron man" width="456" height="390" class="size-full wp-image-22203" /></a><p class="wp-caption-text">Mais je vous jure ça avait du sens y a 40 ans !</p></div>
<p>Par exemple, parlons un peu d&#8217;UTF.</p>
<p>Vous savez, on vous dit toujours d&#8217;utiliser utf8 partout pour être tranquille&#8230;</p>
<p>Mais déjà se pose la question : avec ou sans BOM ?</p>
<p>Le BOM, c&#8217;est une suite d&#8217;octets qui indique en début de fichier qu&#8217;il contient de l&#8217;UTF. Si ça à l&#8217;air pratique, c&#8217;est parce que ça l&#8217;est. Malheureusement, celui-ci n&#8217;est pas obligatoire, certaines applications le requièrent, d&#8217;autres l&#8217;ignorent, et d&#8217;autres plantent face au BOM. D&#8217;ailleurs, <a href="media/c8366670.ch02.pdf" data-original-source="http://www.unicode.org/versions/Unicode5.0.0/ch02.pdf">le standard unicode</a> lui-même ne le recommande pas:</p>
<blockquote><p>Use of a BOM is neither required nor recommended for UTF-8</p></blockquote>
<p>Ca aide vachement à faire son choix.</p>
<p>Perso je ne le mets jamais, sauf si je dois mélanger des fichiers de différents encodings et les différencier plus tard. </p>
<p>Mais Powershell et Excel par exemple, fonctionnent parfois mieux si vous leur passez des données avec le BOM :)</p>
<p>Si vous avez un peu creusé la question, vous savez qu&#8217;il existe aussi UTF16 (par défaut dans l&#8217;API de Windows 7 et 8 et les chaînes de .NET), UTF32 et UTF64. Ils ont des variantes Big et Little Endians, qui ne supportent pas le BOM, et une version neutre qui le supporte, pour faciliter la chose. </p>
<p>Bien, bien, bien.</p>
<p>Mais saviez-vous qu&#8217;il existe aussi UTF-1, 5 et 6 ? Si, si. Et UTF9 et UTF18 aussi, mais sauf que eux ce sont des poissons d&#8217;avril, parce que les gens qui écrivent les RFC sont des mecs trop funs en soirées.</p>
<p>Que sont devenus ces derniers ? Et bien ils ont été proposés comme encoding pour l&#8217;internationalisation des noms de domaine. UTF5 est un encoding en base 32, comme son nom l&#8217;indique. Si, 2 puissance 5 ça fait 32. Funs en soirée, tout ça.</p>
<p>Néanmoins quelqu&#8217;un est arrivé avec une plus grosse bit(e), <a href="https://en.wikipedia.org/wiki/Punycode">punycode</a>, en base 36, et a gagné la partie. J&#8217;imagine que les gens se sont dit qu&#8217;utiliser base64 était déjà trop fait par tout le monde est qu&#8217;on allait pas se priver de cette occasion fabuleuse de rajouter un standard.</p>
<p>Standard qui ne vous dispense pas, dans les URLs, d&#8217;encoder DIFFÉREMMENT ce qui n&#8217;est pas le nom de domaine avec les bons escaping. Et son lot de <a href="http://treerex.blogspot.fr/2013/08/a-url-encoding-horror-story.html">trucs fantastiques</a>. Encoding qui est différent pour les valeurs de formulaire.</p>
<p>Python supporte par ailleurs très bien tout ça:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">'Père noël'</span>.<span style="color: black;">encode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'punycode'</span><span style="color: black;">&#41;</span>
b<span style="color: #483d8b;">'Pre nol-2xa6a'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">urllib</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">urllib</span>.<span style="color: black;">parse</span>.<span style="color: black;">quote</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Père Noël'</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'P%C3%A8re%20No%C3%ABl'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">urllib</span>.<span style="color: black;">parse</span>.<span style="color: black;">quote_plus</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Père Noël'</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'P%C3%A8re+No%C3%ABl'</span></pre></td></tr></table></div>

<p>En plus, si Punycode est l&#8217;encoding par défaut utilisé dans les noms de domaine, c&#8217;est donc aussi celui des adresses email. Ce qui vous permettra de profiter des interprétations diverses de la spec, comme par exemple le retour de la valeur d&#8217;un HTML input marqué &#8220;email&#8221;, qui <a href="https://www.grepular.com/The_Sad_State_of_HTML_Email_Input_Fields_and_IDNs">diffère selon les navigateurs</a>.</p>
<div id="attachment_22204" style="width: 510px" class="wp-caption aligncenter"><a href="media/c5c6089c.f9aqtmt.gif" data-original-source="http://sametmax.com/wp-content/uploads/2017/01/f9aqtmt.gif" class="grouped_elements" rel="tc-fancybox-group22198"><img src="media/c5c6089c.f9aqtmt.gif" data-original-source="http://sametmax.com/wp-content/uploads/2017/01/f9aqtmt.gif" alt="Président faisant un fuck dans idiocracy" width="500" height="281" class="size-full wp-image-22204" /></a><p class="wp-caption-text">If you don&#8217;t encode in Tarrlytons&#8230;fuck you!</p></div>
<p>Pourquoi je vous parle des adresses emails tout à coup ? Ah ah ah ah ah ah ah !</p>
<p>Mes pauvres amis.</p>
<p>Je ne vous avais jamais parlé d&#8217;utf7 ?</p>
<p>Non, je ne me fous pas de votre gueule. Je suis très sérieux.</p>
<p>Figurez-vous que le format email MIME <a href="https://en.wikipedia.org/wiki/UTF-7">accepte l&#8217;utilisation d&#8217;utf7</a> en lieu et place de base64.</p>
<p>Mais ce n&#8217;est pas ça le plus drôle.</p>
<p>Y a mieux, je vous jure.</p>
<p>UTF7 est en effet l&#8217;encoding par défaut pour IMAP, particulièrement les noms des boîtes aux lettres. Vous savez, &#8220;INBOX&#8221;, &#8220;Spams&#8221; et &#8220;Messages envoy&#038;AOk-s&#8221; ;)</p>
<p>Or comme l&#8217;enculerie ne serait pas aussi délicieuse sans un peu de sable&#8230;</p>
<p>La version utilisée maintenant (et pour toujourssssssss) par IMAP est une version d&#8217;UTF7 <a href="https://bugs.python.org/issue5305">non standard et modifiée</a>.</p>
<p>Pourquoi ? Ben parce qu&#8217;allez-vous faire foutre.</p>
<div id="attachment_22202" style="width: 437px" class="wp-caption aligncenter"><a href="media/275f14ab.tvNESh1.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/01/tvNESh1.jpg" class="grouped_elements" rel="tc-fancybox-group22198"><img src="media/275f14ab.tvNESh1.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2017/01/tvNESh1.jpg" alt="The choosen one, crying" width="427" height="231" class="size-full wp-image-22202" /></a><p class="wp-caption-text">The choosen one would soon realize that some things survived outside of the vault. Like bad UI and terrible IT standards. And his &#8216;science&#8217; skills is at 42% and life sucks.</p></div>
<p>Au final je n&#8217;ai fait que parloter d&#8217;UTF, mais souvenez-vous que:</p>

<div class="wp_syntax"><table><tr><td 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;">encodings</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">encodings</span>.<span style="color: black;">aliases</span>.<span style="color: black;">aliases</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">322</span></pre></td></tr></table></div>

<p>Donc on n&#8217;a fait qu&#8217;effleurer la surface de l&#8217;anus boursouflé de la mouche. </p>
<p>J&#8217;espère que la nuit, à 3h du mat, lorsque votre prochaine mise en prod agonisera sur un <code>UnicodeDecodeError</code>, vous penserez à moi et pendant un instant, un sourire se dessinera sous vos larmes.</p>
<div id="attachment_22199" style="width: 310px" class="wp-caption aligncenter"><a href="media/6c661a48.heptapod-writing-in-arrival-300x158.png" data-original-source="http://sametmax.com/wp-content/uploads/2017/01/heptapod-writing-in-arrival-300x158.png" class="grouped_elements" rel="tc-fancybox-group22198"><img src="media/6c661a48.heptapod-writing-in-arrival-300x158.png" data-original-source="http://sametmax.com/wp-content/uploads/2017/01/heptapod-writing-in-arrival-300x158.png" alt="Ecriture extra-terrestre de the arrival" width="300" height="158" class="size-full wp-image-22199" /></a><p class="wp-caption-text">Militaire : Votre avis ? &#8211; Unicode Consortium : Tuez les tous.</p></div>


feed_id: http://sametmax.com/?p=22278
title: Le PEP8 et au delà, par la pratique 3 Recently updated !
uri: Le-PEP8-et-au-delà-par-la-pratique-3-Recently-updated
url: http://sametmax.com/le-pep8-et-au-dela-par-la-pratique/
content:
<p>Je lis régulièrement des commentaires de batailles d&#8217;opinions sur le <a href="https://www.python.org/dev/peps/pep-0008/">PEP8</a>. Pas mal sont en fait dues à un manque de compréhension de son application. Je vais donc vous montrer des codes et les transformer pour qu&#8217;ils soient plus propre.</p>
<p>Rappelez-vous toujours que des recommandations stylistiques sont essentiellement arbitraires. Elles servent à avoir une base commune, et il n&#8217;y en pas de meilleures.</p>
<p>On recommande les espaces au lieu des tabs. Les tabs sont sémantiquement plus adaptés et plus flexibles. Les espaces permettent d&#8217;avoir un seul type de caractères non imprimables dans son code et autorise un alignement fin d&#8217;une expression divisée en plusieurs lignes. Il n&#8217;y a pas de meilleur choix. Juste un choix tranché pour passer à autre chose de plus productif, comme coder.</p>
<p>On recommande par contre une limite de 80 caractères pour les lignes. Cela permet à l’œil, qui scanne par micro-sauts, de parser plus facilement le code. Mais aussi de faciliter le multi-fenêtrage. Néanmoins cette limite peut être brisée ponctuellement si le coût pour la lisibilité du code est trop important. Tout est une question d&#8217;équilibre.</p>
<p>Ready ? Oh yeah !</p>
<p><span class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='1170' height='689' src='http://www.youtube.com/embed/vW0b8hyFs3A?version=3&#038;rel=1&#038;fs=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' frameborder='0' allowfullscreen='true'></iframe></span></p>
<h2>L&#8217;espacement</h2>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span>  foo <span style="color: black;">&#40;</span>bar <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'test'</span><span style="color: black;">&#41;</span>:
   <span style="color: #ff7700;font-weight:bold;">if</span> bar<span style="color: #66cc66;">==</span><span style="color: #483d8b;">'test'</span> : <span style="color: #808080; font-style: italic;"># this is a test</span>
      bar<span style="color: #66cc66;">=</span><span style="color: black;">&#123;</span><span style="color: #ff4500;">1</span>:<span style="color: #ff4500;">2</span> <span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span> : <span style="color: #ff4500;">4</span>*<span style="color: #ff4500;">4</span><span style="color: black;">&#125;</span></pre></td></tr></table></div>

<p>Devient:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> foo<span style="color: black;">&#40;</span>bar<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'test'</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> bar <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">'test'</span>:  <span style="color: #808080; font-style: italic;"># this is a test</span>
        bar <span style="color: #66cc66;">=</span> <span style="color: black;">&#123;</span><span style="color: #ff4500;">1</span>: <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span>: <span style="color: #ff4500;">4</span>*<span style="color: #ff4500;">4</span><span style="color: black;">&#125;</span></pre></td></tr></table></div>

<p>On ne double pas les espaces. On a pas d&#8217;espace avant le &#8216;:&#8217; ou le &#8216;,&#8217; mais un après. Les opérateurs sont entourés d&#8217;espaces, sauf le &#8216;=&#8217; quand il est utilisé dans la signature de la fonction ou pour les opérations mathématiques (pour cette dernière, les deux sont tolérés).</p>
<p>Un commentaire inline est précédé de 2 espaces, une indentation est 4 espaces.</p>
<p>Les sauts de lignes aussi sont important:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> stuff
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> bar<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">pass</span></pre></td></tr></table></div>

<p>Devient:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> stuff
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> bar<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">pass</span></pre></td></tr></table></div>

<p>Les déclaratitons à la racine du fichiers sont séparés de 2 lignes. Pas plus, pas moins.</p>
<p>Mais à l&#8217;intérieur d&#8217;une classe, on sépare les méthodes d&#8217;une seule ligne.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Foo:
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> bar1<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> bar2<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">pass</span></pre></td></tr></table></div>

<p>Devient:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Foo:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> bar1<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> bar2<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">pass</span></pre></td></tr></table></div>

<p>Tout cela contribue à donner un rythme régulier et familier au code. Le cerveau humain adore les motifs, et une fois qu&#8217;il est ancré, il est facile à reconnaître et demande peu d&#8217;effort à traiter.</p>
<p>Les espaces servent aussi à grouper les choses qui sont liés, et a séparer les choses qui ne le sont pas.</p>
<p>Le style de saut de ligne à l&#8217;intérieur d&#8217;une fonction ou méthode est libre, mais évitez de sauter deux lignes d&#8217;un coup.</p>
<h2>Le nom des variables</h2>
<p>Si on s&#8217;en tient au PEP8, on fait du snake case:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> pasUnTrucCommeCa<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    niCommeCa <span style="color: #66cc66;">=</span> <span style="color: #008000;">True</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> mais_un_truc_comme_ca<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    ou_comme_ca <span style="color: #66cc66;">=</span> <span style="color: #008000;">True</span></pre></td></tr></table></div>

<p>Sauf pour les classes:</p>

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

<p>Et si on a un acronyme:</p>

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

<p>Malgré la possibilité d&#8217;utiliser des caractères non ASCII dans les noms en Python 3, ce n&#8217;est pas recommandé. Même si c&#8217;est tentant de faire:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> Σ <span style="color: #66cc66;">=</span> <span style="color: #ff7700;font-weight:bold;">lambda</span> *x: <span style="color: #008000;">sum</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> Σ<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">6</span></pre></td></tr></table></div>

<p>Néanmoins c&#8217;est l&#8217;arbre qui cache la foret. Il y a plus important : donner un contexte à son code.</p>
<p>Si on a:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">numbers <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #dc143c;">random</span>.<span style="color: black;">randint</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> _ <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;">100</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
group <span style="color: #66cc66;">=</span> <span style="color: #ff7700;font-weight:bold;">lambda</span> x: <span style="color: #008000;">sum</span><span style="color: black;">&#40;</span><span style="color: #008000;">map</span><span style="color: black;">&#40;</span><span style="color: #008000;">int</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
numbers <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #dc143c;">math</span>.<span style="color: black;">sqrt</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> numbers <span style="color: #ff7700;font-weight:bold;">if</span> group<span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span> <span style="color: #66cc66;">==</span> <span style="color: #ff4500;">9</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Le contexte du code donne peu d&#8217;informations et il faut lire toutes les instructions pour bien comprendre ce qui se passe. On peut faire mieux:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> digits_sum<span style="color: black;">&#40;</span>number<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; Take a number xyz and return x + y + z &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">sum</span><span style="color: black;">&#40;</span><span style="color: #008000;">map</span><span style="color: black;">&#40;</span><span style="color: #008000;">int</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>number<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
rand_sample <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #dc143c;">random</span>.<span style="color: black;">randint</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> _ <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;">100</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
sqrt_sample <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #dc143c;">math</span>.<span style="color: black;">sqrt</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> rand_sample <span style="color: #ff7700;font-weight:bold;">if</span> digits_sum<span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span> <span style="color: #66cc66;">==</span> <span style="color: #ff4500;">9</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Ici, on utilisant un meilleur nommage et en rajoutant du contexte, on rend son code bien plus facile à lire, même si il est plus long.</p>
<p>Le PEP8 n&#8217;est donc que le début. Un bon code est un code qui s&#8217;auto-documente.</p>
<p>Notez que certains variables sont longues, et d&#8217;autres n&#8217;ont qu&#8217;une seule lettre. C&#8217;est parce qu&#8217;il existe une sorte de convention informelle sur certains noms dans la communauté :</p>
<p><code>i</code> et <code>j</code> sont utilisés dans pour tout ce qui est incrément:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">for</span> i<span style="color: #66cc66;">,</span> stuff <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">enumerate</span><span style="color: black;">&#40;</span>foo<span style="color: black;">&#41;</span>:</pre></td></tr></table></div>

<p><code>x</code>, <code>y</code> et <code>z</code> sont utilisés pour contenir les éléments des boucles:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> foo:
    <span style="color: #ff7700;font-weight:bold;">for</span> y <span style="color: #ff7700;font-weight:bold;">in</span> bar:</pre></td></tr></table></div>

<p><code>_</code> est utilisé soit comme alias de <code>gettext</code>:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">gettext</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">gettext</span> <span style="color: #ff7700;font-weight:bold;">as</span> _</pre></td></tr></table></div>

<p>Soit comme variable inutilisée:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: black;">&#40;</span><span style="color: #dc143c;">random</span>.<span style="color: black;">randint</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> _ <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;">100</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p><code>_</code> a aussi un sens particulier dans le shell Python : elle contient la dernière chose affichée automatiquement.</p>
<p><code>f</code> pour un fichier dans un bloc <code>with</code>:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>stuff<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> f:</pre></td></tr></table></div>

<p>Si vous avez deux fichiers, nommez les:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>foo<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> foo_file<span style="color: #66cc66;">,</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>bar<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> bar_file:</pre></td></tr></table></div>

<p><code>*args</code> et <code>**kwargs</code> pour toute collection d&#8217;arguments hétérogène :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> foo<span style="color: black;">&#40;</span>a<span style="color: #66cc66;">,</span> b<span style="color: #66cc66;">,</span> **kwarg<span style="color: black;">&#41;</span>:</pre></td></tr></table></div>

<p>Mais attention, si les arguments sont homogènes, on les nomme:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> merge_files<span style="color: black;">&#40;</span>*paths<span style="color: black;">&#41;</span>:</pre></td></tr></table></div>

<p>Et bien entendu <code>self</code> pour l&#8217;instance en cours, ou <code>cls</code> pour la classe en cours:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Foo:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> bar<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        ...
&nbsp;
    <span style="color: #66cc66;">@</span><span style="color: #008000;">classmethod</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> barbar<span style="color: black;">&#40;</span>cls<span style="color: black;">&#41;</span>:
        ...</pre></td></tr></table></div>

<p>Dans tous les cas, évitez les noms qui sont utilisés par les built-ins :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">dir</span><span style="color: black;">&#40;</span>__builtins__<span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'ArithmeticError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'AssertionError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'AttributeError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'BaseException'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'BlockingIOError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'BrokenPipeError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'BufferError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'BytesWarning'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'ChildProcessError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'ConnectionAbortedError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'ConnectionError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'ConnectionRefusedError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'ConnectionResetError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'DeprecationWarning'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'EOFError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Ellipsis'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'EnvironmentError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Exception'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'False'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'FileExistsError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'FileNotFoundError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'FloatingPointError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'FutureWarning'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'GeneratorExit'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'IOError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'ImportError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'ImportWarning'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'IndentationError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'IndexError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'InterruptedError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'IsADirectoryError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'KeyError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'KeyboardInterrupt'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'LookupError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'MemoryError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'NameError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'None'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'NotADirectoryError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'NotImplemented'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'NotImplementedError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'OSError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'OverflowError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'PendingDeprecationWarning'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'PermissionError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'ProcessLookupError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'RecursionError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'ReferenceError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'ResourceWarning'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'RuntimeError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'RuntimeWarning'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'StopAsyncIteration'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'StopIteration'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'SyntaxError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'SyntaxWarning'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'SystemError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'SystemExit'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'TabError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'TimeoutError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'True'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'TypeError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'UnboundLocalError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'UnicodeDecodeError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'UnicodeEncodeError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'UnicodeError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'UnicodeTranslateError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'UnicodeWarning'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'UserWarning'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'ValueError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Warning'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'ZeroDivisionError'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'_'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__build_class__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__debug__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__doc__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__import__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__loader__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__name__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__package__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'__spec__'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'abs'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'all'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'any'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'ascii'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'bin'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'bool'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'bytearray'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'bytes'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'callable'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'chr'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'classmethod'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'compile'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'complex'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'copyright'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'credits'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'delattr'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'dict'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'dir'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'divmod'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'enumerate'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'eval'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'exec'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'exit'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'filter'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'float'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'format'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'frozenset'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'getattr'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'globals'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'hasattr'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'hash'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'help'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'hex'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'id'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'input'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'int'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'isinstance'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'issubclass'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'iter'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'len'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'license'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'list'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'locals'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'map'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'max'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'memoryview'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'min'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'next'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'object'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'oct'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'open'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'ord'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'pow'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'print'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'property'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'quit'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'range'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'repr'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'reversed'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'round'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'set'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'setattr'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'slice'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'sorted'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'staticmethod'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'str'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'sum'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'super'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'tuple'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'type'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'vars'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'zip'</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Les erreurs les plus communes : <code>list</code>, <code>dict</code>, <code>min</code>, <code>max</code>, <code>next</code>, <code>file</code>, <code>id</code>, <code>input</code> et <code>str</code>.</p>
<h2>La longueur des lignes</h2>
<p>C&#8217;est le point le plus sujet à polémique. Quelques astuces pour se faciliter la vie.</p>
<p><strong>L&#8217;identation est votre amie.</strong></p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">dico <span style="color: #66cc66;">=</span> <span style="color: black;">&#123;</span><span style="color: #ff4500;">0</span>: <span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1</span>: <span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span>: <span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span>: <span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">4</span>: <span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">5</span>: <span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">6</span>: <span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">7</span>: <span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">8</span>: <span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">9</span>: <span style="color: #008000;">None</span><span style="color: black;">&#125;</span>
tpl <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'jaune'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'bleu'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'rouge'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'noire'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'octarine'</span><span style="color: black;">&#41;</span>
res <span style="color: #66cc66;">=</span> arcpy.<span style="color: black;">FeatureClassToGeodatabase_conversion</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'file1.shp'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'file2.shp'</span> <span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'/path/to/file.gdb'</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Devient:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">dico <span style="color: black;">&#123;</span>
    <span style="color: #ff4500;">0</span>: <span style="color: #008000;">None</span><span style="color: #66cc66;">,</span>
    <span style="color: #ff4500;">1</span>: <span style="color: #008000;">None</span><span style="color: #66cc66;">,</span>
    <span style="color: #ff4500;">2</span>: <span style="color: #008000;">None</span><span style="color: #66cc66;">,</span>
    <span style="color: #ff4500;">3</span>: <span style="color: #008000;">None</span><span style="color: #66cc66;">,</span>
    <span style="color: #ff4500;">4</span>: <span style="color: #008000;">None</span><span style="color: #66cc66;">,</span>
    <span style="color: #ff4500;">5</span>: <span style="color: #008000;">None</span><span style="color: #66cc66;">,</span>
    <span style="color: #ff4500;">6</span>: <span style="color: #008000;">None</span><span style="color: #66cc66;">,</span>
    <span style="color: #ff4500;">7</span>: <span style="color: #008000;">None</span><span style="color: #66cc66;">,</span>
    <span style="color: #ff4500;">8</span>: <span style="color: #008000;">None</span><span style="color: #66cc66;">,</span>
    <span style="color: #ff4500;">9</span>: <span style="color: #008000;">None</span>
<span style="color: black;">&#125;</span>
&nbsp;
tpl <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span>
    <span style="color: #483d8b;">'jaune'</span><span style="color: #66cc66;">,</span>
    <span style="color: #483d8b;">'bleu'</span><span style="color: #66cc66;">,</span>
    <span style="color: #483d8b;">'rouge'</span><span style="color: #66cc66;">,</span>
    <span style="color: #483d8b;">'noire'</span><span style="color: #66cc66;">,</span>
    <span style="color: #483d8b;">'octarine'</span>
<span style="color: black;">&#41;</span>
&nbsp;
res <span style="color: #66cc66;">=</span> arcpy.<span style="color: black;">FeatureClassToGeodatabase_conversion</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>
        <span style="color: #483d8b;">'file1.shp'</span><span style="color: #66cc66;">,</span>
        <span style="color: #483d8b;">'file2.shp'</span>
    <span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span>
    <span style="color: #483d8b;">'/path/to/file.gdb'</span>
<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p><strong>Les parenthèses permettent des choses merveilleuses</strong></p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">query <span style="color: #66cc66;">=</span> db.<span style="color: black;">query</span><span style="color: black;">&#40;</span>MyTableName<span style="color: black;">&#41;</span>.<span style="color: black;">filter_by</span><span style="color: black;">&#40;</span>MyTableName.<span style="color: black;">the_column_name</span> <span style="color: #66cc66;">==</span> the_variable<span style="color: #66cc66;">,</span> MyTableName.<span style="color: black;">second_attribute</span> <span style="color: #66cc66;">&gt;</span> other_stuff<span style="color: black;">&#41;</span>.<span style="color: black;">first</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #dc143c;">string</span> <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.&quot;</span></pre></td></tr></table></div>


<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">query <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span>db.<span style="color: black;">query</span><span style="color: black;">&#40;</span>MyTableName<span style="color: black;">&#41;</span>
           .<span style="color: black;">filter_by</span><span style="color: black;">&#40;</span>MyTableName.<span style="color: black;">the_column_name</span> <span style="color: #66cc66;">==</span> the_variable<span style="color: #66cc66;">,</span>
                      MyTableName.<span style="color: black;">second_attribute</span> <span style="color: #66cc66;">&gt;</span> other_stuff<span style="color: black;">&#41;</span>
           .<span style="color: black;">first</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #dc143c;">string</span> <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Lorem ipsum dolor sit amet, consectetur adipisicing elit, &quot;</span>
          <span style="color: #483d8b;">&quot;sed do eiusmod tempor incididunt ut labore et dolore magna &quot;</span>
          <span style="color: #483d8b;">&quot;aliqua. Ut enim ad minim veniam, quis nostrud exercitation &quot;</span>
          <span style="color: #483d8b;">&quot;ullamco laboris nisi ut aliquip ex ea commodo consequat.&quot;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Les variables intermédiaires documentent le code:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">sqrt_sample <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #dc143c;">math</span>.<span style="color: black;">sqrt</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: black;">&#40;</span><span style="color: #dc143c;">random</span>.<span style="color: black;">randint</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> _ <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;">100</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">sum</span><span style="color: black;">&#40;</span><span style="color: #008000;">map</span><span style="color: black;">&#40;</span><span style="color: #008000;">int</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>number<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">==</span> <span style="color: #ff4500;">9</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Devient bien plus clair avec :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> digits_sum<span style="color: black;">&#40;</span>number<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; Take a number xyz and return x + y + z &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">sum</span><span style="color: black;">&#40;</span><span style="color: #008000;">map</span><span style="color: black;">&#40;</span><span style="color: #008000;">int</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>number<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
rand_sample <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #dc143c;">random</span>.<span style="color: black;">randint</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> _ <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;">100</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
sqrt_sample <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #dc143c;">math</span>.<span style="color: black;">sqrt</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> rand_sample <span style="color: #ff7700;font-weight:bold;">if</span> digits_sum<span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span> <span style="color: #66cc66;">==</span> <span style="color: #ff4500;">9</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p><code>return</code>, <code>break</code> et <code>continue</code> permettent de limiter l&#8217;indentation:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> bar:
        rand_sample <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #dc143c;">random</span>.<span style="color: black;">randint</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> _ <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;">100</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#40;</span><span style="color: #dc143c;">math</span>.<span style="color: black;">sqrt</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> rand_sample <span style="color: #ff7700;font-weight:bold;">if</span> digits_sum<span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span> <span style="color: #66cc66;">==</span> <span style="color: #ff4500;">9</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">None</span></pre></td></tr></table></div>

<p>Est plus élégant écrit ainsi:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> bar:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">None</span>
&nbsp;
    rand_sample <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #dc143c;">random</span>.<span style="color: black;">randint</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> _ <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;">100</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#40;</span><span style="color: #dc143c;">math</span>.<span style="color: black;">sqrt</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> rand_sample <span style="color: #ff7700;font-weight:bold;">if</span> digits_sum<span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span> <span style="color: #66cc66;">==</span> <span style="color: #ff4500;">9</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p><code>any</code>, <code>all</code> et <code>itertools.product</code> évident pas mal de blocs:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> foo:
    <span style="color: #ff7700;font-weight:bold;">if</span> barbarbarbarbarbarbar<span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>:
        meh<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> foo:
    <span style="color: #ff7700;font-weight:bold;">for</span> y <span style="color: #ff7700;font-weight:bold;">in</span> bar:
        meh<span style="color: black;">&#40;</span>y<span style="color: #66cc66;">,</span> y<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Devient:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">is_bar <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span>barbarbarbarbarbarbar<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> foo<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">any</span><span style="color: black;">&#40;</span>is_bar<span style="color: black;">&#41;</span>:
   meh<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">itertools</span>
<span style="color: #ff7700;font-weight:bold;">for</span> x<span style="color: #66cc66;">,</span> y <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">itertools</span>.<span style="color: black;">product</span><span style="color: black;">&#40;</span>foo<span style="color: #66cc66;">,</span> bar<span style="color: black;">&#41;</span>:
    meh<span style="color: black;">&#40;</span>y<span style="color: #66cc66;">,</span> y<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Le fait est que Python est bourré d&#8217;outils très expressifs. Oui, il arrivera parfois que vous deviez briser la limite des 80 charactères. Je le fais souvent pour mettre des URLs en commentaire par exemple. Mais ce n&#8217;est pas le cas typique si vous utilisez le langage tel qu&#8217;il a été prévu.</p>
<h2>Passer en mode pro</h2>
<p>Le PEP8, c&#8217;est un point de départ. Quand on a un script et qu&#8217;il grandit sous la forme d&#8217;une bibliothèque, il faut plus que le reformatter.</p>
<p>A partir d&#8217;un certain point, on voudra coiffer son code et lui mettre un costume. Reprenons :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> digits_sum<span style="color: black;">&#40;</span>number<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; Take a number xyz and return x + y + z &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">sum</span><span style="color: black;">&#40;</span><span style="color: #008000;">map</span><span style="color: black;">&#40;</span><span style="color: #008000;">int</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>number<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
rand_sample <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #dc143c;">random</span>.<span style="color: black;">randint</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> _ <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;">100</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
sqrt_sample <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #dc143c;">math</span>.<span style="color: black;">sqrt</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> rand_sample <span style="color: #ff7700;font-weight:bold;">if</span> digits_sum<span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span> <span style="color: #66cc66;">==</span> <span style="color: #ff4500;">9</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>On lui fait un relooking pour son entretient d&#8217;embauche :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> digits_sum<span style="color: black;">&#40;</span>number<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; Take a number xyz and return x + y + z
&nbsp;
        Arguments:
            number (int): the number with digits to sum.
                            It can't be a float.abs
&nbsp;
        Returns:
            An int, the sum of all digits of the number.
&nbsp;
        Example:
            &gt;&gt;&gt; digits_sum(123)
            6
    &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">sum</span><span style="color: black;">&#40;</span><span style="color: #008000;">map</span><span style="color: black;">&#40;</span><span style="color: #008000;">int</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>number<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> gen_squareroot_sample<span style="color: black;">&#40;</span>size<span style="color: #66cc66;">=</span><span style="color: #ff4500;">100</span><span style="color: #66cc66;">,</span> randstart<span style="color: #66cc66;">=</span><span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> randstop<span style="color: #66cc66;">=</span><span style="color: #ff4500;">100</span><span style="color: #66cc66;">,</span> filter_on<span style="color: #66cc66;">=</span><span style="color: #ff4500;">9</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; Generate a sample of random numbers square root
&nbsp;
        Take `size` number between `randstart` and `randstop`,
        sum it's digits. If the resulting value is equal to `filter_on`,
        yield it.
&nbsp;
        Arguments:
            size (int): the size of the pool to draw the numbers from
            randstart (int): the lower boundary to generate a number
            randstop (int): the upper boundary to generate a number
            filter_on (int): the value to compare to the digits_sum
&nbsp;
        Returns:
            Generator[float]
&nbsp;
        Example:
            &gt;&gt;&gt; list(gen_squareroot_sample(10, 0, 100, filter_on=5))
            [5.291502622129181, 6.708203932499369, 7.280109889280518]
&nbsp;
    &quot;&quot;&quot;</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>size<span style="color: black;">&#41;</span>:
        dsum <span style="color: #66cc66;">=</span> digits_sum<span style="color: black;">&#40;</span><span style="color: #dc143c;">random</span>.<span style="color: black;">randint</span><span style="color: black;">&#40;</span>randstart<span style="color: #66cc66;">,</span> randstop<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> dsum <span style="color: #66cc66;">==</span> filter_on:
            <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #dc143c;">math</span>.<span style="color: black;">sqrt</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Et dans un autre fichier :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">sqrt_sample <span style="color: #66cc66;">=</span> gen_squareroot_sample<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>L&#8217;important ici:</p>
<ul>
<li>Le code devient modulable car on en fait des fonctions</li>
<li>Les fonctions ont des paramètres avec des valeurs par défaut pour faciliter la vie.</li>
<li>On utilise les docstrings pour documenter le code.</li>
<li>Des noms bien choisis complètent cette documentation. Le code devient aussi plus verbeux pour laisser la place à la modularité, mais aussi la facilité d&#8217;édition.</li>
</ul>
<p>Il ne faut pas laisser le PEP8 vous limiter à la vision de la syntaxe. La qualité du code est importante : sa capacité à être lu, compris, utilisé facilement et modifié.</p>
<p>Pour cette même raison, il faut travailler ses APIS.</p>
<p>Si vous avez :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> DataSource:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        ...
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> close<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        ...
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> getTopic<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> topic<span style="color: black;">&#41;</span>:
       ...</pre></td></tr></table></div>

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

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">ds <span style="color: #66cc66;">=</span> DataSource<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
ds.<span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
data <span style="color: #66cc66;">=</span> ds.<span style="color: black;">getTopic</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'foo'</span><span style="color: black;">&#41;</span>
ds.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Vous pouvez raler sur le <code>getTopic</code>. Mais si vous vous limitez à ça, vous ratez l&#8217;essentiel : cette API n&#8217;est pas idiomatique.</p>
<p>Une version plus proche de la philosophie du langage serait:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> DataSource:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        ...
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> close<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        ...
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> get_topic<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> topic<span style="color: black;">&#41;</span>:
       ...
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__getitem__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> index<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">get_topic</span><span style="color: black;">&#40;</span>index<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> __enter__<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> __exit__<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> *args<span style="color: #66cc66;">,</span> **kwargs<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

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

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">with</span> DataSource<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> ds:
    data <span style="color: #66cc66;">=</span> ds<span style="color: black;">&#91;</span><span style="color: #483d8b;">'foo'</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Le style d&#8217;un langage va bien au-delà des règles de la syntaxe.</p>
<h2>Les docstrings</h2>
<p>Je suis beaucoup plus relaxe sur le style des docstrings. Il y a pourtant bien le <a href="https://www.python.org/dev/peps/pep-0257/">PEP 257</a> pour elles.</p>
<p>Simplement ne pas le respecter parfaitement n&#8217;affecte pas autant leur lisibilité car c&#8217;est du texte libre.</p>
<p>Quelques conseils tout de même.</p>
<ul>
<li>Si elle peut tenir sur une ligne, mettez tout sur une ligne, y compris les <code>"""</code>.</li>
<li>Utilisez <code>"""</code>, pas <code>'''</code>. La majorité des gens le font, et ça fera très bizarre de mélanger. </li>
<li>Choisissez une convention de documentation et tenez-vous y. Les plus populaires sont celles de <a href="https://pypi.python.org/pypi/sphinxcontrib-napoleon">sphinx, numpy et Google</a>. J&#8217;ai une préférence pour la dernière.</li>
<li>N&#8217;hésitez pas à la faire longue, avec un example. Il n&#8217;est pas rare que la docstring soit plus longue que le code quelle document.</li>
<li>Une bonne docstring et une fonction gardée courte et avec une signature bien nommée a rarement besoin de commentaires.</li>
<li>Les docstests sont un enfer à maintenir.</li>
</ul>
<h2>En bonus</h2>
<p><a href="https://pypi.python.org/pypi/flake8">flake8</a> est un excellent linter qui vérifiera votre style de code. Il existe en ligne de commande ou en plugin pour la plupart des éditeurs.</p>
<p>Dans le même genre, <a href="https://pypi.python.org/pypi/mccabe">mccabe</a> vérifira la complexité de votre code et vous dira si vous êtes en train de fumer en vous attributant un score. Il existe aussi intégré comme plugin de flake8 et activable via une option.</p>
<p><a href="https://pypi.python.org/pypi/tox">Tox</a> vous permet d&#8217;orchestrer tout ça, en plus de vos tests unittaires. Je ferai un article dessus un de ces 4.</p>
<p>Si vous voyez des commentaires comme <code># noqa</code> ou <code># xxx: ignore</code> ou <code># xxx: disable=YYY</code>, ce sont des commentaires pour pontuellement dire à ces outils de ne pas prendre en considération ces lignes.</p>
<p>Car souvenez-vous, ces règles sont là pour vous aider. Si à un moment précis elles cessent d&#8217;etre utiles, vous avez tous les droits de pouvoir les ignorer.</p>
<p>Mais ces règles communes font de Python un langage à l&#8217;écosystème exceptionnel. Elles facilitent énormément le travail en équipe, le partage et la productivité. Une fois habitué à cela, travailler dans d&#8217;autres conditions vous paraitra un poids inutile.</p>


