# articles

feed_id: http://sametmax.com/?p=8312
title: Pourquoi j’ai horreur d’acheter
uri: Pourquoi-j-ai-horreur-d-acheter
url: http://sametmax.com/pourquoi-jai-horreur-dacheter/
content:
<p>J&#8217;achète rarement des trucs neufs. Déjà, il faut que ça soit utile, que ça prenne pas trop de place, et que ça se déplace facilement vu que je bouge tout le temps.</p>
<p>Mais en plus, le problème d&#8217;un achat, c&#8217;est que ça bouffe énormément de temps, surtout si on l&#8217;achète pas en ligne.</p>
<p>Exemple, je vais à la fnac pour acheter un bidule à 150 euros. Je dois prendre la voiture (j&#8217;ai horreur de conduire) pour aller en centre ville, ce qui prend une bonne demi-heure. Il faut se garer, puis se taper la foule de mongoliens dans le magasin, en arpentant les étages pour trouver le bon rayon. </p>
<p>Là, je prends le produit dont j&#8217;ai fait le choix préalablement sur le net (encore du temps&#8230; pour un putain d&#8217;objet !) car les vendeurs n&#8217;y connaissent que dalle. Il faut se farcir la queue, payer en caisse, retourner chez soit. Une bonne heure et demi de perdue que j&#8217;aurais pu passer à faire des choses plus importantes, comme jouer à <a href="http://www.gog.com/game/dont_starve">Don&#8217;t Starve</a>, et encore, si on sait exactement ce qu&#8217;on fait.</p>
<p>Maintenant ça s&#8217;arrête là si tout va bien, mais évidement, l&#8217;histoire ne mériterait pas un article si c&#8217;était le cas.</p>
<p>Il se trouve qu&#8217;arrivé chez moi, le produit ne me satisfait pas. Pour 150 euros, je vais donc faire l&#8217;effort de le rapporter. Je le remballe, et on reprend la caisse. Ai-je précisé que je déteste conduire ?</p>
<p>Je demande à un vigile à l&#8217;entrée où est l&#8217;accueil.</p>
<p>Je vais à l&#8217;accueil pour demander à ce qu&#8217;on me le change. Je fais donc la queue.</p>
<p>L&#8217;accueil me renvoie vers un autre accueil un étage au dessus, qui s&#8217;en occupe. Je fais donc la queue.</p>
<p>L&#8217;autre accueil me dit que pour l&#8217;électronique, ce sont les vendeurs qui s&#8217;en occupent. Je cherche un vendeur, et tombe sur un mec qui est en fait vendeur Microsoft, pas fnac. Donc je vais en trouver un autre, qui est entouré de personnes qui lui posent des questions essentielles comme la couleur des barrettes de RAM, si l&#8217;anti-virus le protège contre le terrorisme et où sont les toilettes. Je fais donc la queue.</p>
<p>Le vendeur me signale qu&#8217;il me faut un bon de circulation pour cela, qu&#8217;il faut demander au vigile. Je retourne voir mon vigile à l&#8217;entrée, qui fouille le sac d&#8217;un mec alors que bien entendu seule la police est autorisée à faire ça. J&#8217;attends, mon tour. Je fais donc la queue.</p>
<p>Je chope le bon, retourne voir le vendeur, qui entre temps a changé de place alors qu&#8217;il avait dit qu&#8217;il m&#8217;attendrait. Je le retrouve, traitant un autre client. Je fais donc la queue.</p>
<p>Il me fais mon retour produit et m&#8217;annonce la couleur : ce sera un avoir. Donc uniquement valable dans les magasins fnac, et à utiliser dans les 3 mois. La partie fun maintenant : on ne peut pas le diviser, il va falloir que je fasse un achat de 150 euros. Joie.</p>
<p>Je note mentalement que j&#8217;achèterai avec 150 euros de carte cadeau, utilisable un an et divisible. Quand on fait une coloscopie, on choisit son hôpital.</p>
<p>Mais l&#8217;avoir n&#8217;est pas valable tant qu&#8217;il n&#8217;est pas validé en caisse, donc j&#8217;y vais pour, vous l&#8217;avez deviné, faire la queue.</p>
<p>A ce stade, la magasin ferme. Si, si. Je suis parti de chez moi en fin début d&#8217;après midi, et je sors du magasin à la fermeture. Pour me faire faire fouiller mon sac par le vigile. </p>
<p>Je hais les magasins. Je hais acheter des trucs.</p>
<p>Parce que même quand tout se passe bien (en supposant que ça ne tombe pas en panne, parce que là, c&#8217;est reparti pour l&#8217;Iliade version longue avec bonus DVD et sous-titrage en russe), l&#8217;histoire ne s&#8217;arrête pas là. L&#8217;objet prend de la place. Il faut le ranger. Occasionnellement le nettoyer ou l&#8217;entretenir. Et le transporter quand on déménage. Puis en disposer quand il arrive en fin de vie, ce qui, si on est sensible à l&#8217;écologie, suppose l&#8217;amener au bon point de recyclage. En l’occurrence, la fnac.</p>
<p>Je ne comprends pas comment &#8220;faire du shopping&#8221; peut être considéré comme un passe temps. </p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8312&amp;md5=c1d545fa718679ade1bd5c04c792ca06" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8327
title: Les mensonges des DSL
uri: Les-mensonges-des-DSL
url: http://sametmax.com/les-mensonges-des-dsl/
content:
<p>Un DSL, ou Domaine Specific Language, est un langage qui est dédié à un usage très pointu, et pour lequel il est donc particulièrement efficace.</p>
<p>Par exemple, le langage de Matlab est un DSL, dédié à l&#8217;expression mathématique. SQL est un DSL, orienté requête. PHP a commencé comme un DSL, optimisé pour le Web.</p>
<p>En théorie, un DSL doit vous rendre plus productif. En théorie. En pratique, une fois qu&#8217;un DSL sort de son domaine de prédilection, il est extrêmement inéficace. C&#8217;est le prix de la spécialisation.</p>
<p>Or, dernièrement, on a fait beaucoup l&#8217;apanage des DSL dans le cadre d&#8217;autres langages. Car oui, certains langages permettent de créer des DSL. Les macros du C et les capacités de meta programmations de Lisp permettent par exemple de créer des langages complets, avec des dialectes spécialisés.</p>
<p>Vient alors le premier problème : on créé un nouveau langage. Récent. Supporté et donc débuggé et (mal) documenté par l&#8217;auteur. Ensuite, on se rajoute un niveau d&#8217;indirection. Car du coup ça nous fait une abstraction supplémentaire, et il faut savoir ce que ça fait sous le capot. En prime, on freine l&#8217;entrée de nouveaux venus dans le projet, puisqu&#8217;il faut qu&#8217;ils apprenent à faire avec le DSL en plus, là où une simple lib aurait pu faire l&#8217;affaire.</p>
<p>Et on touche ici à une seconde problématique, les faux DSL : des libs ordinnaires qui se déguisent en DSL. Typiquement, je pense à Ruby, ici.</p>
<p>Les rubistes prétendent partout qu&#8217;ils peuvent créer des DSL avec leur langage. Encore un mensonge, puisque tout ce qu&#8217;ils font c&#8217;est utiliser le chaînage de méthode, le namespacing, la surcharge des opérateurs et les parenthèses/virgules facultatives pour donner l&#8217;impression qu&#8217;un nouveau langage est créé.</p>
<p>Tout comme on donne l&#8217;illusion de retourner deux paramètres dans une fonction en Python en retournant un tuple et en faisant de l&#8217;unpacking. C&#8217;est du sucre syntaxique, mais on est très loin de ce que ça prétend être.</p>
<p>Pourquoi c&#8217;est important ? Parce que cela laisse à croire qu&#8217;il y a quelque chose de spéciale là dedans, alors qu&#8217;il s&#8217;agit ni plus ni moins que d&#8217;une bête lib avec une API fluide. Ce qu&#8217;on peut faire dans tout autre langage (excepté l&#8217;absence de parenthèses, sur lequel il faudra que j&#8217;écrive un article tellement c&#8217;est une FBI).</p>
<p>Donc plutôt que de faire du bruit et du hype autour de cela, et amener les gens à se concentrer sur l&#8217;aspect &#8220;comment obtenir une syntaxe exotique&#8221;, il serait plus intéressant de dire tout simplement : voilà comment on peut faire une belle API, voici les bonnes pratiques, appliquez les.</p>
<p>Et aussi écrire une doc&#8230;</p>
<p>J&#8217;ai horreur en informatique quand on donne 40 noms différents à la même chose. Comme par exemple pour les promises, les futures, les deferred, etc. Merde, non seulement ça n&#8217;aide personne, mais en plus ça rend la comprehension de principes plus difficile. Déjà que c&#8217;est rarement bien expliqué&#8230;</p>
<p>Au final, un DSL est rarement une bonne idée, que ce soit un vrai ou un faux. SQL nous aura bien servi, il faut le reconnaitre, <a href="http://yinwang0.wordpress.com/2013/04/05/database/">même si on aurait pu faire mieux</a>. Mais la plupart du temps, ce sont quelques heures de gagnées en redaction de code, et des jours de formation et maintenance perdus, ou alors juste une masquarade cachant simplement derrière le hype des principes sains de programmation.</p>
<blockquote><p>Languages are more than just languages, they are a form of culture, and by being culture they tend to enforce (indirecty or directly) a certain way of doing things, i.e. standards or conventions. This means that if you know the language and its culture, there are less surprises and a longer learning or adaptation curve</p></blockquote>
<p>(Extrait de <a href="http://c2.com/cgi/wiki?LispIsTooPowerful">Is Lisp Too Powerful</a> ?)</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8327&amp;md5=aa6bf4c0a958dd4b3f2c998f329621d5" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8261
title: Remplacer sed, awk, cut et Perl par Python (= orgasme pour sysadmin)
uri: Remplacer-sed-awk-cut-et-Perl-par-Python-(-orgasme-pour-sysadmin)
url: http://sametmax.com/remplacer-sed-awk-cut-et-perl-par-python-orgasme-pour-sysadmin/
content:
<p>La force de Perl c&#8217;est qu&#8217;il permettait de piper des données directement via la ligne de commande pour faire des manipulations rapides.</p>
<p>C&#8217;est pour cela que c&#8217;était devenu les choix des sysadmins. Parce que jusqu&#8217;ici, le choix c&#8217;était soit de faire un truc simple en connaissant par coeur la tool box GNU, soit ouvrir un fichier et faire un script.</p>
<p>Python ne permet pas de piper des données directement dans la commande, mais des projets ont vu le jour pour le faire.</p>
<p>Il y a le projet <a href="http://code.google.com/p/pyp/">pyp</a>, que l&#8217;on doit à Sony Pictures Imageworks qui avait besoin de se simplifier l&#8217;automatisation des tâches de build pour ses films.</p>
<p>Et il y a <a href="https://pypi.python.org/pypi/Pyped/1.0">pyped</a>, dont j&#8217;avais brièvement parlé <a href="http://sametmax.com/sept-petites-libs-qui-changent-la-vie-dun-dev-python/">ici</a> (article qui mérite d&#8217;être mis à jour vu que j&#8217;ai remplace dateutils par <a href="http://sametmax.com/les-time-zones-en-python/">arrow</a>).</p>
<p>Les deux étaient sympas, mais avait des syntaxes alambiquées. Cependant, pyped est récemment passé en v1.0, donc stable, et a une toute nouvelle approche de syntaxe qui rend la bestiole super agréable à utiliser.</p>
<p>Présentation.</p>
<h2>Stdin, ligne à ligne</h2>
<p>L&#8217;installation est bateau, c&#8217;est du <a href="http://sametmax.com/votre-python-aime-les-pip/">pip</a> :</p>

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

<p>Et derrirère, on obtient la commande <code>py</code>. Elle s&#8217;utilise essentiellement à la suite d&#8217;une autre commande. Typiquement :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #000000; font-weight: bold;">/</span>etc<span style="color: #000000; font-weight: bold;">/</span>fsta <span style="color: #000000; font-weight: bold;">|</span> py <span style="color: #ff0000;">&quot;un truc&quot;</span></pre></div></div>

<p>L&#8217;astuce, c&#8217;est que &#8220;un truc&#8221; peut être n&#8217;importe quelle expression Python. Généralement une expression qui <code>print()</code> quelque chose.</p>
<p>Or, Pyped met automatiquement à disposition de cette expression deux variables :</p>
<ul>
<li>La ligne en cours, dans la variable <code>x</code>.</li>
<li>Le numéro de la ligne en cours, dans la variable <code>i</code>.</li>
</ul>
<p>L&#8217;expression Python est appelée une fois pour chaque ligne.</p>
<p>Par exemple, supposons que j&#8217;ai un fichier &#8220;fortune.txt&#8221; contenant :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">bitcoin <span style="color: #7a0874; font-weight: bold;">&#40;</span>btc<span style="color: #7a0874; font-weight: bold;">&#41;</span> : <span style="color: #000000;">5</span>
euros <span style="color: #7a0874; font-weight: bold;">&#40;</span>€<span style="color: #7a0874; font-weight: bold;">&#41;</span> : <span style="color: #000000;">100</span>
dollars <span style="color: #7a0874; font-weight: bold;">&#40;</span>$<span style="color: #7a0874; font-weight: bold;">&#41;</span> : <span style="color: #000000;">80</span></pre></div></div>

<p>Si je veut tout mettre en majuscule, je fais :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">cat</span> fortune.txt <span style="color: #000000; font-weight: bold;">|</span> py <span style="color: #ff0000;">&quot;print(x.upper())&quot;</span>
BITCOIN <span style="color: #7a0874; font-weight: bold;">&#40;</span>BTC<span style="color: #7a0874; font-weight: bold;">&#41;</span> : <span style="color: #000000;">5</span>
EUROS <span style="color: #7a0874; font-weight: bold;">&#40;</span>€<span style="color: #7a0874; font-weight: bold;">&#41;</span> : <span style="color: #000000;">100</span>
DOLLARS <span style="color: #7a0874; font-weight: bold;">&#40;</span>$<span style="color: #7a0874; font-weight: bold;">&#41;</span> : <span style="color: #000000;">80</span></pre></div></div>

<p>On peut mettre plusieurs expressions d&#8217;affilé. Ainsi, si je veux récupérer la somme et le symbole uniquement :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">cat</span> fortune.txt <span style="color: #000000; font-weight: bold;">|</span> py <span style="color: #ff0000;">&quot;devise, sign, _, value = x.split()&quot;</span> <span style="color: #ff0000;">&quot;sign = sign.strip('()')&quot;</span> <span style="color: #ff0000;">&quot;print('%s%s' % (value, sign))&quot;</span>
5btc
<span style="color: #000000;">100</span>€
<span style="color: #000000;">80</span>$</pre></div></div>

<p>Ok, c&#8217;est plus long que perl, mais vachement plus facile à écrire et à relire. Et j&#8217;utilise un langage que je connais déjà. Et pas besoin de faire un mix incompréhensible de sed, awk et autre cut.</p>
<p>Si j&#8217;ai vraiment besoin de lisibilité, je peux même le mettre sur plusieurs lignes :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">cat</span> fortune.txt <span style="color: #000000; font-weight: bold;">|</span> py <span style="color: #ff0000;">&quot;                                                                                                 
devise, sign, _, value = x.split() 
sign = sign.strip('()') 
print('%s%s' % (value, sign))  
&quot;</span>
5btc
<span style="color: #000000;">100</span>€
<span style="color: #000000;">80</span>$</pre></div></div>

<p>Vous aurez noté que j&#8217;utilise <code>print()</code> et que je semble ne pas me soucier de l&#8217;unicode. C&#8217;est parceque pyped fait ça au début du script :</p>

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

<p>Du coup, on est bien en Python 2.7, mais on bénéficie de la division améliorée, de la fonction pour printer, des imports absolus et surtout, de l&#8217;unicode partout. D&#8217;ailleurs pyped vous transforme <code>x</code> pour que ce soit un objet unicode. </p>
<h2>Tout traiter d&#8217;un coup</h2>
<p>Parfois, on a besoin d&#8217;avoir accès à toutes les lignes, pas juste les lignes une à une. pyped permet cela avec l&#8217;option <code>-i</code>. Les variables <code>x</code> et <code>i</code> disparaissent au profit de la variable <code>l</code>, qui contient un itérable sur toutes les lignes.</p>
<p>Par exemple, envie de trier tout ça ?</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">cat fortune.<span style="color: black;">txt</span> | py -i <span style="color: #483d8b;">&quot;
lignes = (x.split() for x in l)
lignes = sorted((v, s.strip('()')) for d, s, _, v in lignes)
for ligne in lignes: print('%s%s' % ligne)
&quot;</span>
<span style="color: #ff4500;">100</span>€
5btc
<span style="color: #ff4500;">80</span>$</pre></div></div>

<h2>Moar options</h2>
<p>Lisez la doc, car il y a d&#8217;autres options du genre éviter que pyped vous strip automatiquement le ligne break, forcer l&#8217;encoding, etc.</p>
<p>Parmi les trucs les plus utiles, il y a l&#8217;option <code>-b</code> qui permet de lancer un code avant la boucle. Pratique pour importer des trucs genre le module <code>tarfile</code> pour extraire une archive avant d&#8217;utiliser son contenu.</p>
<p>Néanmoins la plupart du temps on a rien besoin d&#8217;importer car pyped importe déjà automatiquement les modules les plus utiles : maths, datetime, re, json, hashlib, uuid, etc. </p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8261&amp;md5=83a66390fd625dd860b54e895ddffdee" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8356
title: Solution de l’exercice d’hier
uri: Solution-de-l-exercice-d-hier
url: http://sametmax.com/solution-de-lexercice-dhier/
content:
<p>Il faut bien noter que ce n&#8217;est qu&#8217;une solution parmi d&#8217;autres :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">string</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">unicodedata</span>
&nbsp;
mots = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
texte = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">decode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'utf8'</span><span style="color: black;">&#41;</span>.<span style="color: black;">replace</span><span style="color: black;">&#40;</span>u<span style="color: #483d8b;">'œ'</span>, <span style="color: #483d8b;">'oe'</span><span style="color: black;">&#41;</span>
texte = <span style="color: #dc143c;">unicodedata</span>.<span style="color: black;">normalize</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'NFKD'</span>, texte<span style="color: black;">&#41;</span>.<span style="color: black;">encode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'ascii'</span>, <span style="color: #483d8b;">'ignore'</span><span style="color: black;">&#41;</span>
texte = <span style="color: #dc143c;">re</span>.<span style="color: black;">sub</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'[^%s]'</span> <span style="color: #66cc66;">%</span> <span style="color: #dc143c;">string</span>.<span style="color: black;">ascii_lowercase</span>, <span style="color: #483d8b;">' '</span>, texte.<span style="color: black;">lower</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> i, e <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">enumerate</span><span style="color: black;">&#40;</span>texte.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
    mots.<span style="color: black;">setdefault</span><span style="color: black;">&#40;</span>e, <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>.<span style="color: black;">append</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#41;</span>
&nbsp;
mots = <span style="color: #008000;">sorted</span><span style="color: black;">&#40;</span>mots.<span style="color: black;">items</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, key=<span style="color: #ff7700;font-weight:bold;">lambda</span> x: <span style="color: black;">&#40;</span><span style="color: #008000;">len</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">sorted</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> mot, positions <span style="color: #ff7700;font-weight:bold;">in</span> mots:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'- %s: %s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>mot, <span style="color: #483d8b;">', '</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #008000;">map</span><span style="color: black;">&#40;</span><span style="color: #008000;">str</span>, positions<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></div></div>

<p>On ignore cordialement toute gestion d&#8217;erreur, donc le code peut se permettre d&#8217;être court. Et <code>.replace(u'œ', 'oe')</code> n&#8217;est pas très générique :-)</p>
<p>Dans les propositions de code des commentaires, il faut noter :</p>
<ul>
<li>Une utilisation fort maline du defaultdict par bob.</li>
<li>Le signalement d&#8217;unidecode par zanguu qui aurait géré <code>'œ'</code> sans problème. Mais ça rajoute une dépendance.</li>
</ul>
<p>Décorticage :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">string</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">unicodedata</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On va tocker les mots dans ce dico</span>
mots = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Je récupère en vrac le contenu du fichier. Comme on a pas de gestion des</span>
<span style="color: #808080; font-style: italic;"># erreurs, je récupère cash pistache le chemin de la ligne de commande</span>
<span style="color: #808080; font-style: italic;"># et je suppose un encoding en UTF8. Le résultat obtenu est un objet</span>
<span style="color: #808080; font-style: italic;"># unicode de tout le texte du fichier, sans le caractère 'œ'.</span>
texte = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">decode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'utf8'</span><span style="color: black;">&#41;</span>.<span style="color: black;">replace</span><span style="color: black;">&#40;</span>u<span style="color: #483d8b;">'œ'</span>, <span style="color: #483d8b;">'oe'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Astuce pour normaliser les caractères spéciaux. Ne marche que pour </span>
<span style="color: #808080; font-style: italic;"># l'alphabet latin malheureusement. Donc le script est limité. Unidecode</span>
<span style="color: #808080; font-style: italic;"># permettrait d'avoir un script plus générique.</span>
texte = <span style="color: #dc143c;">unicodedata</span>.<span style="color: black;">normalize</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'NFKD'</span>, texte<span style="color: black;">&#41;</span>.<span style="color: black;">encode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'ascii'</span>, <span style="color: #483d8b;">'ignore'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># string.ascii_lowercase contient toutes les lettres ASCII en minuscule,</span>
<span style="color: #808080; font-style: italic;"># ce qui permet de faire un remplacement, via regex, de </span>
<span style="color: #808080; font-style: italic;"># [^abcdefghijklmnopqrstuvwxyz]', c'est à dire tout ce qui n'est pas</span>
<span style="color: #808080; font-style: italic;"># une lettre ASCII minuscule.</span>
texte = <span style="color: #dc143c;">re</span>.<span style="color: black;">sub</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'[^%s]'</span> <span style="color: #66cc66;">%</span> <span style="color: #dc143c;">string</span>.<span style="color: black;">ascii_lowercase</span>, <span style="color: #483d8b;">' '</span>, texte.<span style="color: black;">lower</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Je récupère tous les &quot;mots&quot;, split() sans paramètre coupe en effet toute </span>
<span style="color: #808080; font-style: italic;"># combinaison de caractères non imprimables. enumerate() me permet d'avoir</span>
<span style="color: #808080; font-style: italic;"># la position de chaque mot. setdefault() me permet d'ignorer les clés qui</span>
<span style="color: #808080; font-style: italic;"># n'existent pas encore dans le dico. J'aurais pu utiliser un defaultdict, mais</span>
<span style="color: #808080; font-style: italic;"># comme on a qu'une seule ligne ici, c'est plus court.</span>
<span style="color: #808080; font-style: italic;"># J'obtiens donc un dico {mot1: [positon1, position2, ...], mot2: ...}</span>
<span style="color: #ff7700;font-weight:bold;">for</span> i, e <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">enumerate</span><span style="color: black;">&#40;</span>texte.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
    mots.<span style="color: black;">setdefault</span><span style="color: black;">&#40;</span>e, <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>.<span style="color: black;">append</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On récupère le contenu du dico sous forme de liste de tuples </span>
<span style="color: #808080; font-style: italic;"># [(mot, positions)...], et on l'ordonne selon le nombre d'apparitions</span>
<span style="color: #808080; font-style: italic;"># (len(x[1])), ou a défaut par ordre naturel des apparitions sorted(x[1]).</span>
<span style="color: #808080; font-style: italic;"># Pour rappel, key attend une fonction qui prend chaque élement, et retourne</span>
<span style="color: #808080; font-style: italic;"># une clé. La clé est utilisée pour ordonner les éléments : chaque élément</span>
<span style="color: #808080; font-style: italic;"># voit sa clé comparée à celle des autres, et ordonnée par ordre naturel.</span>
<span style="color: #808080; font-style: italic;"># Y a un article sur ça : http://sametmax.com/ordonner-en-python/</span>
<span style="color: #808080; font-style: italic;"># En gros, une entrée ('salut', 4, 18) aura pour clé (2, (4, 18)),</span>
<span style="color: #808080; font-style: italic;"># ce que Python peut comparer facilement.</span>
<span style="color: #808080; font-style: italic;"># Je réalise en rédigeant ces lignes que mon sorted est inutile, puisque </span>
<span style="color: #808080; font-style: italic;"># le processus est incrémental et déjà ordonné. Je le laisse comme référence.</span>
mots = <span style="color: #008000;">sorted</span><span style="color: black;">&#40;</span>mots.<span style="color: black;">items</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, key=<span style="color: #ff7700;font-weight:bold;">lambda</span> x: <span style="color: black;">&#40;</span><span style="color: #008000;">len</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">sorted</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Et on affiche tout ça, non sans caster les positions du type int vers str</span>
<span style="color: #808080; font-style: italic;"># pour éviter un crash</span>
<span style="color: #ff7700;font-weight:bold;">for</span> mot, positions <span style="color: #ff7700;font-weight:bold;">in</span> mots:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'- %s: %s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>mot, <span style="color: #483d8b;">', '</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #008000;">map</span><span style="color: black;">&#40;</span><span style="color: #008000;">str</span>, positions<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></div></div>

<hr/>
<p><a href="http://sametmax.com/petit-exercice-en-python/">Enoncé de l&#8217;exercice.</a></p>
<p><a href="https://github.com/sametmax/codes-des-articles/blob/master/2013/decembre/compter.py">Télécharger le code de l&#8217;article.</a></p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8356&amp;md5=80f003c6c2b9415b3b6ce49687108e9b" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8346
title: Petit exercice en Python
uri: Petit-exercice-en-Python
url: http://sametmax.com/petit-exercice-en-python/
content:
<p>Nouveau concept, de temps en temps, je vais proposer un exercice à faire en Python, vous postez vos solutions, et j&#8217;en posterai une le lendemain.</p>
<p>Pas de pression, c&#8217;est pour le fun.</p>
<p>Les solutions dans un autre langage sont bienvenues, mais privilégiez Python si vous avez le choix, c&#8217;est quand même le but.</p>
<p><strong>Postez votre code sur un pastebin ou ailleurs avec un lien en commentaire, pas le code directement dans les commentaires.</strong></p>
<p>Exercice du jour : </p>
<p><em>Un script qui attend un fichier en paramètre, l&#8217;ouvre, et trouve toutes les positions de chaque mot. </p>
<p>Le script doit prendre en compte les apostrophes, supprimer la ponctuation, et normaliser la casse et les caractères spéciaux des mots. </p>
<p>Le résultat doit afficher une liste à de mots avec leurs positions ordonnée par le nombre d&#8217;apparition, ou en cas d&#8217;égalité, par ordre naturel des positions.</em></p>
<p>Aucune gestion d&#8217;erreur n&#8217;est demandée.</p>
<p>Par exemple si j&#8217;ai un fichier contenant :</p>
<blockquote><p>« La marche des vertueux est semée d&#8217;obstacles qui sont les entreprises égoïstes que fait sans fin surgir l&#8217;œuvre du Malin. Béni soit-il l&#8217;homme de bonne volonté qui, au nom de la charité, se fait le berger des faibles qu&#8217;il guide dans la vallée d&#8217;ombre, de la mort et des larmes, car il est le gardien de son frère et la providence des enfants égarés. J&#8217;abattrai alors le bras d&#8217;une terrible colère, d&#8217;une vengeance furieuse et effrayante sur les hordes impies qui pourchassent et réduisent à néant les brebis de Dieu. Et tu connaîtras pourquoi mon nom est l&#8217;éternel quand sur toi s&#8217;abattra la vengeance du Tout-Puissant ! » </p>
<p>Ça fait des années que je répète ça. L&#8217;enfoiré qui l&#8217;entend, il meurt aussitôt. J&#8217;avais jamais cherché à comprendre, je trouvais seulement que ça en jetait de dire ça avant de flinguer un mec. Et puis ce matin, j&#8217;ai vu quelque chose qui m&#8217;a fait réfléchir. D&#8217;un seul coup, je me dis, ça pourrait bien vouloir dire que tu es l&#8217;œuvre du malin, et que l&#8217;homme vertueux c&#8217;est moi, et que mon joli 9 mm ce serait mon protecteur, mon berger dans la vallée de l&#8217;angoisse et des larmes. Ou encore mieux, c&#8217;est moi le berger et toi l&#8217;homme vertueux, et c&#8217;est le monde qui est l&#8217;œuvre de Lucifer. Qu&#8217;est-ce que tu dis de ça ? Mais rien de tout ça n&#8217;est juste. Ce qui est vrai, c&#8217;est que tu es le faible et que je suis la tyrannie des méchants. Et moi j&#8217;essaie, Ringo, au prix d&#8217;un effort harassant, de protéger les faibles.</p></blockquote>
<p>On appelle le script ainsi :</p>

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

<p>Et il affiche ceci :</p>
<pre>- marche: 1
- semee: 5
- obstacles: 7
- sont: 9
- entreprises: 11
- egoistes: 12
- sans: 15
- fin: 16
- surgir: 17
- beni: 22
- soit: 23
- bonne: 28
- volonte: 29
- charite: 35
- se: 36
- guide: 44
- ombre: 49
- mort: 52
- car: 56
- gardien: 60
- son: 62
- frere: 63
- providence: 66
- enfants: 68
- egares: 69
- abattrai: 71
- alors: 72
- bras: 74
- terrible: 77
- colere: 78
- furieuse: 82
- effrayante: 84
- hordes: 87
- impies: 88
- pourchassent: 90
- reduisent: 92
- neant: 94
- brebis: 96
- dieu: 98
- connaitras: 101
- pourquoi: 102
- eternel: 107
- quand: 108
- s: 111
- abattra: 112
- puissant: 117
- annees: 121
- repete: 124
- enfoire: 127
- entend: 130
- meurt: 132
- aussitot: 133
- avais: 135
- jamais: 136
- cherche: 137
- comprendre: 139
- trouvais: 141
- seulement: 142
- en: 145
- jetait: 146
- avant: 150
- flinguer: 152
- mec: 154
- puis: 156
- matin: 158
- ai: 160
- vu: 161
- quelque: 162
- chose: 163
- m: 165
- reflechir: 168
- seul: 171
- coup: 172
- me: 174
- pourrait: 177
- bien: 178
- vouloir: 179
- joli: 199
- mm: 200
- serait: 202
- protecteur: 204
- angoisse: 212
- ou: 216
- encore: 217
- mieux: 218
- monde: 233
- lucifer: 239
- mais: 248
- rien: 249
- n: 253
- juste: 255
- vrai: 259
- faible: 266
- suis: 270
- tyrannie: 272
- mechants: 274
- essaie: 278
- ringo: 279
- prix: 281
- effort: 284
- harassant: 285
- proteger: 287
- malin: 21, 187
- au: 31, 280
- nom: 32, 104
- faibles: 41, 289
- qu: 42, 240
- dans: 45, 207
- vallee: 47, 209
- larmes: 55, 215
- une: 76, 80
- vengeance: 81, 114
- sur: 85, 109
- toi: 110, 225
- tout: 116, 251
- dire: 148, 180
- dis: 175, 245
- es: 183, 264
- vertueux: 3, 192, 228
- oeuvre: 19, 185, 237
- du: 20, 115, 186
- homme: 26, 191, 227
- berger: 39, 206, 223
- a: 93, 138, 166
- un: 153, 170, 283
- moi: 195, 221, 276
- les: 10, 86, 95, 288
- fait: 14, 37, 119, 167
- il: 24, 43, 57, 131
- j: 70, 134, 159, 277
- tu: 100, 182, 244, 263
- mon: 103, 198, 203, 205
- je: 123, 140, 173, 269
- ce: 157, 201, 242, 256
- c: 193, 219, 230, 260
- d: 6, 48, 75, 79, 169, 282
- le: 38, 59, 73, 222, 232, 265
- des: 2, 40, 54, 67, 120, 214, 273
- qui: 8, 30, 89, 128, 164, 234, 257
- ca: 118, 125, 144, 149, 176, 247, 252
- la: 0, 34, 46, 51, 65, 113, 208, 271
- que: 13, 122, 143, 181, 189, 197, 243, 262, 268
- l: 18, 25, 106, 126, 129, 184, 190, 211, 226, 236
- est: 4, 58, 105, 194, 220, 231, 235, 241, 254, 258, 261
- de: 27, 33, 50, 61, 97, 147, 151, 210, 238, 246, 250, 286
- et: 53, 64, 83, 91, 99, 155, 188, 196, 213, 224, 229, 267, 275
</pre>
<hr />
<p><a href="http://sametmax.com/solution-de-lexercice-dhier/">Solution</a></p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8346&amp;md5=d9f222b024219b43e7d80ebc894a065a" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8158
title: Article retiré pour cause de grosse merde
uri: Article-retiré-pour-cause-de-grosse-merde
url: http://sametmax.com/nested-format-expansion-thats-a-swag-title-cracker/
content:
<p>Désolé pour ceux qui ont reçu l&#8217;article via RSS ou email. Je le retire. C&#8217;était de la merde.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8158&amp;md5=c5619aecfdf714e8b31186151b44fc2d" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=7656
title: Changement dans l’unpacking des iterables en Python 3
uri: Changement-dans-l-unpacking-des-iterables-en-Python-3
url: http://sametmax.com/changement-dans-lunpacking-des-iterables-en-python-3/
content:
<p>Ahhh, l&#8217;unpacking&#8230; On croit qu&#8217;on a complètement <a href="http://sametmax.com/tag/unpacking/">fait le tour</a> de cette fonctionalité merveilleuse, et PAF, on découvre encore autre chose.</p>
<p>Par exemple, la syntaxe a été améliorée avec Python 3, et accepte maintenant un <a href="http://www.python.org/dev/peps/pep-3132/">unpacking partiel</a> !</p>
<p>Ca se fait en l&#8217;utilisant l&#8217;opérateur splat, c&#8217;est à dire l&#8217;étoile :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> l = <span style="color: #008000;">list</span><span style="color: black;">&#40;</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: #66cc66;">&gt;&gt;&gt;</span> l
<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span>, <span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> a, <span style="color: #66cc66;">*</span>b = l
<span style="color: #66cc66;">&gt;&gt;&gt;</span> a
<span style="color: #ff4500;">0</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> b
<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span>, <span style="color: #ff4500;">4</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> a, <span style="color: #66cc66;">*</span>b, c = l
<span style="color: #66cc66;">&gt;&gt;&gt;</span> a
<span style="color: #ff4500;">0</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> b
<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> c
<span style="color: #ff4500;">4</span></pre></div></div>

<p>Ca marche bien entendu également dans les boucles <code>for</code>.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7656&amp;md5=79234a2f0c8636aa390b93bd9fb7a3b5" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8392
title: De l’intérêt des tuples comme clé de dictionnaire
uri: De-l-intérêt-des-tuples-comme-clé-de-dictionnaire
url: http://sametmax.com/de-linteret-des-tuples-comme-cle-de-dictionnaire/
content:
<p>On peut utiliser n&#8217;importe quel objet hashable comme clé de dictionnaire en Python, pas uniquement des strings. Donc des entiers bien entendu, mais également, et c&#8217;est rarement utilisé, des tuples.</p>
<p>Imaginez que vous ayez une structures de données ainsi initialisée :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">random</span> <span style="color: #ff7700;font-weight:bold;">import</span> choice, randint
&nbsp;
tags = <span style="color: black;">&#40;</span><span style="color: #483d8b;">'personne'</span>, <span style="color: #483d8b;">'animal'</span>, <span style="color: #483d8b;">'objet'</span><span style="color: black;">&#41;</span>
depart = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
&nbsp;
depart = <span style="color: black;">&#123;</span><span style="color: #483d8b;">'%s_%s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>choice<span style="color: black;">&#40;</span>tags<span style="color: black;">&#41;</span>, randint<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>: <span style="color: #008000;">None</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span><span style="color: black;">&#125;</span></pre></div></div>

<p>Cela donne quelque chose comme ça :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'personne_6'</span>: <span style="color: #008000;">None</span>,
 u<span style="color: #483d8b;">'personne_5'</span>: <span style="color: #008000;">None</span>,
 u<span style="color: #483d8b;">'objet_9'</span>: <span style="color: #008000;">None</span>,
 u<span style="color: #483d8b;">'objet_6'</span>: <span style="color: #008000;">None</span>,
 u<span style="color: #483d8b;">'objet_4'</span>: <span style="color: #008000;">None</span>,
 u<span style="color: #483d8b;">'personne_8'</span>: <span style="color: #008000;">None</span>,
 u<span style="color: #483d8b;">'objet_2'</span>: <span style="color: #008000;">None</span>,
 u<span style="color: #483d8b;">'objet_0'</span>: <span style="color: #008000;">None</span>,
 u<span style="color: #483d8b;">'animal_8'</span>: <span style="color: #008000;">None</span><span style="color: black;">&#125;</span></pre></div></div>

<p>On voit que les clés ont ici une valeur sémantique importante : elles sont porteuses de sens.</p>
<p>Si vous voulez la liste des nombres utilisés, il va vous falloir changer votre structure de données : en avoir plusieurs séparées, probablement. Ou alors faire de la manipulation de chaîne à base de <code>split()</code> et de casting.</p>
<p>Par contre, si vous utilisez un tuple comme clé, vous avez le même format pour votre dictionnaire <code>depart</code>, avec les mêmes possibilités, mais en plus un accès aux clés plus complet.</p>
<p>Déjà le code de génération est plus simple :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">depart = <span style="color: black;">&#123;</span><span style="color: black;">&#40;</span>choice<span style="color: black;">&#40;</span>tags<span style="color: black;">&#41;</span>, randint<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span>, <span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>: <span style="color: #008000;">None</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span><span style="color: black;">&#125;</span></pre></div></div>

<p>Ce qui donne :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: black;">&#123;</span><span style="color: black;">&#40;</span>u<span style="color: #483d8b;">'animal'</span>, <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>: <span style="color: #008000;">None</span>,
 <span style="color: black;">&#40;</span>u<span style="color: #483d8b;">'personne'</span>, <span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>: <span style="color: #008000;">None</span>,
 <span style="color: black;">&#40;</span>u<span style="color: #483d8b;">'personne'</span>, <span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>: <span style="color: #008000;">None</span>,
 <span style="color: black;">&#40;</span>u<span style="color: #483d8b;">'objet'</span>, <span style="color: #ff4500;">6</span><span style="color: black;">&#41;</span>: <span style="color: #008000;">None</span>,
 <span style="color: black;">&#40;</span>u<span style="color: #483d8b;">'objet'</span>, <span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span>: <span style="color: #008000;">None</span>,
 <span style="color: black;">&#40;</span>u<span style="color: #483d8b;">'animal'</span>, <span style="color: #ff4500;">7</span><span style="color: black;">&#41;</span>: <span style="color: #008000;">None</span>,
 <span style="color: black;">&#40;</span>u<span style="color: #483d8b;">'animal'</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>: <span style="color: #008000;">None</span>,
 <span style="color: black;">&#40;</span>u<span style="color: #483d8b;">'animal'</span>, <span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span>: <span style="color: #008000;">None</span>,
 <span style="color: black;">&#40;</span>u<span style="color: #483d8b;">'personne'</span>, <span style="color: #ff4500;">8</span><span style="color: black;">&#41;</span>: <span style="color: #008000;">None</span><span style="color: black;">&#125;</span></pre></div></div>

<p>Mais en prime, on peut faire ça :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">for</span> <span style="color: black;">&#40;</span>tag, number<span style="color: black;">&#41;</span>, value <span style="color: #ff7700;font-weight:bold;">in</span> depart.<span style="color: black;">items</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> tag, number, value
&nbsp;
<span style="color: #808080; font-style: italic;">## animal 2 None</span>
<span style="color: #808080; font-style: italic;">## personne 5 None</span>
<span style="color: #808080; font-style: italic;">## personne 4 None</span>
<span style="color: #808080; font-style: italic;">## objet 6 None</span>
<span style="color: #808080; font-style: italic;">## objet 10 None</span>
<span style="color: #808080; font-style: italic;">## animal 7 None</span>
<span style="color: #808080; font-style: italic;">## animal 1 None</span>
<span style="color: #808080; font-style: italic;">## animal 10 None</span>
<span style="color: #808080; font-style: italic;">## personne 8 None</span></pre></div></div>

<p>Bref, quand vos clés ont une valeur sémantique importante, pensez à utiliser des tuples, voir carrément, un <a href="http://sametmax.com/ce-que-vous-ne-saviez-pas-sur-les-collections-en-python/">namedtuple</a>, qui est une structure de données trop souvent ignorée alors qu&#8217;elle est très puissante, et peut remplacer bien des classes conteneurs.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8392&amp;md5=e596665cb3a170df153e4f3c0f651e83" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8376
title: 5 choses à apprendre en priorité en Python
uri: 5-choses-à-apprendre-en-priorité-en-Python
url: http://sametmax.com/5-choses-a-apprendre-en-priorite-en-python/
content:
<p>Quand on apprend un nouveau langage de programmation, on apprend d&#8217;abord les bases. Et pour la plupart des langages, elles sont communes : déclarer une variable, faire des conditions et des boucles, faire des fonctions, importer un code d&#8217;un autre fichier, etc.</p>
<p>Ce qui va différencier le moment où vous savez programmer dans CE langage, ce sont des notions qui lui sont spécifiques et que vous commencez à maitriser.</p>
<p>Voici 5 notions spécifiques au langage qu&#8217;il faut apprendre en priorité si vous voulez pouvoir dire &#8220;je code en Python&#8221; :</p>
<h2>Pip</h2>
<p>Pip est la moyen le plus utilisé d&#8217;installer une bibliothèque externe dans l&#8217;environnement Python. Dès qu&#8217;on veut faire un projet sérieux, on en a besoin. Tellement qu&#8217;il va en fait être inclus par défaut dans Python 3.4.</p>
<p><a href="http://sametmax.com/votre-python-aime-les-pip/">Lire l&#8217;article sur pip.</a></p>
<h2>Virtualenv</h2>
<p>Virtualenv permet d&#8217;isoler plusieurs installations de Python. A partir du moment où l&#8217;on travaille sur plusieurs projets en même temps, il devient vite indispensable. Mais personnelement, je l&#8217;utilise même quand je n&#8217;ai qu&#8217;un projet installé sur une machine car il me permet de le séparer du setup Python du système et d&#8217;utiliser des hooks.</p>
<p>Un outil qui a été ajouté dans la lib standard en Python 3.3. J&#8217;apprécie que le pragmatisme de l&#8217;évolution de Python qui intègre petit à petit les projets qui se sont révélés les outils de facto dans la communauté.</p>
<p><a href="http://sametmax.com/les-environnement-virtuels-python-virtualenv-et-virtualenvwrapper/">Lire l&#8217;article sur virtualenv.</a></p>
<h2>Les listes en intention</h2>
<p>J&#8217;ai envie de dire l&#8217;itération en générale, mais c&#8217;est un très vaste sujet, et il est couvert en grande partie par les 3 derniers points.</p>
<p>La liste en intention, ou liste en compréhension, est une manière de boucler sur un itérable (souvent une liste), avec optionellement un filtre, afin de produire une nouvelle liste. En une ligne.</p>
<p>C&#8217;est stylistiquement la marque de fabrique de Python (même si c&#8217;est piqué à Haskell). C&#8217;est également ce qui le rend aussi expressif. On peut presque coder tout un programme en déclaratif avec des enchainements de listes en intention.</p>
<p>C&#8217;est beau, propre, efficace et court. IN-DIS-PEN-SA-BLE.</p>
<p><a href="http://sametmax.com/python-love-les-listes-en-intention-partie/">Lire l&#8217;article sur les listes en intention.</a></p>
<h2>L&#8217;unpacking</h2>
<p>L&#8217;unpacking est une autre fonctionalité typiquement pythonienne qui permet de prendre un itérable (souvent un tuple), et de mettre ses éléments dans des variables d&#8217;une traite.</p>
<p>Cela permet d&#8217;augmenter drastiquement la lisibilité des programmes.</p>
<p><a href="http://sametmax.com/tag/unpacking/">Lire les articles sur l&#8217;unpacking.</a></p>
<h2>Les générateurs</h2>
<p>Les générateurs permettent non seulement un énorme gain en performance, mais en plus ils autorisent le traitement itératif de flux de données dont on ne connait pas la taille en avance, voire de taille infinie. Si vous utilisez des expressions génératrices, vous pourrez le faire en déclaratif. Si vous utilisez <code>yield</code>, vous pourrez cacher un algorithme complet derrière une simple boucle <code>for</code>.</p>
<p><a href="http://sametmax.com/comment-utiliser-yield-et-les-generateurs-en-python/">Lire l&#8217;article sur yield.</a></p>
<h2>Le reste ?</h2>
<p>Tout le reste, c&#8217;est du détail. Les décorateurs, la POO, l&#8217;opérateur <code>with</code>, les métaclasses, les astuces magiques pour faire ceci ou cela. C&#8217;est bien, mais ça peut attendre. Ce sont ces 5 notions, qui, bien utilisées, feront d&#8217;un programmeur un dev Python.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8376&amp;md5=0c3f015bc4b353adc195e30c23ba6e29" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6831
title: Présentation de RapydScript
uri: Présentation-de-RapydScript
url: http://sametmax.com/presentation-de-rapydscript/
content:
<p style="text-align: center;"><em><small>Ceci est un post invité de <a href="http://sametmax.com/author/ArtyProg/">ArtyProg</a> posté sous licence <a href="http://creativecommons.org/licenses/by/3.0/">creative common 3.0 unported</a>.</small></em></p>
<p>Javascript est devenu le langage incontournable du Web. C&#8217;est un langage suprenant, avec lequel, entre des mains expertes, il est possible de réaliser des choses impressionnantes.<br />
Néanmoins, pour des tas de raisons, il s&#8217;avère encore compliqué de créer et maintenir des projets d&#8217;envergure. De plus, de nombreux développeurs sont allergiques aux bizareries de Javascript.</p>
<p>Il existe depuis longtemps des solutions permettant d&#8217;éviter de programmer directement en Javascript.Le site <a href="http://altjs.org/" title="http://altjs.org/">http://altjs.org/</a> référence de nombreuses solutions dans ce sens.</p>
<p>Bien entendu, je me suis intéressé aux solutions &#8216;Python to Javascript&#8217;. Parmi ces projets, trois, selon moi, sortent du lot : Brython, Skulpt et RapydScript.<br />
Le but de Brython et Skulpt et de s&#8217;affranchir totalement de Javascript.<br />
Brython pousse le concept très loin, il permet d&#8217;utilier la balise &lt;script lang=&#8221;python&#8221;&gt;&lt;/script&gt; directement dans une page web. Il s&#8217;agit vraiment d&#8217;un formidable projet.</p>
<p>Si Brython et Skulpt sont si bien, pourquoi mettre en avant  RapydScript ?<br />
En fait, la particularité RapydScript est qu&#8217;il ne tente pas de s&#8217;affranchir de Javascript, bien au contraire. La syntaxe est &#8216;pratiquement&#8217; celle de  Python, mais il permet d&#8217;introduire du Javascript de façon totalement transparente.</p>
<p>Pour ceux qui ne sont pas dérangés par la langue de Shakespeare voici l&#8217;adresse du site officiel: <a href="https://bitbucket.org/pyjeon/rapydscript" title="https://bitbucket.org/pyjeon/rapydscript">https://bitbucket.org/pyjeon/rapydscript</a></p>
<p>J&#8217;ai mis en ligne un page contenant quelques applications réalisées avec RapydScript :<a href="http://salvatore.pythonanywhere.com/RapydScript" title="http://salvatore.pythonanywhere.com/RapydScript"> http://salvatore.pythonanywhere.com/RapydScript</a></p>
<p>Voici encore un autre exemple, qui montre la facilité avec laquelle<br />
on peut intégrer les librairies Javascript ici &#8216;canvas.js&#8217;:<br />
<a href="http://salvatore.pythonanywhere.com/RapydBox">http://salvatore.pythonanywhere.com/RapydBox</a> (à voir avec Firefox ou Safari)</p>
<p>Le code Javascript produit est très lisible comme le montrent les exemples suivants:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> sumList<span style="color: black;">&#40;</span>L<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>L<span style="color: black;">&#41;</span> == <span style="color: #ff4500;">0</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>:
        head, tail = L<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>,L<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;">return</span> head + sumList<span style="color: black;">&#40;</span>tail<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> factorial<span style="color: black;">&#40;</span>n<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> n == <span style="color: #ff4500;">0</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #ff4500;">1</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> n <span style="color: #66cc66;">*</span> factorial<span style="color: black;">&#40;</span>n-<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Une fois compilé voici le code Javascsript produit:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> sumList<span style="color: #009900;">&#40;</span>L<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> head<span style="color: #339933;">,</span> tail<span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>len<span style="color: #009900;">&#40;</span>L<span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span>
        _$rapyd$_Unpack <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span>L<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> L.<span style="color: #660066;">slice</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        head <span style="color: #339933;">=</span> _$rapyd$_Unpack<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        tail <span style="color: #339933;">=</span> _$rapyd$_Unpack<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">return</span> head <span style="color: #339933;">+</span> sumList<span style="color: #009900;">&#40;</span>tail<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #003366; font-weight: bold;">function</span> factorial<span style="color: #009900;">&#40;</span>n<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>n <span style="color: #339933;">==</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #CC0000;">1</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000066; font-weight: bold;">return</span> n <span style="color: #339933;">*</span> factorial<span style="color: #009900;">&#40;</span>n <span style="color: #339933;">-</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>RapydScript n&#8217;est pas un gadget, on peut l&#8217;utiliser pour développer de<br />
véritables projets.</p>
<p>Et pour terminer, vous pouvez utiliser <a href="https://github.com/rogerwang/node-webkit" title="node-webkit" target="_blank">node-webkit</a> pour packager et diffuser vos programmes.</p>
<p>A vous de jouer&#8230;</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6831&amp;md5=bb62fd8c3b0bc09c07567c88118cd0e4" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=7754
title: Est-ce que “framework x” supporte la charge ?
uri: Est-ce-que-framework-x-supporte-la-charge
url: http://sametmax.com/est-ce-que-framework-x-supporte-la-charge/
content:
<p style="text-align:center;">Oui.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=7754&amp;md5=949a226976eaf65888716789d2de8a17" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8447
title: Afficher le queryset d’une requête dans les logs SQL sous Django
uri: Afficher-le-queryset-d-une-requête-dans-les-logs-SQL-sous-Django
url: http://sametmax.com/afficher-le-queryset-dune-requete-dans-les-logs-sql-sous-django/
content:
<p>C&#8217;est Noël, 2 articles rien que pour vous dont un <a href="http://sametmax.com/est-ce-que-framework-x-supporte-la-charge/" title="Est-ce que “framework x” supporte la charge ?">très interressant de Sam</a>.</p>
<p>L&#8217;ORM de django pour les bases de données est chouette, agréable à utiliser mais construit des requêtes SQL qu&#8217;on ne peut reconnaître lors de l&#8217;analyse des logs MYSQL du premier coup d&#8217;oeil. Et quand on a des centaines de requêtes par secondes c&#8217;est carrément impossible de s&#8217;y retrouver.</p>
<p>Ce que je vous propose ici c&#8217;est d&#8217;afficher le queryset (sa ligne et le fichier qui le contient) qui a permit d&#8217;exêcuter la requête SQL que vous voyez défiler dans les logs SQL sous forme de <a href="http://dev.mysql.com/doc/refman/5.0/en/comments.html">commentaires SQL</a>.</p>
<p>L&#8217;application se nomme <a href="https://pypi.python.org/pypi/django-sql-stacktrace/">Django Sql StackTrace</a>. C&#8217;est facile à installer et ça peut sauver des heures de debug.</p>
<p><strong>Installation Django Sql StackTrace:</strong></p>
<p><strong>Une bonne PIP comme toujours pour bien commencer.</strong></p>

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

<p><strong>Dans votre fichier settings de django.</strong></p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">INSTALLED_APPS = <span style="color: #7a0874; font-weight: bold;">&#40;</span>
    .........................
    <span style="color: #ff0000;">'sqlstacktrace'</span>,
    .........................
<span style="color: #7a0874; font-weight: bold;">&#41;</span>
&nbsp;
SQL_STACKTRACE = True</pre></div></div>

<p>La variable SQL_STACKTRACE sert à activer le debug.<br />
Pensez à le désactiver lorsque vous n&#8217;en avez pas besoin.</p>
<p><strong>Où se trouve mes super infos de debug ?</strong></p>
<p><a href="http://adw0rd.com/2012/8/23/django-sql-stacktrace/en/#.Urq_5mRdU98">D&#8217;après la doc</a> vous pouvez executer un <a href="http://pwet.fr/man/linux/commandes/watch">watch</a></p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">watch</span> <span style="color: #660033;">-n1</span> mysqladmin <span style="color: #660033;">-u</span> <span style="color: #c20cb9; font-weight: bold;">login</span> -pmot_de_passe processlist <span style="color: #660033;">--verbose</span></pre></div></div>

<p>Chez moi ça n&#8217;a rien donné. Mais du côté des logs MySQL la magie a opérée.<br />
Vérifiez tout d&#8217;abord que vos logs sont activés dans mysql.</p>

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


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#91;</span>mysqld<span style="color: #7a0874; font-weight: bold;">&#93;</span>
......
log = <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>logs<span style="color: #000000; font-weight: bold;">/</span>mysql.log
......</pre></div></div>

<p><strong>Comment on teste ça ?</strong></p>
<p>Redemarrez votre serveur web, surfez sur les pages de votre projet et observez les logs MySql. Vous deviez voir quelques chose de similaire:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">tail</span> <span style="color: #660033;">-F</span> <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>logs<span style="color: #000000; font-weight: bold;">/</span>mysql.log</pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">		  <span style="color: #000000;">644</span> Query	SELECT <span style="color: #000000; font-weight: bold;">`</span>auth_user<span style="color: #000000; font-weight: bold;">`</span>.<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">id</span><span style="color: #000000; font-weight: bold;">`</span>, <span style="color: #000000; font-weight: bold;">`</span>auth_user<span style="color: #000000; font-weight: bold;">`</span>.<span style="color: #000000; font-weight: bold;">`</span>password<span style="color: #000000; font-weight: bold;">`</span>, <span style="color: #000000; font-weight: bold;">`</span>auth_user<span style="color: #000000; font-weight: bold;">`</span>.<span style="color: #000000; font-weight: bold;">`</span>last_login<span style="color: #000000; font-weight: bold;">`</span>, <span style="color: #000000; font-weight: bold;">`</span>auth_user<span style="color: #000000; font-weight: bold;">`</span>.<span style="color: #000000; font-weight: bold;">`</span>is_superuser<span style="color: #000000; font-weight: bold;">`</span>, <span style="color: #000000; font-weight: bold;">`</span>auth_user<span style="color: #000000; font-weight: bold;">`</span>.<span style="color: #000000; font-weight: bold;">`</span>username<span style="color: #000000; font-weight: bold;">`</span>, <span style="color: #000000; font-weight: bold;">`</span>auth_user<span style="color: #000000; font-weight: bold;">`</span>.<span style="color: #000000; font-weight: bold;">`</span>first_name<span style="color: #000000; font-weight: bold;">`</span>, <span style="color: #000000; font-weight: bold;">`</span>auth_user<span style="color: #000000; font-weight: bold;">`</span>.<span style="color: #000000; font-weight: bold;">`</span>last_name<span style="color: #000000; font-weight: bold;">`</span>, <span style="color: #000000; font-weight: bold;">`</span>auth_user<span style="color: #000000; font-weight: bold;">`</span>.<span style="color: #000000; font-weight: bold;">`</span>email<span style="color: #000000; font-weight: bold;">`</span>, <span style="color: #000000; font-weight: bold;">`</span>auth_user<span style="color: #000000; font-weight: bold;">`</span>.<span style="color: #000000; font-weight: bold;">`</span>is_staff<span style="color: #000000; font-weight: bold;">`</span>, <span style="color: #000000; font-weight: bold;">`</span>auth_user<span style="color: #000000; font-weight: bold;">`</span>.<span style="color: #000000; font-weight: bold;">`</span>is_active<span style="color: #000000; font-weight: bold;">`</span>, <span style="color: #000000; font-weight: bold;">`</span>auth_user<span style="color: #000000; font-weight: bold;">`</span>.<span style="color: #000000; font-weight: bold;">`</span>date_joined<span style="color: #000000; font-weight: bold;">`</span> FROM <span style="color: #000000; font-weight: bold;">`</span>auth_user<span style="color: #000000; font-weight: bold;">`</span> WHERE <span style="color: #000000; font-weight: bold;">`</span>auth_user<span style="color: #000000; font-weight: bold;">`</span>.<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">id</span><span style="color: #000000; font-weight: bold;">`</span> = <span style="color: #000000;">65290</span>
<span style="color: #000000; font-weight: bold;">/*</span> File <span style="color: #ff0000;">&quot;/Users/max/work/mon_projet/apps/mon_apps/views/others.py&quot;</span>, line <span style="color: #000000;">146</span>, <span style="color: #000000; font-weight: bold;">in</span> user_public_page
	user = User.objects.get<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #007800;">pk</span>=user_id<span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #000000; font-weight: bold;">*/</span></pre></div></div>

<p>Observez cette merveille !<br />
Entre <strong>/* */</strong> sont les infos générées par django-sql-stacktrace. J&#8217;ai nettoyé quelques fichiers pour plus de lisibilité.<br />
Vous avez droit au chemin du fichier de la requête, à la ligne de la requête et à la requête django elle-même.</p>
<p><strong>Une alternative ? J&#8217;ai pas envie d&#8217;installer d&#8217;app.</strong></p>
<p>Pour les grosses feignasses ou si vous voulez juste tester occasionnellement quelques queries vous pouvez utiliser la méthode extra pour ajouter vos propres commentaires.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">videos = Video.objects.filter<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #007800;">status</span>=<span style="color: #ff0000;">'online'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>.extra<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #007800;">where</span>=<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #ff0000;">'1=1 /* ceci apparaitra dans les logs mysql ! */'</span><span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span></pre></div></div>

<p>Cependant le WHERE 1=1 peut causer quelques baisses de performances, mais lorsqu&#8217;on est en debug en local ça peut servir !</p>
<p>PS: Je rappelle également le formidable outil <a href="https://github.com/django-debug-toolbar/django-debug-toolbar">django-debug-toolbar</a> qui devient vite indispensable.</p>
<p>Alors ? Elle est pas belle la vie ?</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8447&amp;md5=0c39a616337564e02ef8f370811c5c82" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8514
title: Le PEP8, en résumé
uri: Le-PEP8-en-résumé
url: http://sametmax.com/le-pep8-en-resume/
content:
<p>Internet, c&#8217;est la culture du TL;DR, donc plutôt je vais faire une petite synthèse des trucs les plus importants du <a href="http://www.python.org/dev/peps/pep-0008/#names-to-avoid">PEP8</a>, comme ça si vous avez la flemme de le lire, au moins vous aurez l&#8217;essentiel. </p>
<p>Ce texte liste les règles stylistiques recommandées, invitant toute la communauté Python à écrire un code de la même façon.</p>
<p>Je vais également y ajouter des éléments de style qui ne sont pas dedans, mais que j&#8217;ai pu constater comme étant les choix les plus courants dans les sources que j&#8217;ai pu lire.</p>
<h2>Espaces</h2>
<p>Les opérateurs doivent être entourés d&#8217;espaces.</p>
<p>Il faut faire ceci :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">variable = <span style="color: #483d8b;">'valeur'</span>
&nbsp;
ceci == cela
&nbsp;
<span style="color: #ff4500;">1</span> + <span style="color: #ff4500;">2</span></pre></div></div>

<p>Et non:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">variable=<span style="color: #483d8b;">'valeur'</span>
&nbsp;
ceci==cela
&nbsp;
<span style="color: #ff4500;">1</span>+<span style="color: #ff4500;">2</span></pre></div></div>

<p>Il y a deux exceptions notables.</p>
<p>La première étant qu&#8217;on groupe les opérateurs mathématiques ayant la priorité la plus haute pour distinguer les groupes :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">a = x<span style="color: #66cc66;">*</span><span style="color: #ff4500;">2</span> - <span style="color: #ff4500;">1</span>
b = x<span style="color: #66cc66;">*</span>x + y<span style="color: #66cc66;">*</span>y
c = <span style="color: black;">&#40;</span>a+b<span style="color: black;">&#41;</span> <span style="color: #66cc66;">*</span> <span style="color: black;">&#40;</span>a-b<span style="color: black;">&#41;</span></pre></div></div>

<p>La seconde est le signe <code>=</code> dans la déclaration d&#8217;arguments et le passage de paramètres :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> fonction<span style="color: black;">&#40;</span>arg=<span style="color: #483d8b;">'valeur'</span><span style="color: black;">&#41;</span>: <span style="color: #808080; font-style: italic;">#  ça c'est ok</span>
    <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
resultat = fonction<span style="color: black;">&#40;</span>arg=<span style="color: #483d8b;">'valeur'</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;">#  ça aussi</span></pre></div></div>

<p>On ne met pas d&#8217;espace à l&#8217;intérieur des parenthèses, crochets ou accolades.</p>
<p>Oui :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff4500;">2</span> <span style="color: #66cc66;">*</span> <span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span> + <span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> fonction<span style="color: black;">&#40;</span>arg=<span style="color: #483d8b;">'valeur'</span><span style="color: black;">&#41;</span>:
&nbsp;
<span style="color: black;">&#123;</span><span style="color: #008000;">str</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</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;">10</span><span style="color: black;">&#41;</span><span style="color: black;">&#125;</span>
&nbsp;
val = dico<span style="color: black;">&#91;</span><span style="color: #483d8b;">'key'</span><span style="color: black;">&#93;</span></pre></div></div>

<p>Non :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff4500;">2</span> <span style="color: #66cc66;">*</span> <span style="color: black;">&#40;</span> <span style="color: #ff4500;">3</span> + <span style="color: #ff4500;">4</span> <span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> fonction<span style="color: black;">&#40;</span> arg=<span style="color: #483d8b;">'valeur'</span> <span style="color: black;">&#41;</span>:
&nbsp;
<span style="color: black;">&#123;</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</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;">10</span><span style="color: black;">&#41;</span> <span style="color: black;">&#125;</span>
&nbsp;
val = dico<span style="color: black;">&#91;</span> <span style="color: #483d8b;">'key'</span> <span style="color: black;">&#93;</span></pre></div></div>

<p>On ne met pas d&#8217;espace avant les deux points et les virgules, mais après oui.</p>
<p>Oui :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> fonction<span style="color: black;">&#40;</span>arg1=<span style="color: #483d8b;">'valeur'</span>, arg2=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
&nbsp;
dico = <span style="color: black;">&#123;</span><span style="color: #483d8b;">'a'</span>: <span style="color: #ff4500;">1</span><span style="color: black;">&#125;</span></pre></div></div>

<p>Non :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> fonction<span style="color: black;">&#40;</span>arg=<span style="color: #483d8b;">'valeur'</span> , arg2=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span> :
&nbsp;
dico = <span style="color: black;">&#123;</span><span style="color: #483d8b;">'a'</span> : <span style="color: #ff4500;">1</span><span style="color: black;">&#125;</span></pre></div></div>

<h2>Lignes</h2>
<p>Une ligne doit se limiter à 79 charactères. Cette limite, héritée des écrans touts petits, est toujours en vigeur car il est plus facile de scanner un code sur une courte colonne qu&#8217;en faisant des aller-retours constant.</p>
<p>Si une ligne est trop longue, il existe plusieurs manières de la racourcir :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">foo = la_chose_au_nom_si_long_quelle_ne_tient_pas_sur<span style="color: black;">&#40;</span>
          une, 
          carte, 
          de, 
          munchkin<span style="color: black;">&#41;</span></pre></div></div>

<p>Ici l&#8217;indentation entre le nom de la fonction et des paramètres est légèrement différente pour mettre en avant la distinction.</p>
<p>Une variante :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">foo = la_chose_au_nom_si_long_quelle<span style="color: black;">&#40;</span>ne, tient, pas, sur, carte 
                                     une, de, munchkin<span style="color: black;">&#41;</span></pre></div></div>

<p>Si c&#8217;est un appel chainé, on peut utiliser <code>\</code> pour mettre à la ligne :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">queryset = ModelDjangoALaNoix.<span style="color: black;">objects</span>\
                             .<span style="color: #008000;">filter</span><span style="color: black;">&#40;</span>banzai=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>\
                             .<span style="color: black;">exclude</span><span style="color: black;">&#40;</span>chawarma=<span style="color: #008000;">False</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Si c&#8217;est une structure de données, on peut se la jouer langage fonctionel de la vibes du flex :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">chiffres = <span style="color: black;">&#91;</span>
    <span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span>,
    <span style="color: #ff4500;">4</span>, <span style="color: #ff4500;">5</span>, <span style="color: #ff4500;">6</span>,
<span style="color: black;">&#93;</span>
&nbsp;
contacts = <span style="color: black;">&#123;</span>
    <span style="color: #483d8b;">'Cleo'</span>: <span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>,
    <span style="color: #483d8b;">'Ramses'</span>: <span style="color: black;">&#40;</span>
        <span style="color: black;">&#40;</span><span style="color: #483d8b;">'maman'</span>, <span style="color: #483d8b;">'0248163264'</span><span style="color: black;">&#41;</span>,
        <span style="color: black;">&#40;</span><span style="color: #483d8b;">'papa'</span>, <span style="color: #483d8b;">'01234567890'</span><span style="color: black;">&#41;</span>,
        <span style="color: black;">&#40;</span><span style="color: #483d8b;">'mamie'</span>, <span style="color: #483d8b;">'55555555'</span><span style="color: black;">&#41;</span>,
        <span style="color: black;">&#40;</span><span style="color: #483d8b;">'momie'</span>, <span style="color: #483d8b;">'066642424269'</span><span style="color: black;">&#41;</span>
    <span style="color: black;">&#41;</span>
<span style="color: black;">&#125;</span></pre></div></div>

<p>Séparer les fonctions et les classes à la racine d&#8217;un module par 2 lignes vides. Les méthodes par 1 ligne vide. Parfois je triche et je fais 3 et 2 au lieu de 2 et 1. </p>
<p>Les imports de plusieurs modules doivent être sur plusieurs lignes :</p>

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

<p>Et non :</p>

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

<p>Bien sûr, ce n&#8217;est pas valable pour <code>from x import z</code>.</p>
<p>Souvenez-vous qu&#8217;on peut utiliser les parenthèses pour diviser de longues lignes. Par exemple :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> minibelt <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: black;">&#40;</span>dmerge, get, iget, normalize, 
                      chunks, window, skip_duplicates, flatten<span style="color: black;">&#41;</span></pre></div></div>

<p>Idem pour les chaînes très longues :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">s = <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Les chaînes Python sont automatiquement&quot;</span>
     <span style="color: #483d8b;">&quot;concaténées par la VM si elles sont &quot;</span>
     <span style="color: #483d8b;">&quot;uniquement séparées par des espaces &quot;</span>
     <span style="color: #483d8b;">&quot;ou sauts de lignes.&quot;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Pour en revenir aux lignes d&#8217;import, on doit les ordonner ainsi :</p>
<ul>
<li>Import de module > import du contenu du module</li>
<li>Import de la lib standard > import de libs tierces parties > import de votre projet</li>
</ul>
<p>Exemple :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>  <span style="color: #808080; font-style: italic;"># import module de la lib standard</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span> <span style="color: #808080; font-style: italic;"># on groupe car même type </span>
&nbsp;
<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: #808080; font-style: italic;"># import du contenu du module</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">collections</span> on namedtuple <span style="color: #808080; font-style: italic;"># import groupe car même type</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> requests <span style="color: #808080; font-style: italic;"># import lib tierce partie</span>
<span style="color: #ff7700;font-weight:bold;">import</span> arrow <span style="color: #808080; font-style: italic;"># on groupe car même type</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">conf</span> <span style="color: #ff7700;font-weight:bold;">import</span> settings <span style="color: #808080; font-style: italic;"># tierce partie, contenu du module</span>
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">shortcuts</span> <span style="color: #ff7700;font-weight:bold;">import</span> redirect <span style="color: #808080; font-style: italic;"># on groupe car même type</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> mon_projet.<span style="color: black;">mon_module</span> <span style="color: #ff7700;font-weight:bold;">import</span> ma_bite <span style="color: #808080; font-style: italic;"># mon projet</span></pre></div></div>

<h2>Format du fichier</h2>
<p>Indentation : 4 espaces. Pas de tab. C&#8217;est tout. Ce n&#8217;est pas du PEP8, c&#8217;est juste que les codes qui utilisent les tabs sont en (très très très très très très très très) grande minorité dans la communauté Python. Donc faites pas chier. Sinon on vous attend à la sortie de l&#8217;école. Tous.</p>
<p>Encoding : UTF8 ou ASCII (ce qui est de l&#8217;UTF8 de toute façon).</p>
<h2>Docstrings</h2>
<p>(c.f. <a href="http://www.python.org/dev/peps/pep-0257/">PEP257</a>)</p>
<p>On utilise toujours des triples quotes :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> fonction_avec_docstring_courte<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Résumé en une ligne.&quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">pass</span></pre></div></div>

<p>Si la docstring est longue (elle peut être très très très longue si vous le souhaitez) :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> fonction<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Résumé en une ligne suivi d'une line vide.
&nbsp;
    Description longue de la fonction qui 
    se termine par une ligne vide puis une
    triple quotes sur sa propre ligne.
&nbsp;
    &quot;&quot;&quot;</span></pre></div></div>

<h2>Noms de variables</h2>
<p>Lettres seules, en minuscule : pour les boucles et les indices.</p>
<p>Exemple :</p>

<div class="wp_syntax"><div 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> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span>
&nbsp;
i = get_index<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> + <span style="color: #ff4500;">12</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>ma_liste<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Lettres minuscules + underscores : pour les modules, variables, fonctions et méthodes.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">une_variable = <span style="color: #ff4500;">10</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> une_fonction<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;">locals</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> UneClasse:
    <span style="color: #ff7700;font-weight:bold;">def</span> une_methode_comme_une_autre<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;">globals</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Lettres majuscules + underscores : pour les (pseudo) constantes.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">MAX_SIZE = <span style="color: #ff4500;">100000</span>  <span style="color: #808080; font-style: italic;"># à mettre après les imports</span></pre></div></div>

<p>Camel case : nom de classe.</p>

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

<p>Si le nom contient un acronyme, on fait une entorse à la règle :</p>

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

<p>On n&#8217;utilise PAS le mixedCase.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8514&amp;md5=6d7faba7df4ef3dfcca63e157f006405" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8538
title: Retrait de l’article sur Rapydscript
uri: Retrait-de-l-article-sur-Rapydscript
url: http://sametmax.com/retrait-de-larticle-sur-rapydscript/
content:
<p>L&#8217;article invité sur Rapydscript a été retiré par l&#8217;auteur. Il a en effet reçu quelques remarques sur les photos entourant l&#8217;article sur la page d&#8217;accueil ^^</p>
<p>J&#8217;en profite pour rappeler que les auteurs des articles invités peuvent bien entendu retirer les articles qu&#8217;ils veulent, les éditer, et mettre un lien vers à peu près tout ce qu&#8217;ils souhaitent dedans.</p>
<p><strong>Ils n&#8217;ont aucune obligation envers nous et nous leur sommes reconnaissant d&#8217;avoir pris le temps de poster sur Sam et Max.<br />
</strong><br />
N&#8217;oubliez cependant pas que sur le blog il y aura toujours des trucs Not Safe For <del datetime="2013-12-27T16:06:47+00:00">Work</del> Anything. Donc prenez un bon pseudo et faites gaffes à ceux à qui vous passez les liens :-)</p>
<p>P.S: l&#8217;articl est bien entendu toujours disponible sur les autoblogs puisque nous n&#8217;avons pas contrôle dessus et que les articles sont publiés sous licence creative common.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8538&amp;md5=c94188536b16ebb40e3e999379e1951d" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8532
title: Les stats Sam&Max 2013
uri: Les-stats-Sam-Max-2013
url: http://sametmax.com/les-stats-sammax-2013/
content:
<p>Presque 2 ans déjà que ce blog prêche la bonne parole aux brebis égarées ici bas. Comme tout webmaster qui se respecte on adore les stats alors on va se faire un petit résumé de l&#8217;année 2013 dans la joie et la bonne humeur. On avait déjà publié <a href="http://sametmax.com/sam-et-max-en-quelques-chiffres/">quelques stats ici</a> d&#8217;ailleurs l&#8217;été dernier.</p>
<p>Pour info sur l&#8217;année 2012 le blog totalisait 244,183 visites.</p>
<p><strong>Petit récap année 2013:</strong></p>
<p><strong>Date de création</strong>: 4 février 2012<br />
<strong>Visites pour l&#8217;année 2013:</strong> 1,173,671<br />
<strong>Visites depuis la création du blog:</strong> 1,417,854<br />
<strong>Nombre de posts:</strong> 323<br />
<strong>Nombre de commentaires:</strong> 5967</p>
<p><strong>Qui nous envoi du monde ?</strong><br />
<code><br />
Search Engines                  <strong>481,053</strong><br />
Twitter                         <strong>20,139</strong><br />
news.humancoders.com			<strong>9,702</strong><br />
sebsauvage.net					<strong>8,837</strong><br />
Facebook						<strong>6,072</strong><br />
Netvibes						<strong>4,727</strong><br />
multiboards.net					<strong>4,465</strong><br />
google.fr						<strong>1,366</strong><br />
macg.co							<strong>1,257</strong><br />
search.free.fr					<strong>1,129</strong><br />
Google Reader					<strong>897</strong><br />
Google+							<strong>837</strong><br />
lehollandaisvolant.net			<strong>678</strong></code></p>
<p><strong>Par quels mots-clefs les gens sont arrivés ici ?</strong><br />
(Comme il y en a trop la liste est volontairement tronquée)<br />
<code><br />
masturbation feminine	<strong>19,981</strong><br />
masturbation féminine	<strong>8,896</strong><br />
fkk<strong>	6,504</strong><br />
masturbation	<strong>6,362</strong><br />
video masturbation	<strong>3,789</strong><br />
masturbation video	<strong>3,272</strong><br />
masturbation femme	<strong>2,403</strong><br />
maison close allemagne	<strong>2,105</strong><br />
freeplug	<strong>1,904</strong><br />
synchroniser freeplug	<strong>1,641</strong><br />
video masturbation feminine	<strong>1,427</strong><br />
masturbation feminine video	<strong>1,328</strong><br />
sam et max	<strong>1,197</strong><br />
fkk allemagne	<strong>1,118</strong><br />
synchronisation freeplug	<strong>965</strong><br />
sex japon	<strong>868</strong><br />
sexe japonais	<strong>813</strong></code></p>
<p><strong>Les posts les plus vus:</strong><br />
<code><br />
Home page / Archives	<strong>268,964</strong><br />
Masturbation féminine – Un peu de théorie en vidéo	<strong>160,715</strong><br />
Une journée dans un FKK (maison close Allemande)	<strong>65,974</strong><br />
Synchroniser les freeplugs (les adaptateurs réseaux CPL de free)	<strong>	43,321</strong><br />
Les abréviations de la prostitution et des Escorts, vous connaissez ?	<strong>33,502</strong><br />
Les Japonais et le sexe – des gros malades… Ou pas…	<strong>17,011</strong><br />
Les émoticones cachées de Skype	<strong>15,244</strong><br />
Il ne faut pas prendre les gens pour des cons mais ne jamais oublier qu’ils en sont	<strong>14,666</strong><br />
10 astuces pour Sublime Text 2	<strong>12,716</strong><br />
Ajouter un chemin à la variable d’environnement PATH sous Windows	<strong>9,309</strong><br />
Les articles pour apprendre Python, dans le bon ordre :-)	<strong>8,188</strong><br />
Liste des plugins sublime text que j’utilise	<strong>7,514</strong><br />
Cours et tutos	<strong>6,415</strong><br />
L’encoding en Python, une bonne fois pour toute	<strong>5,532</strong><br />
Les environnements virtuels Python : virtualenv et virtualenvwrapper	<strong>5,423</strong><br />
Entreprendre en France, Autopsie d’un échec.	<strong>5,204</strong><br />
Bitcoin: créer un portefeuille, obtenir des bitcoins et payer	<strong>5,138</strong><br />
La fonction anonyme appelée immédiatement en Javascript: (function())()	<strong>4,933</strong><br />
Mettre la capote sans casser l’ambiance	<strong>4,333</strong><br />
Nos tweets	<strong>4,137</strong><br />
Qu’est-ce que Javascript et à quoi ça sert ?	<strong>4,073</strong><br />
Soyez relax, faites vous un petit Git stash	<strong>3,976</strong><br />
Tiens, je suis toujours sur OSX	<strong>3,891</strong><br />
Comment tailler une pipe	<strong>3,786</strong><br />
Qu’est-ce qu’on peut faire avec Python ?	<strong>3,705</strong><br />
Votre Python aime les pip	<strong>3,688</strong><br />
Qu’est-ce que bitcoin ?	<strong>3,609</strong></code></p>
<p>Flattr nous rapporte un peu de pognon mais j&#8217;ai pas les stats actuellement (c&#8217;est sam qui tiens les bourses&#8230;). On s&#8217;en est toujours pas servi je crois d&#8217;ailleurs.</p>
<p>Cela nous fait quand même à peu près 1 200 000 visites dans l&#8217;année. Comprenez que des fois ce petit VPS avec 512MO de RAM que nous louons soit un peu essouflé.</p>
<p>Passez de bonnes fêtes ou ouvrez-vous bien les veines (toujours dans le sens des fibres)</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8532&amp;md5=16fccb7db56493162ca244eb19084c9a" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8572
title: Sam on the road again
uri: Sam-on-the-road-again
url: http://sametmax.com/sam-on-the-road-again/
content:
<p>Je vous laisse, j&#8217;ai des km à parcourir.</p>
<p>Retour dans une ou deux semaines.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8572&amp;md5=619ade70417b4220608ab0d6cb5d5bdd" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8764
title: Un gros guide bien gras sur les tests unitaires en Python, partie 1
uri: Un-gros-guide-bien-gras-sur-les-tests-unitaires-en-Python-partie-1
url: http://sametmax.com/un-gros-guide-bien-gras-sur-les-tests-unitaires-en-python-partie-1/
content:
<p>La zik maintenant traditionelle :</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="560" height="315" src="//www.youtube.com/embed/1pm4fQRl72k" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<p>Les tests unitaires font partie de ces &#8220;bonnes pratiques&#8221; que tout le monde semble appliquer sur le net. Tous les devs hypes parlent de tests unitaires : les conférences, les blogs, les tutos, les livres, whooooo !</p>
<p>Dans la vraie vie vivante, on croise pourtant peu de gens qui les utilisent vraiment. On les retrouvent surtout dans les gros projets et les grosses boîtes, et encore.</p>
<p>Il y a plusieurs raisons à cela. D&#8217;une part, beaucoup, beaucoup, beaucoup de développeurs n&#8217;ont aucune idée de ce qu&#8217;est un test unitaire. Ceux qui savent, ne voient pas forcément l’intérêt, et ceux qui en voient l’intérêt n&#8217;ont pas forcément l&#8217;expérience nécessaire à leur mise en œuvre.</p>
<p>Je connais des tas de dev qui codent des tas d&#8217;excellents projets sans le moindre test unitaires.</p>
<p>L&#8217;adage selon lequel un code sans test unitaire est un code buggé est parfaitement faux puisque existe bien d&#8217;autres manières de tester son code. De plus, même un code bien testé est un code buggé. Je le sais, je l&#8217;ai codé.</p>
<p>Malgré cela, vous devriez maitriser l&#8217;usage des tests unitaires, car quand vous arrivez à vous sortir les extrémités digitales de la terminaison dorsale afin de les mettre en place, le bénéfice est très important. Mais aussi parce que certains projets ne peuvent pas s&#8217;en passer, et donc que vous ne pourrez pas travailler dessus sans savoir en faire. Certains projets sur Github n&#8217;acceptent pas de pull request sans couverture de tests, et certaines personnes n&#8217;utiliseront pas votre lib si elle n&#8217;est pas testée. C&#8217;est un gage de qualité.</p>
<p>Je n&#8217;en ferai pas une question morale ou de principe, les projets que l&#8217;on publie sur Sam et Max sont parfaitement exempt de tests unitaires, et d&#8217;ailleurs, la plupart des projets pros avec Max n&#8217;ont aucun tests non plus.</p>
<p>En revanche, en tant que freelance, je prends généralement le temps d&#8217;en faire.</p>
<p>Pas de dogmatisme du test donc, mais passé le goût de crabe dans la bouche, ça vaut le coup, alors lisez ce guide.</p>
<h2>Qu&#8217;est-ce qu&#8217;un test unitaire</h2>
<p>Le test unitaire est un bout de code qui fait exactement ce que son nom dit : il teste une unité de code.</p>
<p>Le problème c&#8217;est quoi tester, qu&#8217;est-ce qu&#8217;une &#8220;unité de code&#8221;, ce n&#8217;est pas quelque chose d&#8217;évident à définir, et vient avec la pratique. En théorie c&#8217;est un bout de code minimaliste, que l&#8217;on ne peut pas réduire plus. En pratique, on choisit avec pragmatisme un truc assez petit, mais pas trop, parce que merde, hein.</p>
<p>Mais alors que veut-on dire par &#8220;tester&#8221; ?</p>
<p>Et bien c&#8217;est d&#8217;une banalité affligeante : on donne des entrées au code, et on vérifie que ses sorties sont celles attendues pour ces entrées.</p>
<p>Bref, généralement (mais pas toujours) on teste une fonction. Souvent avec une autre fonction. Et c&#8217;est d&#8217;un manque d&#8217;originalité terrible.</p>
<p>Le test unitaire le plus bête qu&#8217;on puisse avoir en Python :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># Fichier de code</span>
<span style="color: #ff7700;font-weight:bold;">def</span> fonction_a_tester<span style="color: black;">&#40;</span>param1, param2<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> param1 + param2</pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># Fichier de test</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> fichier_de_code <span style="color: #ff7700;font-weight:bold;">import</span> fonction_a_test
&nbsp;
<span style="color: #ff7700;font-weight:bold;">assert</span> fonction_a_tester<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span> == <span style="color: #ff4500;">2</span>  <span style="color: #808080; font-style: italic;"># test de l'addition</span>
<span style="color: #ff7700;font-weight:bold;">assert</span> fonction_a_tester<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, -<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span> == <span style="color: #ff4500;">0</span> <span style="color: #808080; font-style: italic;"># test avec chiffre négatif</span>
<span style="color: #ff7700;font-weight:bold;">assert</span> fonction_a_tester<span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span>, <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span> == <span style="color: #ff4500;">6</span> <span style="color: #808080; font-style: italic;"># test avec autre chose que des 1</span>
<span style="color: #ff7700;font-weight:bold;">assert</span> fonction_a_tester<span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span>., <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span> == <span style="color: #ff4500;">6</span>. <span style="color: #808080; font-style: italic;"># test avec des floats</span></pre></div></div>

<p>Deux constats :</p>
<ul>
<li>C&#8217;est parfaitement chiant. Les tests unitaires sont dans 99% des cas des tautologiques super ennuyeuses.</li>
<li>On teste le même code plusieurs fois, avec plusieurs cas de figure, pour être certain que ça se comporte comme prévu.</li>
</ul>
<p><code>assert</code> est un mot clé qui lève l&#8217;exception <code>AssertionError</code> quand l&#8217;expression évaluée ne retourne pas <code>True</code>. L&#8217;utilisation d&#8217;<code>assert</code> n&#8217;est pas le sujet de l&#8217;article, ici on s&#8217;en sert pour faire un test unitaire tout simplement parce que la première ligne qui ne renverra pas <code>True</code> fera  planter le programme. C&#8217;est le test unitaire du pauvre.</p>
<p>Un test unitaire, ce n&#8217;est que ça. Un répétition bête et emmerdante de vérifications généralement très connes.</p>
<h2>C&#8217;est minable ! A quoi ça sert ?</h2>
<p>Là normalement vous vous dites &#8220;je sais ce que fait mon code, surtout une unité minimaliste, je n&#8217;ai pas besoin d&#8217;écrire des évidences pour le tester&#8221;. Et c&#8217;est pour cela que je ne suis pas dogmatique sur les tests unitaires, car c&#8217;est en partie vrai. Beaucoup de codes sont suffisamment simples ou peu critiques pour ne pas avoir besoin d&#8217;être renforcés par des tests unitaires. Et même si il faut des tests, tout le code n&#8217;a pas nécessairement besoin d&#8217;être testé.</p>
<p>Lancer un blog pour sa cousine n&#8217;est pas la même chose qu&#8217;une site de rencontre pour un grand compte.</p>
<p>Mais le test unitaire a plusieurs bénéfices. Le premier c&#8217;est qu&#8217;il vous oblige à réfléchir aux entrées et sorties de vos fonctions, et à l&#8217;API de votre code en général. Vous vous apercevrez à l&#8217;usage qu&#8217;un code est plus ou moins facile à tester selon la manière dont vous l&#8217;avez organisé, et ce faisant, vous serez forcé d&#8217;écrire un code plus souple, propre, extensible.</p>
<p>Écrire des tests fait de vous un meilleur développeur.</p>
<p>Cependant ce n&#8217;est pas le principal intérêt. Le véritable gain tient dans ce que vous gagnez dans le futur : quand vous allez modifier votre code, vous pourrez rapidement voir si il n&#8217;est pas cassé. En effet, votre code va grossir, et vous ne vous souviendrez pas de toutes les dépendances, de tous les effets de bords, de toutes les interactions. Certains dev sont meilleurs que d&#8217;autres à tout garder dans la tête, mais même Cortex a ses limites. Au bout d&#8217;un moment, le code est plus fort que vous.</p>
<p>À partir de là, vous allez tout de même avoir besoin de factoriser le code, bouger des choses, en ajouter d&#8217;autres, corriger un bug, faire un petit ajustement. À chaque fois que vous le faites, vous prenez le risque de casser un truc. Au début du projet, le risque est faible, et même si ça arrive, ça se répare vite. Après 2 mois de dev, les tests seront votre filet de sécurité. Vous pouvez les lancer après chaque modif, et voir que vous n&#8217;avez rien pété. Vous pouvez les lancer après une contribution d&#8217;un autre dev, et voir que ça tourne toujours. Vous pouvez les lancer après un changement d’environnement (OS, base de données, système de fichier, format, etc) et vous assurer que ça n&#8217;a pas d’impacts.</p>
<p>Particulièrement, des tests unitaires ont beaucoup de valeur sur un projet avec beaucoup de participants, tels que des logiciels libres populaires ou des systèmes de grandes sociétés.</p>
<p>Par exemple, sur notre dernière fonction bidon, on décide de faire une petite modification :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># Fichier de code</span>
<span style="color: #ff7700;font-weight:bold;">def</span> fonction_a_tester<span style="color: black;">&#40;</span>param1, param2<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>param1<span style="color: black;">&#41;</span> + <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>param2<span style="color: black;">&#41;</span></pre></div></div>

<p>On peut maintenant passer une string, et elle sera convertie en entier.</p>
<p>On lance notre batterie de tests, et là, au milieu de centaines d&#8217;autres tests, celui là foire :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">assert</span> fonction_a_tester<span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span>., <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span> == <span style="color: #ff4500;">6</span>. <span style="color: #808080; font-style: italic;"># test avec des floats</span></pre></div></div>

<p>On voit très vite que notre idée était pourrie, car on a un use case qui ne sera plus compatible. Si quelqu&#8217;un a utilisé des floats avec notre fonction, on va casser son code.</p>
<p>En l&#8217;essence, c&#8217;est ça l’intérêt des tests unitaires : vous faire sauter au yeux quand quelque chose casse. On appelle ça des &#8220;tests de régression&#8221;, et c&#8217;est l&#8217;usage le plus courant.</p>
<p>Plus tard vous verrez qu&#8217;on utilise aussi les tests pour développer son code (TDD), pour définir un comportement du produit avec le client (BDD) ou tout simplement pour servir de documentation.</p>
<p>Mais l&#8217;usage de base, c&#8217;est ça. S&#8217;assurer qu&#8217;on est pas en train de merder.</p>
<h2>Résumé</h2>
<ol>
<li>N&#8217;écoutez pas les Papes du test vous disant que si vous n&#8217;avez pas des tests unitaires à 50 ans, vous avez raté votre vie. Les tests, c&#8217;est bien. Un projet livré, c&#8217;est mieux. Une documentation est plus importante que des tests. Les 3, évidement, c&#8217;est l&#8217;idéal.</li>
<li>Un test, c&#8217;est une suite parfaitement chiante d&#8217;énonciations d&#8217;évidences. Il n&#8217;y a généralement rien de compliqué dans les tests. Vous vous sentirez parfois insulté en les écrivant tellement c&#8217;est con.</li>
<li>L’intérêt majeur des tests est d&#8217;avoir une alerte rouge qui se lance quand vous avez pété un truc. Ça arrive bien plus souvent que vous ne le croyez sans que vous ne vous en aperceviez car vous n&#8217;avez pas de tests.</li>
</ol>
<p>Ces bases posées, la prochaine partie fera la démonstration du module <a href="http://docs.python.org/2/library/unittest.html">unittest</a> afin de créer vos premiers tests unitaires en Python, puis on enchaînera, partie par partie, sur les applications pratiques, les variantes, les girafes lesbiennes et tout ce qui fait un bon article de s&#038;m.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8764&amp;md5=ca05e3d293406df04c3c71bb017b88a4" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8772
title: Importer des données, retour d’expérience
uri: Importer-des-données-retour-d-expérience
url: http://sametmax.com/importer-des-donnees-retour-dexperience/
content:
<p>Dédicaçons la chanson de notre article au plus barbu de mes amis poneys.</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="560" height="315" src="//www.youtube.com/embed/9wrVTYMGTao" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<p>J&#8217;ai importé des données un très grand nombre de fois dans ma vie. Depuis des APIs, des XML, des CSV, du filesystem, des formats binaires, des formats batards, etc</p>
<p>Pour tous les jobs d&#8217;import, Python est probablement le meilleur langage au monde. Autant j&#8217;aime Python, autant je suis lucide sur le fait qu&#8217;en dev Web, Ruby et Javascript sont d&#8217;excellentes alternatives. En programmation concurrente, Go dépasse Python. En IA, Lisp est le top de la concurrence.</p>
<p>Mais pour l&#8217;import de données, Python est simplement le meilleur langage au monde. Sa capacité à lire énormément de formats facilement, sa force de manipulation de données numériques et texte, sa philosophie d&#8217;itération, ses nombreuses libs en font un outil incroyablement souple et puissant.</p>
<p>Malgré cela, on retrouve toujours des grosses difficultés dans l&#8217;import de données. Elles sont les mêmes pour tous les langages.</p>
<p>Voici mes 2 centimes.</p>
<h2>N&#8217;accordez aucune confiance à la donnée</h2>
<p>Partez du principe que tout champ peut manquer. Que toute donnée peut être mal formée ou corrompue. Ou fausse.</p>
<p>Même si le service en face est sérieux. J&#8217;ai bossé avec des données du service de santé américain, de France Télécom, de startups, d&#8217;outils Open Source, de scrapping de sites, de mon pote Maurice, et de mes propres scripts</p>
<p>Vous savez ce qu&#8217;ils ont tous en commun ? Aucun ne sont fiables. Aucun.</p>
<p>Ils ont tous des données merdiques à un moment où à un autre.</p>
<p>Ayez donc une approche défensive. Pour CHAQUE champ, posez vous la question : que doit faire le script d&#8217;import si il manque ? Si la donnée contenue est foireuse ?</p>
<h2>Les outils d&#8217;abstraction sont vos amis</h2>
<p>Un import, c&#8217;est typiquement le genre de taff où les surcouches vont énormément vous aider. ORM, DSL, XML objectify et toute lib qui peut vous éviter de travailler trop proche du format va vous faire gagner un temps fou.</p>
<p>Prenez un peu de temps pour les mettre en place. Même si ils vous font perdre un peu en perf, un gros script d&#8217;import devient TRÈS VITE un sac de nœud. Et vous voulez que les problèmes soient facilement identifiables.</p>
<p>Pour cette même raison, virez toute la logique de l&#8217;insertion des données en dehors du script. Votre script doit avoir une logique découpée en 3 parties :</p>
<ol>
<li>Le script d’acquisition, qui charge les données et les passe sous forme brute à un importeur.</li>
<li>Un importeur, qui est capable d&#8217;extraire des données raffinées à partir d&#8217;un format de données brutes et appeler le bon code d&#8217;insertion.</li>
<li>Du code d&#8217;insertion, qui attend en paramètre une donnée toujours propre (sans aucun check), et qui se charge uniquement de prendre cette donnée et la mettre dans votre système de stockage (généralement la base de données).</li>
</ol>
<p>Le script d’acquisition doit rester très simple. Une suite d&#8217;instructions logiques pour récupérer la donnée, l&#8217;énumérer et la passer à l&#8217;importeur. C&#8217;est lui qui fait les appels API, qui se connecte au FTP, qui ouvre le CSV, qui parse le XML, etc. Ainsi vous pouvez facilement interchanger les importeurs ou voir si il y a une couille dans la récupération des données.</p>
<p>L&#8217;importeur est généralement le code le plus crade. C&#8217;est une série de <code>try</code> / <code>except</code>, de logique métier, d&#8217;assainissement des données. Vous ne voulez pas de code d&#8217;insertion là dedans, car vous voulez que ce code, qui est difficile à débugger et va être celui qui va être modifié toutes les 5 minutes au fur et à mesure que vous découvrez toute les merdes, soit dédié à une seule logique : obtenir de la donnée saine. Ce code sera spaghetti, vous n&#8217;y pouvez rien. Mais vous pouvez l&#8217;isoler et le commenter à mort.</p>
<p>Le code d&#8217;insertion est un code réutilisable. Il se fout de savoir d&#8217;où vient la donnée. Il attend un format, et un seul, et toujours de données correctes, et propres. C&#8217;est le but des importeurs de lui filer une entrée normalisée et pertinente. Ce code est propre, et doit être très bien testé via des tests unittaires. Il va vous servir plusieurs fois, car c&#8217;est le même code qui sera utilisé que vous importiez d&#8217;un service X ou un service Y. Il représente VOTRE logique métier. N&#8217;insérez pas ce code dans le code d&#8217;une autre abstraction (type ORM), ainsi, si vous changez d&#8217;outils, vous changez simplement ce code, et l&#8217;interface reste la même pour vos importeurs.</p>
<h2>Debugging</h2>
<p>Votre script va planter. Beaucoup. Souvent.</p>
<p>Un champ absolument indispensable &#8211; que la spec papier notait comme toujours présent &#8211; va manquer. Un autre champ noté de type int dans le xld contient une lettre. L&#8217;encoding n&#8217;est pas le bon, alors qu&#8217;il l&#8217;a toujours été pendant 5 mois.</p>
<p>Ce n&#8217;est pas une question de si, c&#8217;est une question de quand.</p>
<p>Donc déjà, blindez votre script de <a href="http://sametmax.com/ecrire-des-logs-en-python/">log</a>. Quand je dis blindez, je veux dire que chaque <code>if</code>, chaque résultat de check, doit être accompagné d&#8217;une ligne affichant l&#8217;action en cours, et son contexte (la donnée traitée, de préférence avec un truc pour l&#8217;identifier, genre un ID). Quand il plantera à 3 heure du matin sur un truc hubuesque et que le relancer pour obtenir le même état prendra une demi-journée, le log sera votre seul chance de réparer la panne sans engager un psy.</p>
<p>Mettez aussi un gros <code>try / except</code> générique qui loggue toute exception, pour pouvoir faire un debug post mortem. Idéalement, faites le dumper <code>locals()</code> et envoyez-vous un mail d&#8217;alerte. Vous ne voulez pas que le script ne tourne pas pendant une journée sans que vous le sachiez.</p>
<p>Mettez des options dans votre scripts pour pouvoir débugger plus facilement. Par exemple, si vous avez de code d&#8217;insertion qui est sous forme de tâche asynchrone (type <a href="http://sametmax.com/files-de-taches-et-taches-recurrentes-avec-celery/">celery</a>), mettez une option <code>--synchronous</code> qui insère le code inline afin de pouvoir utiliser <a href="http://sametmax.com/debugger-en-python-les-bases-de-pdb/">pdb</a> sur tout le script en cas de besoin. Ou alors, si vous avez une grosse archive à décompresser, mettez une option <code>--nozip</code> pour pouvoir sauter cette étape.</p>
<p>Et si vous insérez un break point, mettez le dans une condition du genre :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">if</span> id_du_champ_ou_autre_moyen_identifiant == <span style="color: #483d8b;">&quot;valeur&quot;</span>:
    send_mail<span style="color: black;">&#40;</span><span style="color: #483d8b;">'Alerte, on est peut être au bug. Bouge ton fion.'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">import</span> ipdb<span style="color: #66cc66;">;</span> ipdp.<span style="color: black;">set_trace</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Comme ça vous pouvez retourner à vos moutons le temps que le breakpoint s&#8217;active, ce qui, sur des gros jeux de données, peut prendre énormément de temps.</p>
<p>Enfin, je sais qu&#8217;on a tendance à être fainéant et vouloir toujours débugger en direct. Mais faites des mocks. Faites un faux XML, une API bidon, bref, un truc qui vous permet d&#8217;insérer des cas d&#8217;import avec une données dans le format attendu, et testez votre code avec ça. Pour les petits imports, c&#8217;est une perte de temps, mais pour les gros imports, ça va vous faire gagner des jours. Ainsi vous pouvez tester des cas isolé, rajouter des bugs rencontrés, etc. Et en plus ça sert de documentation.</p>
<h2>Problèmes courants</h2>
<p>Il y a mille et une manière d&#8217;avoir un import qui plante, mais il y a généralement 6 grosses foirades qu&#8217;on retrouve tout le temps.</p>
<h3>Service défaillant</h3>
<p>Le service (FTP, API, humain en face, NAS, etc) qui doit vous fournir les données est indisponible. Vous n&#8217;y pouvez rien. Envoyez-vous un SMS pour vous prévenir, aujourd&#8217;hui <a href="http://www.twilio.com/">c&#8217;est facile et ça coûte presque rien</a>. Ainsi vous pourrez dialoguer rapidement avec les personnes responsables de problème.</p>
<h3>Champs manquants</h3>
<p>Grand classique. Tout champ peut manquer. Tout. Même un ID unique sans lequel la donnée n&#8217;a aucune sens. Faites vous un wrapper du genre :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> get_data<span style="color: black;">&#40;</span>champ<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        <span style="color: #808080; font-style: italic;"># extraire le champ</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> ChampAbsent, ChampMalFormé:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">None</span></pre></div></div>

<p>Et utilisez le partout. Et décidez ce que doit faire votre programme si il rencontre <code>None</code>. Pour TOUS les champs. Si <code>None</code> est une valeur possible, utilisez <code>Ellipsis</code>. Si <code>Ellipsis</code> est une valeur possible, faites vous une classe <code>InvalidData</code>.</p>
<h3>Mauvais encoding</h3>
<p>Super vicieux. Je vous renvoie à <a href="http://sametmax.com/lencoding-en-python-une-bonne-fois-pour-toute/">l&#8217;article sur l&#8217;encoding</a> pour cela.</p>
<h3>Donnée aberrante</h3>
<p>Impossible à prévoir, très difficile à identifier. Donnée de mauvais type, date ou nombre hors limites, texte dans la mauvaise langue, etc. Vous ne pouvez pas tout prévoir. Pour ça, il faudra faire au fur et à mesure des plantages.</p>
<h3>Données mal formatée et malicieuses</h3>
<p>En plus de <code>get_data</code>, il vous faut un <code>clean_data</code>. Qui check si on peut processer la donnée sereinement. Pour tous les champs également. C&#8217;est con, mais si LEUR système n&#8217;escape pas les entrées utilisateurs, c&#8217;est VOTRE système dans lequel se retrouve les injections de code.</p>
<h2>Performances</h2>
<p>La vitesse de votre script sera généralement limitée par 3 facteurs :</p>
<ul>
<li>Vitesse de lecture.</li>
<li>Vitesse d&#8217;écriture.</li>
<li>Vos plantages.</li>
</ul>
<p>Ces 3 facteurs sont en général très liés.</p>
<p>La meilleur stratégie, c&#8217;est d&#8217;extrapoler un max de données, et de cacher tout ce qui est cacheable. Par exemple, copiez les données brutes sur vos serveurs (genre si c&#8217;est un fichier sur le leur). Copiez les références externes, même si vous n&#8217;en avez pas besoin afin d&#8217;éviter une query de plus, vous les supprimerez plus tard. Pré-calculez les champs, par exemple age, si vous avez la date de naissance, etc.</p>
<p>Si vous avez beaucoup de checks à faire pour l&#8217;assainissement des données, mettez vos données en cache (par exemple dans redis), pour que les looks up soient rapides, ou au moins, ajoutez les index qui vont bien dans la DB (on peut avoir des perfs X10 rien qu&#8217;avec ça).</p>
<p>Ensuite, partez du principe que ça va planter souvent, donc :</p>
<ul>
<li>Faites des opérations <a href="https://fr.wikipedia.org/wiki/Idempotent">idempotentes</a>, c&#8217;est à dire qu&#8217;on peut les relancer autant de fois qu&#8217;on veut sans risque. Typiquement, vérifiez si une donnée existe avant l&#8217;insertion, et si oui, faites une mise à jour complète.</li>
<li>Mettez un historique. Sauvegardez quelque part l&#8217;avancement de votre import, afin de ne pas tout recommencer depuis le début après le plantage.</li>
</ul>
<p>Ah oui, et faites des copies de sauvegarde des données brutes ET des données importées. Pour les premières, parce qu&#8217;on est pas à l&#8217;abri un &#8220;rm -fr&#8221; malencontreux. Ne rigolez pas, ça m&#8217;est arrivé la semaine dernière. Une semaine à tout DL à nouveau. Pour les secondes, parce que tant que le dernier import n&#8217;est pas terminé, on peut toujours corrompre toute sa base avec une couille de dernière minute. Comme un encoding qui change aléatoirement sur une donnée non datée.</p>
<h2>Bon sens</h2>
<p>Évidement, je parle ici d&#8217;un synthèse des problématiques rencontrées. Vous ne pouvez pas appliquer TOUT ça, ou en tout cas, pas au début, ou pas sur des petits scripts, etc. Selon le sérieux de votre source de données, il faudra plus ou moins être défensif. L&#8217;expérience et la douleur vous permettra de trouver la juste dose de morphine.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8772&amp;md5=a75ae119cce37f84e878f3157e64968a" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8781
title: En attendant asyncio
uri: En-attendant-asyncio
url: http://sametmax.com/en-attendant-asyncio/
content:
<p>La programmation asynchrone arrive en force avec la version 3.4, mais celle-ci n&#8217;est pas encore en version stable. En attendant, Python 3 possède déjà de quoi faire de la programmation asynchrone, et même parallèle, avec une bien plus grande facilité qu&#8217;en Python 2.</p>
<p>Si vous avez oublié le principe ou l’intérêt de la programmation asynchrone, <a href="http://sametmax.com/la-difference-entre-la-programmation-asynchrone-parallele-et-concurrente/">il y a un article pour ça</a> ©.</p>
<p>Pour montrer l’intérêt de la chose, nous allons utiliser un bout de code pour télécharger le code HTML de pages Web.</p>
<h2>Sans programmation asynchrone</h2>
<p>Le code est simple et sans chichi :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">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
&nbsp;
start_time = <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>
&nbsp;
URLS = <span style="color: black;">&#91;</span><span style="color: #483d8b;">'http://sebsauvage.net/'</span>,
        <span style="color: #483d8b;">'http://github.com/'</span>,
        <span style="color: #483d8b;">'http://sametmax.com/'</span>,
        <span style="color: #483d8b;">'http://duckduckgo.com/'</span>,
        <span style="color: #483d8b;">'http://0bin.net/'</span>,
        <span style="color: #483d8b;">'http://bitstamp.net/'</span><span style="color: black;">&#93;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> url <span style="color: #ff7700;font-weight:bold;">in</span> URLS:
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        <span style="color: #808080; font-style: italic;"># j'ignore volontairement toute gestion d'erreur évoluée</span>
        result = urlopen<span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'%s page: %s bytes'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>url, <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>result<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">Exception</span> <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;">'%s generated an exception: %s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>url, e<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
elsapsed_time = <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> - start_time
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Elapsed time: %ss&quot;</span> <span style="color: #66cc66;">%</span> elsapsed_time.<span style="color: black;">total_seconds</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Ce qui nous donne:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">python sans_future.py
http:<span style="color: #000000; font-weight: bold;">//</span>sebsauvage.net<span style="color: #000000; font-weight: bold;">/</span> page: <span style="color: #000000;">9036</span> bytes
http:<span style="color: #000000; font-weight: bold;">//</span>github.com<span style="color: #000000; font-weight: bold;">/</span> page: <span style="color: #000000;">12582</span> bytes
http:<span style="color: #000000; font-weight: bold;">//</span>sametmax.com<span style="color: #000000; font-weight: bold;">/</span> generated an exception: HTTP Error <span style="color: #000000;">502</span>: Bad Gateway
http:<span style="color: #000000; font-weight: bold;">//</span>duckduckgo.com<span style="color: #000000; font-weight: bold;">/</span> page: <span style="color: #000000;">8826</span> bytes
http:<span style="color: #000000; font-weight: bold;">//</span>0bin.net<span style="color: #000000; font-weight: bold;">/</span> page: <span style="color: #000000;">5551</span> bytes
http:<span style="color: #000000; font-weight: bold;">//</span>bitstamp.net<span style="color: #000000; font-weight: bold;">/</span> page: <span style="color: #000000;">51996</span> bytes
Elapsed <span style="color: #000000; font-weight: bold;">time</span>: 25.536095s</pre></div></div>

<p>Erreur 500 sur S&#038;M&#8230; Mon script qui se fout de ma gueule en plus&#8230;</p>
<h2>Avec programmation asynchrone</h2>
<p>On utilise le module <a href="http://docs.python.org/3.2/library/concurrent.futures.html">future</a>, qui, comme sont nom l&#8217;indique, implémente des outils pour manipuler des &#8220;futures&#8221; en Python. Il inclut notamment un context manager pour créer, lancer et arrêter des workers automatiquement, et leur envoyer des tâches, puis récupérer les résultats de ces tâches sous forme de &#8220;futures&#8221;.</p>
<p>Pour rappel, une &#8220;future&#8221; est juste un objet qui représente le résultat d&#8217;une opération asynchrone (puisqu&#8217;on ne sait pas quand elle se termine). Cet objet contient des méthodes pour vérifier si le résultat est disponible à un instant t, et obtenir ce résultat si c&#8217;est le cas.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">datetime</span>
<span style="color: #ff7700;font-weight:bold;">import</span> concurrent.<span style="color: black;">futures</span>
&nbsp;
<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;">from</span> concurrent.<span style="color: black;">futures</span> <span style="color: #ff7700;font-weight:bold;">import</span> ProcessPoolExecutor, as_completed
&nbsp;
start_time = <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>
&nbsp;
URLS = <span style="color: black;">&#91;</span><span style="color: #483d8b;">'http://sebsauvage.net/'</span>,
        <span style="color: #483d8b;">'http://github.com/'</span>,
        <span style="color: #483d8b;">'http://sametmax.com/'</span>,
        <span style="color: #483d8b;">'http://duckduckgo.com/'</span>,
        <span style="color: #483d8b;">'http://0bin.net/'</span>,
        <span style="color: #483d8b;">'http://bitstamp.net/'</span><span style="color: black;">&#93;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> load_url<span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
        Le callback que vont appeler les workers pour télécharger le contenu
        d'un site. On peut appeler cela une 'tâche'
    &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> urlopen<span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Un pool executor est un context manager qui va automatiquement créer des</span>
<span style="color: #808080; font-style: italic;"># processus Python séparés et répartir les tâches qu'on va lui envoyer entre</span>
<span style="color: #808080; font-style: italic;"># ces processus (appelés workers, ici on en utilise 5).</span>
<span style="color: #ff7700;font-weight:bold;">with</span> ProcessPoolExecutor<span style="color: black;">&#40;</span>max_workers=<span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> e:
&nbsp;
    <span style="color: #808080; font-style: italic;"># On e.submit() envoie les tâches à l'executor qui les dispatch aux</span>
    <span style="color: #808080; font-style: italic;"># workers. Ces derniers appelleront &quot;load_url(url)&quot;. &quot;e.submit()&quot; retourne</span>
    <span style="color: #808080; font-style: italic;"># une structure de données appelées &quot;future&quot;, qui représente  un accès au</span>
    <span style="color: #808080; font-style: italic;"># résultat asynchrone, qu'il soit résolu ou non.</span>
    futures_and_url = <span style="color: black;">&#123;</span>e.<span style="color: black;">submit</span><span style="color: black;">&#40;</span>load_url, url<span style="color: black;">&#41;</span>: url <span style="color: #ff7700;font-weight:bold;">for</span> url <span style="color: #ff7700;font-weight:bold;">in</span> URLS<span style="color: black;">&#125;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># &quot;as_completed()&quot; prend un iterable de future, et retourne un générateur</span>
    <span style="color: #808080; font-style: italic;"># qui itère sur les futures au fur et à mesures que celles</span>
    <span style="color: #808080; font-style: italic;"># ci sont résolues. Les premiers résultats sont donc les premiers arrivés,</span>
    <span style="color: #808080; font-style: italic;"># donc on récupère le contenu des sites qui ont été les premiers à répondre</span>
    <span style="color: #808080; font-style: italic;"># en premier, et non dans l'ordre des URLS.</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> future <span style="color: #ff7700;font-weight:bold;">in</span> as_completed<span style="color: black;">&#40;</span>futures_and_url<span style="color: black;">&#41;</span>:
&nbsp;
        <span style="color: #808080; font-style: italic;"># Une future est hashable, et peut donc être une clé de dictionnaire.</span>
        <span style="color: #808080; font-style: italic;"># On s'en sert ici pour récupérer l'URL correspondant à cette future.</span>
        url = futures_and_url<span style="color: black;">&#91;</span>future<span style="color: black;">&#93;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># On affiche le résultats contenu des sites si les futures le contienne.</span>
        <span style="color: #808080; font-style: italic;"># Si elles contiennent une exception, on affiche l'exception.</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> future.<span style="color: black;">exception</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">None</span>:
            <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'%s generated an exception: %s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>url, future.<span style="color: black;">exception</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: #ff7700;font-weight:bold;">else</span>:
            <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'%s page: %s bytes'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>url, <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>future.<span style="color: black;">result</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: black;">&#41;</span>
&nbsp;
&nbsp;
elsapsed_time = <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> - start_time
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Elapsed time: %ss&quot;</span> <span style="color: #66cc66;">%</span> elsapsed_time.<span style="color: black;">total_seconds</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Et c&#8217;est quand même vachement plus rapide :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">python3 avec_future.<span style="color: black;">py</span> <span style="color: #808080; font-style: italic;"># notez qu'on utilise Python 3 cette fois</span>
http://duckduckgo.<span style="color: black;">com</span>/ page: <span style="color: #ff4500;">8826</span> <span style="color: #dc143c;">bytes</span>
http://sebsauvage.<span style="color: black;">net</span>/ page: <span style="color: #ff4500;">9036</span> <span style="color: #dc143c;">bytes</span>
http://github.<span style="color: black;">com</span>/ page: <span style="color: #ff4500;">12582</span> <span style="color: #dc143c;">bytes</span>
http://sametmax.<span style="color: black;">com</span>/ page: <span style="color: #ff4500;">50998</span> <span style="color: #dc143c;">bytes</span>
http://0bin.<span style="color: black;">net</span>/ page: <span style="color: #ff4500;">5551</span> <span style="color: #dc143c;">bytes</span>
http://bitstamp.<span style="color: black;">net</span>/ page: <span style="color: #ff4500;">52001</span> <span style="color: #dc143c;">bytes</span>
Elapsed <span style="color: #dc143c;">time</span>: 3.480596s</pre></div></div>

<p>Même si vous retirez les commentaires, le code est encore très verbeux, ce qui explique pourquoi j&#8217;attends avec impatience <a href="http://www.python.org/dev/peps/pep-3156/">asyncio</a> qui, grâce à <code>yield from</code>, va intégrer l&#8217;asynchrone de manière plus naturelle au langage.</p>
<p>Mais ça reste beaucoup plus simple que de créer son process à la main, créer une queue, envoyer les tâches dans la queue, s&#8217;assurer que le process est arrêté, gérer les erreurs et le clean up, etc.</p>
<p>Notez qu&#8217;on peut remplacer <code>ProcessPoolExecutor</code> par <code>ThreadPoolExecutor</code> si vous n&#8217;avez pas besoin d&#8217;un process séparé mais juste de l&#8217;IO non bloquant.</p>
<hr />
<p>Télécharger le code de larticle : <a href="https://github.com/sametmax/codes-des-articles/blob/master/2014/janvier/avec_future.py">avec future</a> / <a href="https://github.com/sametmax/codes-des-articles/blob/master/2014/janvier/sans_future.py">sans future</a>.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8781&amp;md5=edd20d1bc83a2cbb327cddfcb1fb3116" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8789
title: Django, une app à la fois – faire une app de base
uri: Django-une-app-à-la-fois-faire-une-app-de-base
url: http://sametmax.com/django-une-app-a-la-fois-faire-une-app-de-base/
content:
<p>Ca faisait longtemps que je n&#8217;avais pas fait avancer le projet <a href="http://sametmax.com/organisation-dune-application-django/">django, an app at a time</a>.</p>
<p>Voici donc un nouveau morceau qui montre comment écrire une petite app de base avec un template et une vue réutilisables qui serviront donc dans les prochaines apps du projet.</p>
<p>Comme d&#8217;hab, vous pouvez récupérer le code sur <a href="https://github.com/sametmax/Django--an-app-at-a-time">la teub de Guy</a> et il y a une version française et anglaise.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8789&amp;md5=5af69319290f2c2a9532c4eebdaf3d40" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8795
title: Vous avez un message ?
uri: Vous-avez-un-message
url: http://sametmax.com/vous-avez-un-message/
content:
<p>Bon, je vois que les mails s&#8217;accumulent dans notre boîte.</p>
<p>Je rappelle qu&#8217;on répond toujours à tout, mais que ça peut prendre plusieurs mois.</p>
<p>Cela dit, j&#8217;ai fais un gros flush là, donc si votre mail est en attente depuis des semaines ou plus, renvoyez le moi, des fois que je l&#8217;ai effacé dans un excès de zèle.</p>
<p>Notamment je crois qu&#8217;on m&#8217;avais envoyé un code à décortiquer dans le cadre de notre <a href="http://sametmax.com/notre-programme-envoyez-nous-les-scripts-que-vous-ne-pigez-pas-est-toujours-dactu/">programme d&#8217;aide</a>, et je le retrouve plus. Si c&#8217;est le votre, faut renvoyer.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8795&amp;md5=96acf5b670771fca5b461f71b6bfb88a" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8798
title: Retirer la friction n’est pas un gadget pour fainéant
uri: Retirer-la-friction-n-est-pas-un-gadget-pour-fainéant
url: http://sametmax.com/retirer-la-friction-nest-pas-un-gadget-pour-faineant/
content:
<p>C&#8217;est une stratégie marketing.</p>
<p>Je vous écris ceci en réaction à <a href="http://sebsauvage.net/links/?mSpC6w">ce post vieux de Sebsauvage</a>, qui peste (à raison) contre l&#8217;introduction des NFC au vu des nombreuses saloperies qu&#8217;on peut faire avec. Couplé au RFID, on a des trucs super vicieux qui se préparent. Je déteste cette techno. Je suis pour la combattre.</p>
<p>Mais sa réflexion de fond est biaisée:</p>
<blockquote><p>
Je rage contre les banques qui poussent massivement cette imbécilité, troquant la sécurité pour un gadget pour feignants («oh cool j&#8217;ai pas besoin de sortir ma carte du portefeuille» &#8211; meh.)
</p></blockquote>
<p>Ce n&#8217;est pas du tout ça. L&#8217;idée, c&#8217;est de rendre le paiement inconscient. Une des raisons pour laquelle itunes et l&#8217;appstores marchent si bien commercialement parlant, c&#8217;est qu&#8217;une fois qu&#8217;on a enregistré sa carte de crédit, acheter est un acte sans friction.</p>
<p>Quand on veut une app ou une musique, on clique juste sur un bouton. L&#8217;action de payer est invisible, sans action de la part de l&#8217;utilisateur: il est passif.</p>
<p>Et ça, c&#8217;est une arme de destruction massive.</p>
<p>Quand Amazon a introduit son système de paiement <a href="http://www.amazon.fr/gp/help/customer/display.html?nodeId=548626">1-click</a>, qui permettait de payer sans plus d&#8217;étapes, ils ont gagné le marché. Tout le marché. En 2 ans, ils sont devenus le Google de la vente en ligne, laissant aux milliers de sites web de vente concurrents des miettes.</p>
<p>Retirer la friction, c&#8217;est <a href="http://www.eyrolles.com/Informatique/Livre/9782744021893?societe=nodesway">la base de l&#8217;expérience UI</a>.</p>
<p>Donc quand les banques et les commerciaux poussent au cul pour faire passer des méthodes de paiement avec le moins de friction possible (le NFC évite également d&#8217;entrer son code PIN en dessous d&#8217;une certaine somme il me semble), c&#8217;est tout simplement pour que les gens dépensent plus. Massivement plus.</p>
<p>Pour cette même raison, des <a href="http://www.courrierinternational.com/article/2004/06/03/une-puce-electronique-sous-la-peau-pour-entrer-en-discotheque">expérimentations</a> ont été faites à Barcelonne avec des puces sous-cutanées de paiement insérées dans la main. Le résultat est là : les consommateurs ne font plus attention.</p>
<p>Vous pouvez vous-même faire cet essai : interdisez-vous l&#8217;usage de la carte de crédit pour un mois. Vous allez-voir la friction de votre opération de paiement augmenter, et vous dépenserez moins. Laisser sa carte de crédit à la maison, ce sont des économies instantanées.</p>
<p>De même pour le NFC, le simple fait de ne pas avoir à sortir son portefeuille va diminuer la friction. Encore plus loin, le fait de  devoir emporter uniquement son téléphone, ajouté peut être un jour à l&#8217;inutilité de le sortir de sa poche va, contre-intuitivement, booster énormément les ventes. Ce n&#8217;est pas une question d&#8217;être fainéant, c&#8217;est juste que l&#8217;humain, psychologiquement, ne se rend pas autant compte qu&#8217;il dépense. C&#8217;est comme le coup des 9,90 € au lieux des 10 euros. Ce n&#8217;est pas un cheap trick, c&#8217;est des milliards en plus.</p>
<p>À cause de la crise, on a tendance à penser que les gens n&#8217;ont plus d&#8217;argent. On se demande donc quel intérêt on a à tenter de leur faire dépenser plus.</p>
<p>Seulement cela ignore deux choses : la premières, c&#8217;est que le NFC sera couplé bientôt à des crédits à la consommation. Il ne faut pas se leurer. Les gens s&#8217;endetterons sans s&#8217;en rendre compte, c&#8217;est le but. Des dettes, des enfants, de la bouffe bien riche, 7 heures de boulot par jour + 2 h de transport et on ne peut pas protester, on devient un rouage huilé et prévisible du système. Mais je m&#8217;égare sur un autre sujet.</p>
<p>La seconde c&#8217;est qu&#8217;on estime que les français détiennent encore <a href="http://www.latribune.fr/vos-finances/epargne/20110406trib000613635/les-francais-detiennent-11.000-milliards-d-euros-d-epargne-.html">11 000 milliards en épargne</a>. 11 000 MILLIARDS. Bref, il y a encore de l&#8217;argent à gratter, et il faut  trouver un moyen de le faire sortir.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8798&amp;md5=f56e0f7f029296bde134ceaf1daaa740" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8808
title: La fin du mystère du binaire (nananère)
uri: La-fin-du-mystère-du-binaire-(nananère)
url: http://sametmax.com/la-fin-du-mystere-du-binaire-nananere/
content:
<p>Quand mon voisin de table en cours de SVT a commencé à m&#8217;expliquer le binaire (il programmait en assembleur sur sa TI89), j&#8217;ai pas bien pigé. Des années plus tard, en cours d&#8217;archi, un prof nous a fait un cours magistral sur la question. Je n&#8217;ai définitivement rien pigé. J&#8217;ai regardé des tutos sur le net. RIEN P-I-G-É.</p>
<p>J&#8217;ai mis presque 10 ans (littéralement) avant que mon cerveau tilte. Non pas que je n&#8217;avais pas compris le principe, mais le détails, comment on faisait la conversion, ce qu&#8217;on pouvait faire avec, etc&#8230; Ca me passait au dessus de la tête.</p>
<p>Je râle beaucoup sur le manque de pédagogie d’autrui, et après tout, d&#8217;autres ont compris le truc à partir de ces explications. Mais je vais me répéter : leurs explications étaient merdiques.</p>
<p>Le binaire c&#8217;est simple. Tout le monde peut le comprendre.</p>
<p>Si vous ne pigez pas, c&#8217;est que le mec en face de vous est une grosse pine.</p>
<p>Par contre, il y a beaucoup de choses à savoir, alors à long article, loooooooooooongue musique :</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="420" height="315" src="//www.youtube.com/embed/6XIpR59xeEU" frameborder="0" scrolling="no" class="iframe-class"></iframe>
<p>Long article car j&#8217;ai vu des connards mélanger tout et n&#8217;importe quoi dans leurs explications du binaire, et je vais devoir démêler le sac de nœuds qu&#8217;ils ont fait dans votre tête.</p>
<h2>Pourquoi apprendre le binaire ?</h2>
<p>Pour le sport, essentiellement. La culture G. Parce qu&#8217;en toute honnêteté, aujourd&#8217;hui, ça ne sert plus à grand chose, tellement vous avez de couches d&#8217;abstraction entre les manipulations binaires et vous.</p>
<p>Il y a toujours quelques grincheux qui vous diront des trucs de grincheux comme &#8220;oui, mais pour comprendre les erreurs de flottant en arithmétique, il faut comprendre le binaire&#8221; comme mon père qui me disait qu&#8217;il fallait apprendre le latin au lycée. Meh.</p>
<p>D&#8217;abord, on a pas plus besoin d&#8217;apprendre le binaire pour comprendre les erreurs de flottant qu&#8217;on a besoin de comprendre la composition moléculaire de l&#8217;essence pour savoir pourquoi une voiture tombe en panne quand il y en a plus. Ensuite, vous n&#8217;avez même pas besoin de comprendre pourquoi il y a des erreurs de flottant, juste à savoir comment les éviter (ce que des tas de gens &#8220;qui les comprennent&#8221; ne sont pas foutu de faire).</p>
<p>Bref, c&#8217;est l&#8217;éternel bataille de l&#8217;arrière garde qui veut défendre le savoir aujourd&#8217;hui obsolète &#8211; qu&#8217;il a accumulé parce qu&#8217;a son époque c&#8217;était indispensable &#8211; à grand renfort de pédanterie. On voit ça dans tous les domaines. Généralement avec  force exemples de niches et enculage de mouche.</p>
<p>Mais au delà de ça, le binaire est encore utilisé dans certains domaines, comme la programmation de micro-contrôleurs (si vous planifiez de bosser chez Intel, Nvidia ou la NASA, ça peut servir), la cryptographie ou la programmation de calculatrices en cours de bio. Ce dernier point étant semble-t-il, un sujet intemporel qui ne se démode jamais.</p>
<p>Néanmoins ça reste 0.00001 % de l&#8217;informatique actuelle. Vous n&#8217;aurez pas besoin du binaire pour vos tâches de Sys Admin, vos GUI, votre app mobile, votre site Web, votre algo de simulation, etc. Bref, les trucs pour lesquels les gens sont payés dans les années 2000.</p>
<p>Maintenant que j&#8217;ai bien été désagréable avec une partie du lectorat, précisons tout de même que savoir 2, 3 trucs sur le binaire, ça ne fait pas de mal. Vous êtes informaticiens, ça fait un peu partie du folklore.</p>
<h2>Valeur et représentation</h2>
<p>En informatique, il y a le problème sans fond de la dualité valeur / représentation. L&#8217;écriture des nombres est un exemple parfait de cela.</p>
<p>Par exemple, j&#8217;ai ce nombre d&#8217;étoiles :</p>
<pre>* * * * *</pre>
<p>Il y a la valeur du nombre d&#8217;étoiles. Cette valeur ne peut pas être manipulée, elle existe, c&#8217;est tout. On ne peut que constater le nombre d&#8217;étoiles en interprétant ce que l&#8217;on voit.</p>
<p>Si on veut manipuler cette valeur (parler d&#8217;une valeur, c&#8217;est déjà manipuler la valeur), il faut lui donner une représentation.</p>
<p>Les arabes nous ont donné une représentation : 5.</p>
<p>Les romains avaient une autre représentation : V.</p>
<p>La valeur derrière ces deux représentations est strictement la même.</p>
<p>Le binaire est juste une autre représentation. Il n&#8217;y a rien de magique derrière le binaire.</p>
<p>Par exemple, la valeur que l&#8217;on représentante par 5, se représente ainsi en binaire : 101.</p>
<p>C&#8217;est la même valeur de nombre d&#8217;étoiles. Juste écrit différemment. Cela n&#8217;a aucun impact sur la réalité, ne change rien sur la nature des étoiles ou la valeur manipulée. C&#8217;est une manière de transmettre une information.</p>
<h2>A la base de la base</h2>
<p>La raison pour laquelle on s&#8217;embrouille facilement avec le binaire, c&#8217;est que la plupart d&#8217;entre nous ont appris à lire les nombres par cœur. On lit un nombre comme un tout.</p>
<p>En vérité, un nombre est une notation qui obéit à des règles très strictes, et non seulement chaque chiffre donne une information, mais <strong>sa place</strong> dans le nombre donne une information. Ce qu&#8217;on appelle &#8220;centaine&#8221;, &#8220;millier&#8221;, etc, sont des notions qu&#8217;on manipule sans y penser, mais derrière, il y a en fait un système.</p>
<p>Le système des bases.</p>
<p>Quand on utilise les chiffres arabes pour écrire un nombre, on utilise une série de symboles, et on les aligne dans un ordre précis. <strong>Selon la base utilisée, l&#8217;ordre implique une valeur différente.</strong></p>
<p>On ne s&#8217;en rend pas compte, mais on utilise tous les jours l&#8217;ordre de la base 10. On pense en base 10. On a tellement l&#8217;habitude de tout calculer en base 10 qu&#8217;on ne se rend pas compte qu&#8217;on suit une règle précise pour cela.</p>
<p>Que signifie le fait d&#8217;utiliser une base 10 ?</p>
<p>Deux choses.</p>
<p>La première, c&#8217;est que l&#8217;on a DIX symboles pour représenter DIX valeurs. On ne sait représenter directement que ces DIX valeurs là.</p>
<pre>
          0
*         1
**        2
***       3
****      4
*****     5
******    6
*******   7
********  8
********* 9</pre>
<p>On a des valeurs (un nombre d&#8217;étoiles), et on fait correspondre <strong>complètement arbitrairement</strong> dix symboles pour ces valeurs. On connait ces symboles par cœur, ce sont des conventions. Ils ne signifient rien par eux-même, nous leur avons donné cette signification.</p>
<p>Ça c&#8217;est la première règle. La deuxième règle, c&#8217;est que quand on tombe à cours de symboles parceque la valeur est trop grande, on utilise <strong>la position</strong> des symboles pour dire combien de groupes de dizaines de symboles il y a.</p>
<p>Par exemple avec ce nombre :</p>
<pre>10</pre>
<p>10 veut dire (en lisant de droite à gauche, ce sont des chiffres arabes, je le rappelle), 0 unité, et 1 groupe d&#8217;une dizaine.</p>
<p>Si on a 587, on dit (toujours de droite à gauche) : il y a 7 unités et 8 groupes d&#8217;une dizaine et 5 groupes d&#8217;une <strong>dizaine de dizaines</strong>.</p>
<p>La position du chiffre dit si l&#8217;on parle d&#8217;un groupe de 1, de 10, de 10 groupes de 10 (cent), de 10 groupes de 10 groupes de 10 (1000), etc.</p>
<p>C&#8217;est pour ça qu&#8217;on parle de base 10. Tout est en groupe de 10. On fait des paquets de 10. Puis des paquets de 10 paquets de 10. Puis des paquets de 10 paquets de 10 paquets de 10&#8230;</p>
<p>Exemple avec le nombre 1982 :</p>
<pre>
[1][9][8][2]
 |  |  |  |
 |  |  |  2 unités
 |  |  8 groupes de 10
 |  9 groupes de 10 groupes de 10 (10 x 10 = 100)
1 groupe de 10 groupes de 10 groupes de 10 (10 x 10 x 10 = 1000)</pre>
<p>Si on lit un chiffre comme un tableau en informatique (donc en commençant par 0), mais de droite à gauche, on peut utiliser les puissances pour noter ça de manière propre :</p>
<pre>
[1][9][8][2]
 |  |  |  |
 |  |  |  2 est à la place 0, sa "valeur" est 2 x 10^0 = 2 * 1 = 2
 |  |  8 est à la place 1, sa "valeur" est 8 x 10^1 = 8 * 10 = 80
 |  9 est à la place 2, sa "valeur" est 9 x 10^2 = 9 x 10 x 10 = 9 x 100 = 900
1 est à la place 3, sa "valeur" est 1 x 10^3 = 1 x 10 x 10 x 10 = 1 x 1000 = 1000</pre>
<p>Ça vous parait évident sans avoir à faire le calcul ? C&#8217;est parce que vous êtes tellement habitué à compter en base 10 que c&#8217;est automatique pour vous. Pourtant, en base 2, c&#8217;est <strong>exactement la même chose.</strong></p>
<p>On a DEUX symboles pour représenter DEUX valeurs. On ne sait représenter que ces DEUX valeurs là.</p>
<pre>
  0
* 1</pre>
<p>Quand on tombe à cours de symbole parce qu&#8217;une valeur est trop grande, on utilise <strong>la position</strong> des symboles pour dire combien de groupes de deux symboles il y a.</p>
<p>Par exemple avec ce nombre :</p>
<pre>10</pre>
<p>10, <strong>qui ne se prononce PAS dix</strong>, veut dire (en lisant de droite à gauche), 0 unité, et 1 groupe d&#8217;une paire. Donc deux en base 10 :-).</p>
<p>Pour les chiffres plus longs, c&#8217;est kiff, kiff :</p>
<pre>
[1][1][1][0]
 |  |  |  |
 |  |  |  0 unité
 |  |  1 groupes de 2
 |  1 groupes de 2 groupes de 2 (2 x 2 = 4 en base 10)
1 groupe de 2 groupes de 2 groupes de 2 (2 x 2 x 2 = 8 en base 10)</pre>
<p>Donc en base 10 : 8 + 4 + 2, soit 14.</p>
<p>Si on le représente en puissance de 2 :</p>
<pre>
[1][1][1][0]
 |  |  |  |
 |  |  |  0 est à la place 0, sa "valeur" est 0 x 2^0 = 0 * 1 = 0
 |  |  1 est à la place 1, sa "valeur" est 1 x 2^1 = 1 * 2 = 2
 |  1 est à la place 2, sa "valeur" est 1 x 2^2 = 1 x 2 x 2 = 1 x 4 = 4
1 est à la place 3, sa "valeur" est 1 x 2^3 = 1 x 2 x 2 x 2 = 1 x 8 = 8</pre>
<p>En gros pour convertir du binaire en base 10, il suffit de réciter les puissances de deux dans sa tête :</p>
<p>2, 4, 8, 16, 32&#8230; (2 fois 2 = 4, 2 fois 4 = 8, 2 fois 8 = 16, 2 fois 16 = 32&#8230;)</p>
<p>Et les appliquer de droite à gauche :</p>
<pre>[1][0][1][1][1][0] => [1 * 32] + [0 * 16] + [1 * 8] + [1 * 4] + [1 * 2] + [O * 1] => 46 en base 10</pre>
<p>Une illustration graphique ?</p>
<p>Voici quarante-six étoiles :</p>
<pre>**********************************************</pre>
<p>Si je les représente en base 10, je noterais ça 46, soit 4 groupes de dizaines, et 6 unités :</p>
<pre>
    4          6

**********   ******
**********
**********
**********
</pre>
<p>Si je le représente en base 2, je le note 101110: soit 1 groupe de trente-deux, 0 groupe de seize, 1 groupe de huit, 1 groupe de quatre, 1 groupe de deux, et 0 unité.</p>
<pre>
                1                  0      1        1     1    0

********************************   -   ********   ****   **   -</pre>
<p>On peut faire ça avec n&#8217;importe quelle base. On peut compter en base 3 (ternaire) ou en base 4, 5, 6&#8230; On utilise notamment parfois en informatique la base 8 (octale) et la base 16 (hexadécimale). Pour cette base, il y a 16 symboles : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F, représentant chacun une valeur, puis, quand on a plus de symbole, on utilise la position pour signaler un paquet de 16.</p>
<h2>Passons au code</h2>
<p>En Python on peut écrire un nombre en binaire en le préfixant de &#8217;0b&#8217;:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> 0b101110
<span style="color: #ff4500;">46</span></pre></div></div>

<p>Mais par défaut Python <strong>représente</strong> toujours à l&#8217;affichage ce nombre en base 10. La valeur derrière est la même de toute façon (qui, de manière amusante, est sockée en binaire).</p>
<p>Si vous voulez forcer <strong>l&#8217;affichage</strong> du nombre en binaire, vous pouvez utilisez <code>bin()</code> ou <code>format()</code> :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">'Le nombre {0} en binaire donne : {0:b}'</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">46</span><span style="color: black;">&#41;</span>
u<span style="color: #483d8b;">'Le nombre 46 en binaire donne : 101110'</span>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> bin<span style="color: black;">&#40;</span><span style="color: #ff4500;">46</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'0b101110'</span></pre></div></div>

<p>A l&#8217;inverse, si vous avez une représentation textuelle d&#8217;un chiffre binaire, vous pouvez préciser la base via le second paramètre de <code>int()</code> :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'101110'</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># la base 10 est le réglage par défaut...</span>
<span style="color: #ff4500;">101110</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'101110'</span>, <span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># ...donc on récupère cent un mille cent dix.</span>
<span style="color: #ff4500;">101110</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'101110'</span>, <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># si on précise la base 2, on récupère quarante-six.</span>
<span style="color: #ff4500;">46</span></pre></div></div>

<p>Mais si on n&#8217;a pas codé sa petite fonction pour faire pareil à la main à 50 ans, on a raté sa vie. Donc, voici un exemple simple d&#8217;une fonction qui convertit une représentation textuelle d&#8217;un chiffre binaire en int Python :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> bin2dec<span style="color: black;">&#40;</span>s<span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;"># on rejette les chaînes vides</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> s:
        <span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #008000;">ValueError</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'The string cannot be empty'</span><span style="color: black;">&#41;</span>
&nbsp;
    total = <span style="color: #ff4500;">0</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># on itère sur la chaîne, de droite à gauche</span>
    reversed_number = s<span style="color: black;">&#91;</span>::-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> pos, num <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">enumerate</span><span style="color: black;">&#40;</span>reversed_number<span style="color: black;">&#41;</span>:
&nbsp;
        <span style="color: #808080; font-style: italic;"># on multiplie le chiffre en cours par la puissance de 2</span>
        <span style="color: #808080; font-style: italic;"># qui correspond à sa position</span>
        total += <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>num<span style="color: black;">&#41;</span> <span style="color: #66cc66;">*</span> <span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span> <span style="color: #66cc66;">**</span> pos<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> total
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>bin2dec<span style="color: black;">&#40;</span><span style="color: #483d8b;">'0'</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>bin2dec<span style="color: black;">&#40;</span><span style="color: #483d8b;">'1'</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>bin2dec<span style="color: black;">&#40;</span><span style="color: #483d8b;">'10'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>bin2dec<span style="color: black;">&#40;</span><span style="color: #483d8b;">'101'</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>bin2dec<span style="color: black;">&#40;</span><span style="color: #483d8b;">'10011100'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">## 0</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;">## 5</span>
<span style="color: #808080; font-style: italic;">## 156</span></pre></div></div>

<p>Et la fonction inverse :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">__future__</span> <span style="color: #ff7700;font-weight:bold;">import</span> division <span style="color: #808080; font-style: italic;"># pour être tous d'accord sur la division entière</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> dec2bin<span style="color: black;">&#40;</span>i<span style="color: black;">&#41;</span>:
&nbsp;
    numbers = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> i == <span style="color: #ff4500;">0</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> i
&nbsp;
    <span style="color: #808080; font-style: italic;"># On divise (avec la division entière) par deux jusqu'à ce qu'il ne reste</span>
    <span style="color: #808080; font-style: italic;"># plus rien à diviser (on fait des paquets de 2, quoi).</span>
    <span style="color: #808080; font-style: italic;"># Avant chaque division par deux, on regarde si il y aura un reste</span>
    <span style="color: #808080; font-style: italic;"># pour la prochaine division. Si oui, on met 1 pour le paquet de 2 actuel,</span>
    <span style="color: #808080; font-style: italic;"># sinon on met 0.</span>
    <span style="color: #808080; font-style: italic;"># C'est comme pour la multiplication à la main (&quot;je met 2 et je retiens 1&quot;),</span>
    <span style="color: #808080; font-style: italic;"># mais à l'envers.</span>
    <span style="color: #ff7700;font-weight:bold;">while</span> i <span style="color: #66cc66;">!</span>= <span style="color: #ff4500;">0</span>:
        numbers.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#40;</span>i <span style="color: #66cc66;">%</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        i = i // <span style="color: #ff4500;">2</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Ensuite on inverse tout ça et on join() tout en une belle string</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>numbers<span style="color: black;">&#91;</span>::-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>dec2bin<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</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>dec2bin<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</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>dec2bin<span style="color: black;">&#40;</span><span style="color: #ff4500;">2</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>dec2bin<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: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>dec2bin<span style="color: black;">&#40;</span><span style="color: #ff4500;">156</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">## 0</span>
<span style="color: #808080; font-style: italic;">## 1</span>
<span style="color: #808080; font-style: italic;">## 10</span>
<span style="color: #808080; font-style: italic;">## 101</span>
<span style="color: #808080; font-style: italic;">## 10011100</span></pre></div></div>

<h2>Et les opérateurs bitwise ?</h2>
<p>Dans les tutos on voit souvent mélanger la notion de binaire, avec la représentation des nombres, du texte, et les opérateurs spécialisés dans la manipulation du binaire : </p>
<pre>|, ^, ~, >>, <<, >>>, &#038;, etc</pre>
<p>C&#8217;est le bordel.</p>
<p>On les appelle ces opérateurs &#8220;bitwise&#8221;, et ils sont essentiellement de deux types : les shifts, et les opérateurs logiques.</p>
<p>Les shifts, souvent notés <code>&gt;&gt;</code>, <code>&lt;&lt;</code>, etc, décalent d&#8217;un bit. Un bit, c&#8217;est une case dans un nombre binaire, une d&#8217;un chiffre position, qui prend donc la valeur 0 ou 1.</p>
<p>Ex: 1010 est un nombre de 4 bits. 10100 est un nombre de 5 bits.</p>
<p>Par décaler, j&#8217;entends qu&#8217;ils poussent littéralement les bits dans un sens ou dans l&#8217;autre :</p>
<p>1010 &gt;&gt; 1 va donner 101 (les bits se sont décalés vers la droite d&#8217;un cran, c&#8217;est le rshift). Ca fait disparaitre un bit à droite.<br />
1010 &lt;&lt; 1 va donner 10100 (les bits se sont décalés vers la gauche d&#8217;un cran, c&#8217;est le lshift). Ca rajoute un bit à droite.</p>
<p>Si on met un plus grand nombre, on décale de plusieurs bits :</p>
<p>1010 &lt;&lt; 3 va donner 1010000 (les bits se sont décalés vers la gauche de 3 crans)</p>
<p>C&#8217;est une opération très rapide, puisqu&#8217;il suffit de décaler les chiffres, sans faire de calculs complexes. Pourtant, c&#8217;est l&#8217;équivalent de certaines opérations mathématiques.</p>
<p>Par exemple, un lshift peut être équivalent à une multiplication par une puissance de 2.</p>
<p>Ainsi, si je prends le chiffre 10 en (binaire 1010), et que je lui applique un lshift de 3, c&#8217;est comme si je le multipliais par 2^3 (soit 8). Démo en Python :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> 0b1010
<span style="color: #ff4500;">10</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> 0b1010 <span style="color: #66cc66;">&lt;&lt;</span> <span style="color: #ff4500;">3</span>
<span style="color: #ff4500;">80</span></pre></div></div>

<p>Mais l&#8217;opération prend beaucoup moins de cycles CPU qu&#8217;une multiplication. C&#8217;est une astuce d&#8217;optimisation qui a été beaucoup utilisée au paléolithique et qui reste en vigueur chez les cryptonerds. Néanmoins ne l&#8217;utilisez pas en Python, les gains sont minimes. C&#8217;est surtout utile pour les codes C ou assembleur qui sont déjà sur optimisés et ont besoin de ce petit coup de pouce supplémentaire.</p>
<p>Ensuite il y a les opérateurs logiques. Ils appliquent tout simplement la logique booléenne à chaque bit d&#8217;un nombre avec chaque bit d&#8217;un autre nombre dont la position correspond. Par exemple :</p>
<p>Si je fais &#8220;1101 ET (représenté souvent par &#8216;&#038;&#8217;) 110&#8243;, je vais obtenir :</p>
<pre>
[1][1][0][1]
 |  |  |  |
 &#038;  &#038;  &#038;  &#038;
 |  |  |  |
[ ][1][1][0]
 |  |  |  |
 v  v  v  v
 0  1  0  0

1 et rien => vrai ET faux ? => faux => 0
1 et 1 => vrai ET vrai ? => vrai => 1
0 et 1 => faux ET vrai ? => faux => 0
1 et 0 => faux ET vrai ? => faux => 0
</pre>
<p>C&#8217;est de la logique booléenne de base, vous pouvez la tester avec <code>True</code>, <code>False</code>, <code>and</code> et <code>or</code> dans votre shell si ça ne vous parle pas.</p>
<p>En code Python :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> bin<span style="color: black;">&#40;</span>0b1101 <span style="color: #66cc66;">&amp;</span> 0b100<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'0b100'</span></pre></div></div>

<p>On l&#8217;utilise parfois pour faire ce qu&#8217;on appelle des &#8220;masques&#8221;, c&#8217;est à dire représenter une série d&#8217;états sous forme de grille de bits, et changer un état de cette grille en appliquant une opération logique avec une autre grille.</p>
<p>Je sais, ça fait flou comme ça. Un exemple peut-être ?</p>
<p>Les permissions d&#8217;un fichiers Unix sont Read (lire), Write (écrire) et Execute (exécuter). Soit &#8220;rwx&#8221;. Elles s&#8217;appliquent à User (utilisateur), Group (groupe), Other (autre), soit &#8220;ugo&#8221;.</p>
<p>Cela est peut être représenté par 3 groupes de 3 bits, soit 9 bits :</p>
<pre>
    U         G         O
[r][w][x] [r][w][x] [r][w][x]</pre>
<p>1 veut dire que la permission est donnée, 0 veut dire qu&#8217;elle n&#8217;est pas donnée.</p>
<p>Ainsi :</p>
<pre>
[1][1][1] [1][0][1] [1][0][1]</pre>
<p>Veut dire que l&#8217;utilisateur à le droit de lire, écrire et exécuter le fichier. Le groupe et les autres n&#8217;ont que le droit de le lire et exécuter le fichier.</p>
<p>Si vous mettez ça en base 10, ça donne 7/5/5 (et NON sept-cent-cinquante-cinq car il y a 3 valeurs). Cela  explique le fameux <code>chmod 755</code> que vous voyez dans tous les tutos bash.</p>
<p>Si vous faites :</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">chmod</span> g+<span style="color: #c20cb9; font-weight: bold;">w</span> fichier</pre></div></div>

<p>Le programme va rajouter la permission d&#8217;écrire au groupe. On peut représenter cette opération par l&#8217;application d&#8217;une opération &#8220;OU&#8221; (représentée par &#8216;|&#8217;) :</p>
<p>En effet on a 101 pour les permissions du groupe et on veut obtenir 111. Il suffit d&#8217;appliquer le masque 010 (qui correspond pile poil à un 1 à la case de la permission voulue) :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> bin<span style="color: black;">&#40;</span>0b101 | 0b010<span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'0b111'</span></pre></div></div>

<h2>Représentation des nombres dans un ordinateur</h2>
<p>Cette partie c&#8217;est vraiment pour vos beaux yeux hein, ne vous en faites pas si vous ne pigez pas tout. Je ne vais pas dans le détail car ça demanderait un autre article complet, plus un comparatif des archis, des notions, des systèmes de typages des langages, etc. Et j&#8217;ai vraiment pas envie de le faire.</p>
<p>Bon, déjà, la représentation des nombres dans un ordi, c&#8217;est une grande source de confusion : en effet, <strong>l’ordinateur ne stocke pas la représentation binaire directe d&#8217;un nombre</strong>.</p>
<p>On pourrait se dire : l’ordinateur manipule du binaire, on traduit nos nombres en binaire, on fout tout tel quel dedans, et yala.</p>
<p>Mais un ordinateur a des limitations techniques. Notamment, il possède des plages de mémoires d&#8217;un nombre de bits limité. Il faut donc faire tenir la représentation de la valeur sur cet espace limité.</p>
<p>Si votre espace de mémoire pour représenter une valeur est limité à 16 bits et que vous devez stocker un nombre entier dedans, il pourra être au maximum 2^16 &#8211; 1 = 65535.</p>
<p>C&#8217;est pour cela qu&#8217;en C on déclare le type d&#8217;une variable qui va contenir un nombre qu&#8217;on va manipuler. On dit clairement, &#8220;alloue moi cet espace mémoire, mon nombre ne sera jamais plus grand que ça&#8221;. En Python, c&#8217;est automatiquement et transparent.</p>
<p>(C&#8217;est aussi pour ça qu&#8217;on parle de processeur 16bits, 32bits, 64bits, etc. C&#8217;est la taille des jeux d&#8217;instructions qu&#8217;ils sont capables de traiter en un cycle.)</p>
<p>Mais il se rajoute une autre complexité : un entier peut avoir un signe plus ou un signe moins. Il faut bien le représenter quelque part. On peut le faire en utilisant le premier bit, mais aussi avec un format appelé &#8220;le complément à deux&#8221;. Comme cet article est déjà super long, je vais pas me lancer dans l&#8217;explication. J&#8217;ai mal aux doigts. Sachez juste qu&#8217;on utilise en quelque sorte &#8220;l&#8217;inverse&#8221; du nombre.</p>
<p>Encore une fois, en C, on déclare que l&#8217;on va utiliser un &#8220;signed int&#8221; ou un &#8220;unsigned int&#8221; à l&#8217;initialisation d&#8217;une variable.</p>
<p>Enfin, il y a les nombres à virgule, aussi appelés &#8220;flottants&#8221; (d&#8217;où le type &#8220;float&#8221; en Python).</p>
<p>On pourrait se dire qu&#8217;on utilise les puissances de deux négatives :</p>
<p>0.92 se lit en base 10 &#8220;0 x 1 + 9 x 10^-1 + 2 x 10^-2&#8243;</p>
<p>On garderait la logique des positions.</p>
<p>Donc :</p>
<p>0.11 se lit en base 2 &#8220;0 x 1 + 1 x 2^-1 + 1 x 2^-1 + 1 x 2^-2&#8243;</p>
<p>A priori on pourrait stocker le nombre en utilisant ce principe. Mais ça ne permet pas de présenter les nombres très grands (tendant vers l&#8217;infini) ou très petit (tendant vers zéro). Alors on utilise un autre principe : on représente un nombre avec la formule <code>m x 2^n</code>, très couramment sur 64 bits (ce que fait le type float Python, mais on peut avoir <a href="http://docs.scipy.org/doc/numpy/user/basics.types.html">plus de choix</a> de manoeuvre en utilisant numpy).</p>
<p><code>m</code> est un nombre à virgule compris entre 1 et 2 (ce dernier étant exclus). On appelle ça la mantisse. Ce sera stocké sur 52 bits en utilisant une représentation binaire littérale.</p>
<p><code>n</code> est l&#8217;exposant, c&#8217;est un nombre entier compris entre -1022 et 1023, stocké sur 11 bits.</p>
<p>On garde le premier bit pour le signe.</p>
<p>Et il y a des exceptions pour 0, l&#8217;infini et NaN.</p>
<p>(et je n&#8217;ai pas la moindre putain d&#8217;idée de comment sont représentés les complexes)</p>
<p>Si vous êtes en manque d&#8217;aspirine, tout ça est codifié dans la norme <a href="http://fr.wikipedia.org/wiki/IEEE_754">IEEE 754</a>, que Python respecte scrupuleusement.</p>
<p>Mais ça vous fait une belle jambe pas vrai ?</p>
<p>Tout ça pour dire que même avec une belle précision, le nombre de chiffres stockés après la virgule est limité. Du coup, on a une valeur <strong>approximative</strong> stockée dans l&#8217;ordi, ce qui fait que les calculs se font sur des approximations :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;{0:.35f}&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0.9999999999999999999999999999999999999999999999999999999</span> + <span style="color: #ff4500;">0.000000000000000000001</span><span style="color: black;">&#41;</span>
u<span style="color: #483d8b;">'1.00000000000000000000000000000000000'</span></pre></div></div>

<p>En Python on peut gagner en précision en utilisant le module <code>decimal</code>:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">decimal</span> <span style="color: #ff7700;font-weight:bold;">import</span> Decimal
<span style="color: #66cc66;">&gt;&gt;&gt;</span> Decimal<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;0.9999999999999999999999999999999999999999999999999999999&quot;</span><span style="color: black;">&#41;</span> + Decimal<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;0.000000000000000000001&quot;</span><span style="color: black;">&#41;</span>
Decimal<span style="color: black;">&#40;</span><span style="color: #483d8b;">'1.000000000000000000001000000'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>C&#8217;est plus lent, mais plus intuitif. Quand on manipule des sous, du temps, des unités de poids, de température, de longueur, etc, c&#8217;est utile.</p>
<h2>Représentation du texte</h2>
<p>Pour le texte, c&#8217;est encore autre chose. Et là je vous renvoie à l&#8217;<a href="http://sametmax.com/lencoding-en-python-une-bonne-fois-pour-toute/">article sur les encodings</a>.</p>
<p>En résumé, le stockage du texte n&#8217;a rien à avoir avec l&#8217;arithmétique binaire, c&#8217;est juste qu&#8217;on fait correspondre un nombre (on montre souvent sa représentation binaire pour l&#8217;ASCII et sa représentation hexa pour l&#8217;unicode, mais ça reste un nombre, point) à un caractère. Il y a un grand tableau en mémoire qui fait cette correspondance de manière totalement arbitraire. </p>
<p><strong>C&#8217;est une norme arbitraire de correspondance, c&#8217;est tout.</strong></p>
<p>Donc quand on vous dit &#8220;ecrivez les mots &#8216;glory hole&#8217; en binaire&#8221;, <strong>ça ne veut rien dire</strong>.</p>
<p>Une bonne consigne serait de dire : &#8220;donnez moi la suite de nombres, représentés sous forme binaire, qui corresponde aux caractères qui compose les mots &#8216;glory hole&#8217; selon l&#8217;encoding ASCII&#8221;.</p>
<p>On peut obtenir la valeur numérique ASCII en utilisant <code>ord()</code> en Python :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #483d8b;">'glory hole'</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #008000;">ord</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
...
<span style="color: #ff4500;">103</span>
<span style="color: #ff4500;">108</span>
<span style="color: #ff4500;">111</span>
<span style="color: #ff4500;">114</span>
<span style="color: #ff4500;">121</span>
<span style="color: #ff4500;">32</span>
<span style="color: #ff4500;">104</span>
<span style="color: #ff4500;">111</span>
<span style="color: #ff4500;">108</span>
<span style="color: #ff4500;">101</span></pre></div></div>

<p>Après, c&#8217;est juste du formatage pour afficher le binaire :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #483d8b;">'glory hole'</span>:
...     <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;{:b}&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span><span style="color: #008000;">ord</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>
...
<span style="color: #ff4500;">1100111</span>
<span style="color: #ff4500;">1101100</span>
<span style="color: #ff4500;">1101111</span>
<span style="color: #ff4500;">1110010</span>
<span style="color: #ff4500;">1111001</span>
<span style="color: #ff4500;">100000</span>
<span style="color: #ff4500;">1101000</span>
<span style="color: #ff4500;">1101111</span>
<span style="color: #ff4500;">1101100</span>
<span style="color: #ff4500;">1100101</span></pre></div></div>

 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8808&amp;md5=d36e3a0ab4132d5ca90d332dc6b67d99" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8745
title: Wheel installs require setuptools >= 0.8 for dist-info support.
uri: Wheel-installs-require-setuptools-0-8-for-dist-info-support
url: http://sametmax.com/wheel-installs-require-setuptools-0-8-for-dist-info-support/
content:
<p>Je ne sais pas pourquoi, mais une fois j&#8217;ai eu cette erreur en essayant d&#8217;installer un truc avec pip.</p>
<p>La solution est de lancer :</p>
<p><code>sudo pip install setuptools --no-use-wheel --upgrade</code></p>
<p>Et on peut réutiliser pip sans problème.</p>
<p>Zarb.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8745&amp;md5=bd12ac3c7794653e675bc73b7643b82c" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8830
title: Beaucoup de femmes sont de mauvais coups
uri: Beaucoup-de-femmes-sont-de-mauvais-coups
url: http://sametmax.com/beaucoup-de-femmes-sont-de-mauvais-coups/
content:
<p>La caricature du mauvais coup est généralement masculine. Le mec bourrin, le trop pressé, l&#8217;éjaculateur précoce, le crade, celui qui casse l&#8217;ambiance, etc. Il y a tout un tas de stéréotypes.</p>
<p>Mais la vérité c&#8217;est que beaucoup de personnes sont des mauvais coups, et statistiquement, la moitié des personnes sont des femmes.</p>
<p>On en entend moins parler parce que, aussi pathétique que cela soit, beaucoup d&#8217;hommes sont déjà trop heureux de pouvoir baiser, et ne vont donc pas se plaindre, ça arrive pas si souvent.</p>
<p>Or, je ne cesse de vous le répéter, l&#8217;évidence n&#8217;existe pas. Et les nanas n&#8217;ont pas la science infuse non plus, donc il y a pas de raison qu&#8217;elles sachent toutes, comme ça, pouf, comment assurer au pieu (si tant est qu&#8217;il y est une réponse universelle à cette question, et je suis à peu près certain que non).</p>
<p>Bref, voici le tour des stéréotypes féminins des mauvais coups.</p>
<h2>L&#8217;étoile de mer</h2>
<p>Je commence par du classique, parce que je pense que la plupart des mecs en ont rencontré. C&#8217;est la nana dont la participation à l&#8217;action consiste à se mettre sur le dos, et c&#8217;est tout. Ce qui est terrible, c&#8217;est qu&#8217;elles sont assez nombreuses. Je ne saurais pas définir la cause du phénomène. Trop de mauvaises expériences avant ? Pas assez d&#8217;expérience avant ? Peur de mal faire ? Fainéantise ? Ignorance ?</p>
<p>L&#8217;anglaise, surtout bourrée (mais n&#8217;est-ce pas un pléonasme ?), est spécialiste de cette stratégie, qui donne envie de tirer fort sur un bras pour voir si ça va repousser après.</p>
<div id="attachment_8836" class="wp-caption aligncenter" style="width: 510px"><a href="media/200409a9.R6FzJEl.png" data-original-source="http://sametmax.com/wp-content/uploads/2014/01/R6FzJEl.png"><img src="media/200409a9.R6FzJEl.png" data-original-source="http://sametmax.com/wp-content/uploads/2014/01/R6FzJEl.png" alt="Couverture d&#039;un animorphs sur laquelle l&#039;heroine morphe en une étoile de mer" title="J&#039;en ai lu des dizaines quand j&#039;étais gosse; j&#039;étais fan.. Dans un moment de nostalgie, j&#039;en ai relu un l&#039;année dernière. C&#039;est super mauvais." width="500" height="750" class="size-full wp-image-8836" /></a><p class="wp-caption-text">J&#039;en ai lu des dizaines quand j&#039;étais gosse; j&#039;étais fan.. Dans un moment de nostalgie, j&#039;en ai relu un l&#039;année dernière. C&#039;est super mauvais.</p></div>
<h2>La beugleuse</h2>
<p>Vous commencez à peine à lui toucher le genou, et elle est déjà en train de haleter. En levrette, elle fait le bruit d&#8217;un klaxon de 206 au centre de Marseille. Vous faites une tentative désespérée pour ne pas penser à un animal dont le cri s&#8217;en rapproche le plus, mais c&#8217;est trop tard, vous visualisez une étable et la mi-molle se pointe.</p>
<p>Qu&#8217;on ne se trompe pas, j&#8217;adore les filles qui crient. J&#8217;adore même les filles qui simulent. Même qui surjouent, quand l&#8217;ambiance s&#8217;y prête. Mais il y a le niveau au dessus, le Michael Bay du porno qui déclenche une explosion à chaque fois qu&#8217;on fait un créneau avec une 2 chevaux.</p>
<div id="attachment_8838" class="wp-caption aligncenter" style="width: 450px"><a href="media/726f7d54.Kdwt0fv.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/01/Kdwt0fv.jpg"><img src="media/726f7d54.Kdwt0fv.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/01/Kdwt0fv.jpg" alt="Photo d&#039;un écouveur en forme de bonhomme tentant de pénetrer un port jack" title="Ceci dit je comprends une augmentation des décibels quand on passe bestialement du digital vers l&#039;analogique" width="440" height="572" class="size-full wp-image-8838" /></a><p class="wp-caption-text">Ceci dit je comprends une augmentation des décibels quand on passe bestialement du digital vers l&#039;analogique</p></div>
<h2>La maladroite</h2>
<p>Une petit exception pour celle là, parce que je trouve ça touchant. Mais en même tant ça met vite fin à la partie de jambe en l&#8217;air, au bout de la cinquième collision de tête, entre coupées de dents qui se cognent.</p>
<p>C&#8217;est aussi souvent celle qui est capable de <a href="http://sametmax.com/comment-tailler-une-pipe/">faire mal en suçant</a>.</p>
<p>Ouch.</p>
<div id="attachment_8847" class="wp-caption aligncenter" style="width: 310px"><a href="media/90ce1c9d.kTopRight35-76_AA278_PIkin4BottomRight-6422_AA300_SH20_OU01_.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/01/51qiWxgS+HL._BO2204203200_PIsitb-sticker-arrow-clickTopRight35-76_AA278_PIkin4BottomRight-6422_AA300_SH20_OU01_.jpg"><img src="media/90ce1c9d.kTopRight35-76_AA278_PIkin4BottomRight-6422_AA300_SH20_OU01_.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/01/51qiWxgS+HL._BO2204203200_PIsitb-sticker-arrow-clickTopRight35-76_AA278_PIkin4BottomRight-6422_AA300_SH20_OU01_.jpg" alt="Couverture du livre &quot;how to ail at almost everything...&quot;" title="Entre parenthèses, j&#039;adore Scott Adams" width="300" height="300" class="size-full wp-image-8847" /></a><p class="wp-caption-text">Entre parenthèses, j&#039;adore Scott Adams</p></div>
<h2>L&#8217;arythmique</h2>
<p>Le sexe a un rythme, et quand on connait pas son (ou ses) partenaire(s), le plus important est que tout le monde s&#8217;harmonise bien. Parfois ça se fait tout seul, parfois il y en a un qui donne le ton et l&#8217;autre suit. Parfois il faut faire quelques efforts, mais on finit par trouver.</p>
<p>Et parfois on se retrouve avec l&#8217;équivalent de cette meuf toute seule sur le dance floor, et pas du tout, mais alors pas du tout, calée sur la musique. Et qui s&#8217;excite comme une folle en plus.</p>
<p>Et là ça amène le déboitage de penis, avec parfois à la clé un arrêt au stand pour changer le pneu. Mais aussi des morsures / griffures qui arrivent trop tôt, un vêtement qui se retirer trop tard, ou à moitié.</p>
<div id="attachment_8846" class="wp-caption aligncenter" style="width: 330px"><a href="media/452c3837.bad-girl-dirty-dance_3.png" data-original-source="http://sametmax.com/wp-content/uploads/2014/01/bad-girl-dirty-dance_3.png"><img src="media/452c3837.bad-girl-dirty-dance_3.png" data-original-source="http://sametmax.com/wp-content/uploads/2014/01/bad-girl-dirty-dance_3.png" alt="Capture d&#039;écran d&#039;un jeu de séduction" title="Il y a une extension avec une option &quot;pogo&quot;" width="320" height="480" class="size-full wp-image-8846" /></a><p class="wp-caption-text">Il y a une extension avec une option &quot;pogo&quot;</p></div>
<h2>L&#8217;arme bactérioloqiue</h2>
<p>Il reste un bout de PQ collé sur sa chatte que vous retirez pour faire un cuni, mais vous êtes stoppé net par une attaque biochimique. Vous lui léchez les seins et un goût acre vous reste dans la bouche. Un baiser et vous pouvez dire qu&#8217;elle fume des sans-filtre.</p>
<p>C&#8217;est marrant parce par contre, le &#8220;je suis pas épilée&#8221; ou &#8220;j&#8217;ai mes règles&#8221; qui semblent poser un tel dilemme à la gente féminine, je m&#8217;en branle complètement.</p>
<div id="attachment_8841" class="wp-caption aligncenter" style="width: 610px"><a href="media/50fd3124.cannes_topcuts_outdoor_bar-ad.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/01/cannes_topcuts_outdoor_bar-ad.jpg"><img src="media/50fd3124.cannes_topcuts_outdoor_bar-ad.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/01/cannes_topcuts_outdoor_bar-ad.jpg" alt="Photo d&#039;une femme et un yeti" title="Les mecs c&#039;est tous des connards ! Ils couchent avec toi et te rapellent jamais !" width="600" height="784" class="size-full wp-image-8841" /></a><p class="wp-caption-text">Les mecs c&#039;est tous des connards ! Ils couchent avec toi et te rapellent jamais !</p></div>
<h2>La chochotte</h2>
<p>Elle ne met pas la langue. Attention à ses seins, ils sont sensibles. Non, vous ne pouvez pas lui tirer les cheveux. Ne pensez même pas à la fessée. La levrette, ça fait mal aux bras à force, on peut changer de position ? Au bout de 5 minutes de sucette, elle a déjà changé 3 fois de main, et annonce qu&#8217;elle a une crampe.</p>
<p>&#8220;Aie, attend, tu m&#8217;écrases !&#8221;</p>
<div id="attachment_8840" class="wp-caption aligncenter" style="width: 510px"><a href="media/94f1e825.tumblr_mzuljnt4861r539hzo1_500.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/01/tumblr_mzuljnt4861r539hzo1_500.jpg"><img src="media/94f1e825.tumblr_mzuljnt4861r539hzo1_500.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/01/tumblr_mzuljnt4861r539hzo1_500.jpg" alt="Photo d&#039;une femme s&#039;enfonçant un poteau de lit dans la chatte" title="Sérieux, des fois j&#039;ai l&#039;impression que tu fais aucun effort !" width="500" height="747" class="size-full wp-image-8840" /></a><p class="wp-caption-text">Sérieux, des fois j&#039;ai l&#039;impression que tu fais aucun effort !</p></div>
<h2>La feignasse</h2>
<p>Elle ne se cambre pas, c&#8217;est trop crevant. D&#8217;ailleurs, même quand elle est au dessus, c&#8217;est vous qui bougez. Vous pourriez croire que c&#8217;est un manque complet de motivation sauf qu&#8217;elle vient vous sauter dessus 5 fois par jour, et une fois bien allumé, elle vous délègue tout le boulot.</p>
<p>Non elle vous mettra pas la capote parce qu&#8217;elle prétend qu&#8217;elle &#8220;sait pas comment faire&#8221;. Comme vos potes qui vous demandaient toujours de rouler le join au lycée.</p>
<p>Le feignasse et l&#8217;étoile de mer sont deux espèces distinctes. L&#8217;étoile de mer ne pige rien, la feignasse sait très bien quoi faire. Elle le fait parfois. Mais pas cette semaine. Ou les jours impairs.</p>
<div id="attachment_8843" class="wp-caption aligncenter" style="width: 440px"><a href="media/f3fe4ec9.n7miBMF.png" data-original-source="http://sametmax.com/wp-content/uploads/2014/01/n7miBMF.png"><img src="media/f3fe4ec9.n7miBMF.png" data-original-source="http://sametmax.com/wp-content/uploads/2014/01/n7miBMF.png" alt="Caricature de &quot;justagirlything&quot; disant &quot;pulling food crumbs out of your cleavage and eating them&quot;" title="Si on se faisait un petit dej au lit ? Tu vas chercher les croissants par -5°C pendant que je fais le café en chausson." width="430" height="343" class="size-full wp-image-8843" /></a><p class="wp-caption-text">Si on se faisait un petit dej au lit ? Tu vas chercher les croissants par -5°C pendant que je fais le café en chausson.</p></div>
<h2>La timide</h2>
<p>C&#8217;est lumière éteinte, et sous la couette. Et peut être qu&#8217;elle va garder son haut, parce qu&#8217;elle a froid. Après 3 ans de négociation, elle fait mine de vous lécher le gland, mais vous n&#8217;avez pas le droit de la regarder. Au final, elle a tellement peur de ce que vous pouvez pensez d&#8217;elle qu&#8217;elle fait tout pour que vous pensiez qu&#8217;elle est super chiante.</p>
<p>Et non, vous ne pouvez pas lui bouffer la chatte, &#8220;elle aime pas ça&#8221;.</p>
<p>(Cela dit je suis toujours assez surpris du nombre de nanas qui ne sont pas à l&#8217;aise avec le cuni. J&#8217;ai rencontré plus de meufs me disant qu&#8217;elles ne voulaient pas que de mec qui ne faisaient pas.)</p>
<div id="attachment_8834" class="wp-caption aligncenter" style="width: 460px"><a href="media/daee8966.3vbjuy6.gif" data-original-source="http://sametmax.com/wp-content/uploads/2014/01/3vbjuy6.gif"><img src="media/daee8966.3vbjuy6.gif" data-original-source="http://sametmax.com/wp-content/uploads/2014/01/3vbjuy6.gif" alt="Gif animé d&#039;un extra terreste avec une enorme bite poursuivant une femme" title="Dans le noir ? Cool, je brille dans le noir !" width="450" height="320" class="size-full wp-image-8834" /></a><p class="wp-caption-text">Dans le noir ? Cool, je brille dans le noir !</p></div>
<h2>La &#8220;féministe&#8221;</h2>
<p>Il y a tout un tas de truc qu&#8217;elle ne veut pas faire parce qu&#8217;elle trouve ça dégradant (et ça doit inclure trouver un job&#8230;), et elle va vous l&#8217;expliquer au plus mauvais moment, en lançant un débat si nécessaire. Mais elle se plaint que votre libido décline avec le temps. C&#8217;est bizarre, la position du missionnaire pendant 20 minutes, uniquement dans le lit après 19 h, ça vous tente plus autant qu&#8217;avant.</p>
<p>Et elle veut un massage aussi, parce qu&#8217;elle &#8220;le mérite&#8221;. Ben voyons.</p>
<p>Ah oui, elle ne veut pas prendre le pillule car c&#8217;est mauvais pour la santé, mais elle trouve que la capote c&#8217;est desagréable. Alors elle voudrait bien essayer la méthode des températures. </p>
<p>Elle est pour l&#8217;IVG bien sûr, mais quelque chose vous dit qu&#8217;elle n&#8217;en veut pas pour elle.</p>
<div id="attachment_8835" class="wp-caption aligncenter" style="width: 623px"><a href="media/3d9f8b7f.l-enfant-c-est-la-joie.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/01/l-enfant-c-est-la-joie.jpg"><img src="media/3d9f8b7f.l-enfant-c-est-la-joie.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2014/01/l-enfant-c-est-la-joie.jpg" alt="Ancienne affiche publicitaire contre l&#039;IVG" title="Vous sentez la joie la ?" width="613" height="828" class="size-full wp-image-8835" /></a><p class="wp-caption-text">Vous sentez la joie la ?</p></div>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8830&amp;md5=c6eaa867c771a8a88860fb3dddd0250a" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=6161
title: Parser du HTML avec BeautifulSoup
uri: Parser-du-HTML-avec-BeautifulSoup
url: http://sametmax.com/parser-du-html-avec-beautifulsoup/
content:
<p style="text-align: center;"><em><small>Ceci est un post invité de <a href="http://sametmax.com/author/k3c/">k3c</a> posté sous licence <a href="http://creativecommons.org/licenses/by/3.0/">creative common 3.0 unported</a>.</small></em></p>
<p>Un exemple de parsing HTML avec BeautifulSoup. </p>
<p>Cet article ne traitera pas l&#8217;écriture ou la modification de HTML, et pompera allègrement la doc BeautifulSoup (traduite).</p>
<p>De manière générale, pour télécharger une vidéo sur un site de replay, il faut</p>
<ul>
<li>récupérer un identifiant de la vidéo</li>
<li>le passer à un autre site</li>
<li>analyser le résultat pour trouver l&#8217;adresse de la vidéo.</li>
</ul>
<p>Prenons un exemple sur les replays de d8.tv, par exemple</p>
<p><a href="http://www.d8.tv/d8-series/pid6654-d8-longmire.html">une vidéo de D8</a></p>
<p>(attention cet exemple sera rapidement obsolète, mais c&#8217;est le principe qui nous intéresse)</p>
<p>L&#8217;installation de BeautifulSoup 4 se fait avec, au choix</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">$ apt-get install python-bs4
$ easy_install beautifulsoup4
$ pip install beautifulsoup4</pre></div></div>

<p>La documentation de BeautifulSoup 4 est à</p>
<p><a href="http://www.crummy.com/software/BeautifulSoup/bs4/doc/">http://www.crummy.com/software/BeautifulSoup/bs4/doc/</a></p>
<p>Si on regarde le code source de la page (CTRL U sous Firefox, sinon voyez avec votre navigateur préféré), on voit que la partie qui nous intéresse et qui contient videoId est courte</p>
<p>Ici l&#8217;identifiant recherché est 943696</p>
<p>En Python, on va donc faire quelque chose comme</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">urllib2</span> <span style="color: #ff7700;font-weight:bold;">import</span> urlopen
<span style="color: #ff7700;font-weight:bold;">import</span> bs4 <span style="color: #ff7700;font-weight:bold;">as</span> BeautifulSoup
html = urlopen<span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://www.d8.tv/d8-series/pid6654-d8-longmire.html'</span><span style="color: black;">&#41;</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
soup = BeautifulSoup.<span style="color: black;">BeautifulSoup</span><span style="color: black;">&#40;</span>html<span style="color: black;">&#41;</span></pre></div></div>

<p>Comme le dit la doc BeautifulSoup</p>
<p><em>début du pompage de la doc BeautifulSoup</em></p>
<p>Beautiful Soup transforme un document HTML complexe en un arbre complexe d&#8217;objets Python. Mais vous aurez à manipuler seulement quatre types d&#8217;objets : Tag, NavigableString, BeautifulSoup, et Comment.</p>
<ul>
<li>Tag<br />
	Un objet Tag correspond à un tag HTML ou XML dans le document<br />
	Les Tags ont de nombreux attributs et méthodes, que nous verrons dans<br />
	<a href="http://www.crummy.com/software/BeautifulSoup/bs4/doc/#navigating-the-tree">naviguer dans l&#8217;arborescence</a><br />
	et<br />
	<a href="http://www.crummy.com/software/BeautifulSoup/bs4/doc/#searching-the-tree">chercher dans 	l&#8217;arborescence</a></p>
<p>	Pour l&#8217;instant, les caractéristiques les plus importantes d&#8217;un tag sont<br />
	son nom</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> tag.<span style="color: black;">name</span>
 u<span style="color: #483d8b;">'b'</span></pre></div></div>

<p>	ses attributs<br />
	Un tag peut avoir n&#8217;importe quel nombre d&#8217;attributs. Le tag</p>

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

<p> possède un attribut “class” dont la  valeur est “boldest”. On peut accéder les attributs d&#8217;un tag en le traitant comme un dictionaire :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> tag<span style="color: black;">&#91;</span><span style="color: #483d8b;">'class'</span><span style="color: black;">&#93;</span>
 u<span style="color: #483d8b;">'boldest'</span></pre></div></div>

<p>	On peut accéder directement ce dictionaire avec .attrs:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span>tag.<span style="color: black;">attrs</span>
 <span style="color: black;">&#123;</span>u<span style="color: #483d8b;">'class'</span>: u<span style="color: #483d8b;">'boldest'</span><span style="color: black;">&#125;</span></pre></div></div>

</li>
<li>NavigableString<br />
	Une chaîne de caractères est un peu de texte  l&#8217;intérieur d&#8217;un tag. Beautiful Soup utilise la classe NavigableString class pour contenir ces morceaux de texte:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> tag.<span style="color: #dc143c;">string</span>
 u<span style="color: #483d8b;">'Extremely bold'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>tag.<span style="color: #dc143c;">string</span><span style="color: black;">&#41;</span>
 <span style="color: #ff7700;font-weight:bold;">class</span> <span style="color: #483d8b;">'bs4.element.NavigableString'</span></pre></div></div>

<p>	Un NavigableString est comme une chaîne de caractères  Python Unicode, sauf que elle supporte aussi quelques unes des caractéristiques décrites dans Navigating the tree et Searching the tree. Vous pouvez convertir une chaîne de caractères NavigableString en Unicode avec unicode():</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> unicode_string = <span style="color: #008000;">unicode</span><span style="color: black;">&#40;</span>tag.<span style="color: #dc143c;">string</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> unicode_string
 u<span style="color: #483d8b;">'Extremely bold'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>unicode_string<span style="color: black;">&#41;</span>
 <span style="color: #008000;">type</span> <span style="color: #483d8b;">'unicode'</span></pre></div></div>

</li>
<li>
BeautifulSoup<br />
	L&#8217;objet BeautifulSoup lui-même représente le document dans son ensemble. Dans la plupart des cas, vous pouvez le 	traiter en tant qu&#8217;objet Cela signifie qu&#8217;il supporte la plupart des méthodes décrites dans Navigating the tree et 	Searching the tree.</p>
<p>	Comme l&#8217;objet BeautifulSoup ne correspond pas à un tag final HTML ou XML, il n&#8217;a pas de nom et pas d&#8217;attributs. 	Mais il est parfois utile de rechercher son .name, donc on lui a donné le .name “[document]”:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> soup.<span style="color: black;">name</span>
 u<span style="color: #483d8b;">'[document]'</span></pre></div></div>

</li>
<li> Commentaires et autres chaînes de caractères spéciales
<p>	Tag, NavigableString, et BeautifulSoup couvrent presque tout ce que vous verrez dans un fichier HTML ou XML, mais il y a quelques cas à part. Le seul qui doit vous inquiéter (un peu) est le commentaire :</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">markup = &quot;&lt;b&gt;&lt;!--Hey, buddy. Want to buy a used parser?--&gt;&lt;/b&gt;&quot;</pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> soup = BeautifulSoup<span style="color: black;">&#40;</span>markup<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> comment = soup.<span style="color: black;">b</span>.<span style="color: #dc143c;">string</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>comment<span style="color: black;">&#41;</span>
 <span style="color: #ff7700;font-weight:bold;">class</span> <span style="color: #483d8b;">'bs4.element.Comment'</span></pre></div></div>

<p>	L&#8217;objet Comment est simplement un type spécial de NavigableString:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> comment
 u<span style="color: #483d8b;">'Hey, buddy. Want to buy a used parser'</span></pre></div></div>

<p>	Mais quand il apparaît en tant que morceau de document HTML, un Comment est affiché avec un formattage spécial :</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;"># &lt;b&gt;
#  &lt;!--Hey, buddy. Want to buy a used parser?--&gt;
# &lt;/b&gt;</pre></div></div>

<p>	Beautiful Soup définit des classes pour n&#8217;importe quoi d&#8217;autre qui apparaîtrait dans un document XML : CData, ProcessingInstruction, Declaration, et Doctype. De la meme manière que Comment, ces classes sont des sous-classes de NavigableString qui ajoutent quelque chose à la chaîne de caractères. Voici un exemple qui remplace le commentaire par un block CDATA :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> bs4 <span style="color: #ff7700;font-weight:bold;">import</span> CData
cdata = CData<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;A CDATA block&quot;</span><span style="color: black;">&#41;</span>
comment.<span style="color: black;">replace_with</span><span style="color: black;">&#40;</span>cdata<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>soup.<span style="color: black;">b</span>.<span style="color: black;">prettify</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;"># &lt;b&gt;
#  &lt;![CDATA[A CDATA block]]&gt;
# &lt;/b&gt;</pre></div></div>

</li>
</ul>
<p><em>fin du pompage de la doc BeautifulSoup</em></p>
<p>On peut faire un</p>

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

<p>pour voir à quoi ressemble le code HTML de la page</p>
<p>Il faut d&#8217;abord analyser la page et rechercher ce qui suit videoId</p>
<p>Pour commencer nous allons naviguer dans le document.</p>
<p>BeautifulSoup permet de multiples syntaxes, par exemple, on n&#8217;est pas obligé de donner le chemin complet</p>

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

<p>ou</p>

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

<p>affichent le meme résultat, vu que la première balise meta est sous la balise head</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;meta content=&quot;text/html; charset=utf-8&quot; http-equiv=&quot;Content-Type&quot;/&gt;</pre></div></div>

<p>Si on regarde les méthodes disponibles</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #008000;">dir</span><span style="color: black;">&#40;</span>soup.<span style="color: black;">meta</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'FORMATTERS'</span>, <span style="color: #483d8b;">'__call__'</span>, <span style="color: #483d8b;">'__class__'</span>, <span style="color: #483d8b;">'__contains__'</span>, <span style="color: #483d8b;">'__delattr__'</span>, <span style="color: #483d8b;">'__delitem__'</span>, <span style="color: #483d8b;">'__dict__'</span>, <span style="color: #483d8b;">'__doc__'</span>, <span style="color: #483d8b;">'__eq__'</span>, <span style="color: #483d8b;">'__format__'</span>, <span style="color: #483d8b;">'__getattr__'</span>, <span style="color: #483d8b;">'__getattribute__'</span>, <span style="color: #483d8b;">'__getitem__'</span>, <span style="color: #483d8b;">'__hash__'</span>, <span style="color: #483d8b;">'__init__'</span>, <span style="color: #483d8b;">'__iter__'</span>, <span style="color: #483d8b;">'__len__'</span>, <span style="color: #483d8b;">'__module__'</span>, <span style="color: #483d8b;">'__ne__'</span>, <span style="color: #483d8b;">'__new__'</span>, <span style="color: #483d8b;">'__nonzero__'</span>, <span style="color: #483d8b;">'__reduce__'</span>, <span style="color: #483d8b;">'__reduce_ex__'</span>, <span style="color: #483d8b;">'__repr__'</span>, <span style="color: #483d8b;">'__setattr__'</span>, <span style="color: #483d8b;">'__setitem__'</span>, <span style="color: #483d8b;">'__sizeof__'</span>, <span style="color: #483d8b;">'__str__'</span>, <span style="color: #483d8b;">'__subclasshook__'</span>, <span style="color: #483d8b;">'__unicode__'</span>, <span style="color: #483d8b;">'__weakref__'</span>, <span style="color: #483d8b;">'_all_strings'</span>, <span style="color: #483d8b;">'_attr_value_as_string'</span>, <span style="color: #483d8b;">'_attribute_checker'</span>, <span style="color: #483d8b;">'_find_all'</span>, <span style="color: #483d8b;">'_find_one'</span>, <span style="color: #483d8b;">'_lastRecursiveChild'</span>, <span style="color: #483d8b;">'_last_descendant'</span>, <span style="color: #483d8b;">'append'</span>, <span style="color: #483d8b;">'attribselect_re'</span>, <span style="color: #483d8b;">'attrs'</span>, <span style="color: #483d8b;">'can_be_empty_element'</span>, <span style="color: #483d8b;">'childGenerator'</span>, <span style="color: #483d8b;">'children'</span>, <span style="color: #483d8b;">'clear'</span>, <span style="color: #483d8b;">'contents'</span>, <span style="color: #483d8b;">'decode'</span>, <span style="color: #483d8b;">'decode_contents'</span>, <span style="color: #483d8b;">'decompose'</span>, <span style="color: #483d8b;">'descendants'</span>, <span style="color: #483d8b;">'encode'</span>, <span style="color: #483d8b;">'encode_contents'</span>, <span style="color: #483d8b;">'extract'</span>, <span style="color: #483d8b;">'fetchNextSiblings'</span>, <span style="color: #483d8b;">'fetchParents'</span>, <span style="color: #483d8b;">'fetchPrevious'</span>, <span style="color: #483d8b;">'fetchPreviousSiblings'</span>, <span style="color: #483d8b;">'find'</span>, <span style="color: #483d8b;">'findAll'</span>, <span style="color: #483d8b;">'findAllNext'</span>, <span style="color: #483d8b;">'findAllPrevious'</span>, <span style="color: #483d8b;">'findChild'</span>, <span style="color: #483d8b;">'findChildren'</span>, <span style="color: #483d8b;">'findNext'</span>, <span style="color: #483d8b;">'findNextSibling'</span>, <span style="color: #483d8b;">'findNextSiblings'</span>, <span style="color: #483d8b;">'findParent'</span>, <span style="color: #483d8b;">'findParents'</span>, <span style="color: #483d8b;">'findPrevious'</span>, <span style="color: #483d8b;">'findPreviousSibling'</span>, <span style="color: #483d8b;">'findPreviousSiblings'</span>, <span style="color: #483d8b;">'find_all'</span>, <span style="color: #483d8b;">'find_all_next'</span>, <span style="color: #483d8b;">'find_all_previous'</span>, <span style="color: #483d8b;">'find_next'</span>, <span style="color: #483d8b;">'find_next_sibling'</span>, <span style="color: #483d8b;">'find_next_siblings'</span>, <span style="color: #483d8b;">'find_parent'</span>, <span style="color: #483d8b;">'find_parents'</span>, <span style="color: #483d8b;">'find_previous'</span>, <span style="color: #483d8b;">'find_previous_sibling'</span>, <span style="color: #483d8b;">'find_previous_siblings'</span>, <span style="color: #483d8b;">'format_string'</span>, <span style="color: #483d8b;">'get'</span>, <span style="color: #483d8b;">'getText'</span>, <span style="color: #483d8b;">'get_text'</span>, <span style="color: #483d8b;">'has_attr'</span>, <span style="color: #483d8b;">'has_key'</span>, <span style="color: #483d8b;">'hidden'</span>, <span style="color: #483d8b;">'index'</span>, <span style="color: #483d8b;">'insert'</span>, <span style="color: #483d8b;">'insert_after'</span>, <span style="color: #483d8b;">'insert_before'</span>, <span style="color: #483d8b;">'isSelfClosing'</span>, <span style="color: #483d8b;">'is_empty_element'</span>, <span style="color: #483d8b;">'name'</span>, <span style="color: #483d8b;">'namespace'</span>, <span style="color: #483d8b;">'next'</span>, <span style="color: #483d8b;">'nextGenerator'</span>, <span style="color: #483d8b;">'nextSibling'</span>, <span style="color: #483d8b;">'nextSiblingGenerator'</span>, <span style="color: #483d8b;">'next_element'</span>, <span style="color: #483d8b;">'next_elements'</span>, <span style="color: #483d8b;">'next_sibling'</span>, <span style="color: #483d8b;">'next_siblings'</span>, <span style="color: #483d8b;">'parent'</span>, <span style="color: #483d8b;">'parentGenerator'</span>, <span style="color: #483d8b;">'parents'</span>, <span style="color: #483d8b;">'parserClass'</span>, <span style="color: #483d8b;">'parser_class'</span>, <span style="color: #483d8b;">'prefix'</span>, <span style="color: #483d8b;">'prettify'</span>, <span style="color: #483d8b;">'previous'</span>, <span style="color: #483d8b;">'previousGenerator'</span>, <span style="color: #483d8b;">'previousSibling'</span>, <span style="color: #483d8b;">'previousSiblingGenerator'</span>, <span style="color: #483d8b;">'previous_element'</span>, <span style="color: #483d8b;">'previous_elements'</span>, <span style="color: #483d8b;">'previous_sibling'</span>, <span style="color: #483d8b;">'previous_siblings'</span>, <span style="color: #483d8b;">'recursiveChildGenerator'</span>, <span style="color: #483d8b;">'renderContents'</span>, <span style="color: #483d8b;">'replaceWith'</span>, <span style="color: #483d8b;">'replaceWithChildren'</span>, <span style="color: #483d8b;">'replace_with'</span>, <span style="color: #483d8b;">'replace_with_children'</span>, <span style="color: #483d8b;">'select'</span>, <span style="color: #483d8b;">'setup'</span>, <span style="color: #483d8b;">'string'</span>, <span style="color: #483d8b;">'strings'</span>, <span style="color: #483d8b;">'stripped_strings'</span>, <span style="color: #483d8b;">'tag_name_re'</span>, <span style="color: #483d8b;">'text'</span>, <span style="color: #483d8b;">'unwrap'</span>, <span style="color: #483d8b;">'wrap'</span><span style="color: black;">&#93;</span></pre></div></div>

<p>on voit que de nombreuses méthodes sont disponibles, et suivant la doc, on peut donc le traiter comme un dictionnaire</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> soup.<span style="color: black;">meta</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'http-equiv'</span><span style="color: black;">&#93;</span>
<span style="color: #483d8b;">'Content-Type'</span></pre></div></div>

<p>et tester quelques méthodes</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> soup.<span style="color: black;">meta</span>.<span style="color: black;">name</span>
<span style="color: #483d8b;">'meta'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> soup.<span style="color: black;">meta</span>.<span style="color: black;">find_next_sibling</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'&lt;meta content=&quot;D8&quot; name=&quot;author&quot;/&gt;'</span></pre></div></div>


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

<p>Nous voyons que soup.meta a un sibling (frère ou soeur) suivant, mais pas de précédent, c&#8217;est le premier de l&#8217;arborescence.<br />
Bon, la balise meta a pour nom meta, pas un scoop, on continue avec les clés de dictionnaire, sans surprise</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> soup.<span style="color: black;">meta</span>.<span style="color: black;">find_next_sibling</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'&lt;meta content=&quot;D8&quot; name=&quot;author&quot;/&gt;'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> soup.<span style="color: black;">meta</span>.<span style="color: black;">find_next_sibling</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'content'</span><span style="color: black;">&#93;</span>
<span style="color: #483d8b;">'D8'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> soup.<span style="color: black;">meta</span>.<span style="color: black;">find_next_sibling</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'name'</span><span style="color: black;">&#93;</span>
<span style="color: #483d8b;">'author'</span></pre></div></div>

<p>Pour le fun, regardez ce que renvoie</p>

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

<p>et</p>

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

<p>et je vous laisse deviner la prochaine commande que vous allez passer&#8230;</p>
<p>Revenons à une recherche qui va trouver de nombreuses occurences</p>

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

<p> va trouver la première balise div, et</p>

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

<p>va renvoyer une liste contenant tous les div de la page, mais cela ne permet pas de trouver facilement la portion contenant videoId, par contre, la documentation de BeautifulSoup montre comment trouver spécifiquement une CSS class, voir<br />
<a href="http://www.crummy.com/software/BeautifulSoup/bs4/doc/#searching-by-css-class">searching by css class dans la doc BeautifulSoup</a><br />
dans la documentation BeautifulSoup<br />
Voici la syntaxe à utiliser</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">soup.<span style="color: black;">find</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'div'</span>,attrs=<span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;class&quot;</span>:u<span style="color: #483d8b;">&quot;block-common block-player-programme&quot;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>va renvoyer la partie qui nous intéresse, par exemple</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">        &lt;div class=&quot;block-common block-player-programme&quot;&gt;
&nbsp;
            &lt;div class=&quot;bpp-player&quot;&gt;
                &lt;div class=&quot;playerVideo player_16_9&quot;&gt;
&nbsp;
		&lt;div class=&quot;itemprop&quot; itemprop=&quot;video&quot; itemscope itemtype=&quot;http://schema.org/VideoObject&quot;&gt;
			&lt;h1&gt;Vidéo : &lt;span itemprop=&quot;name&quot;&gt;Longmire - Samedi 30 novembre à 20h50&lt;/span&gt;&lt;/h1&gt;
			&lt;meta itemprop=&quot;duration&quot; content=&quot;&quot; /&gt;
			&lt;meta itemprop=&quot;thumbnailUrl&quot; content=&quot;http://media.canal-plus.com/wwwplus/image/53/1/1/LONGMIRE___BANDE_ANNONCE__131120_UGC_3279_image_L.jpg&quot; /&gt;			
&nbsp;
			&lt;meta itemprop=&quot;embedURL&quot; content=&quot;http://player.canalplus.fr/embed/flash/CanalPlayerEmbarque.swf?vid=975153&quot; /&gt;
			&lt;meta itemprop=&quot;uploadDate&quot; content=&quot;2013-11-29T00:00:00+01:00&quot; /&gt;
			&lt;meta itemprop=&quot;expires&quot; content=&quot;2014-02-18T00:00:00+01:00&quot; /&gt;
&nbsp;
    &lt;canal:player videoId=&quot;975153&quot; width=&quot;640&quot; height=&quot;360&quot; id=&quot;CanalPlayerEmbarque&quot;&gt;&lt;/canal:player&gt;</pre></div></div>

<p>Le type de cette donnée est bs4 élément tag </p>
<p>Comme l&#8217;a dit un homme célèbre<br />
<a href="http://sametmax.com/si-vous-ne-savez-pas-ce-que-contient-une-variable-vous-ne-comprenez-pas-le-programme/">si vous ne savez pas ce que contient une variable, vous ne comprenez pas le programme</a><br />
on peut donc faire un type, dir, help, doc, repr, par exemple</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>soup.<span style="color: black;">find</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'div'</span>,attrs=<span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;class&quot;</span>:u<span style="color: #483d8b;">&quot;block-common block-player-programme&quot;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">class</span> <span style="color: #483d8b;">'bs4.element.Tag'</span></pre></div></div>

<p>donc nous pouvons rechercher un tag, comme<br />
canal:player</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> soup.<span style="color: black;">find</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'div'</span>,attrs=<span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;class&quot;</span>:u<span style="color: #483d8b;">&quot;block-common block-player-programme&quot;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>.<span style="color: black;">find</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'canal:player'</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'&lt;canal:player height=&quot;360&quot; id=&quot;CanalPlayerEmbarque&quot; videoid=&quot;786679&quot; width=&quot;640&quot;&gt;&lt;/canal:player&gt;'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> soup.<span style="color: black;">findAll</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'div'</span>, attrs=<span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;class&quot;</span>:u<span style="color: #483d8b;">&quot;tlog-inner&quot;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>renvoie une liste</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: black;">&#91;</span><span style="color: #66cc66;">&lt;</span>div <span style="color: #ff7700;font-weight:bold;">class</span>=<span style="color: #483d8b;">&quot;tlog-inner&quot;</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>div <span style="color: #ff7700;font-weight:bold;">class</span>=<span style="color: #483d8b;">&quot;tlog-account&quot;</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>span <span style="color: #ff7700;font-weight:bold;">class</span>=<span style="color: #483d8b;">&quot;tlog-avatar&quot;</span><span style="color: #66cc66;">&gt;&lt;</span>img height=<span style="color: #483d8b;">&quot;30&quot;</span> src=<span style="color: #483d8b;">&quot;http://media.canal-plus.com/design/front_office_d8/images/xtrans.gif&quot;</span> width=<span style="color: #483d8b;">&quot;30&quot;</span>/<span style="color: #66cc66;">&gt;&lt;</span>/span<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>a <span style="color: #ff7700;font-weight:bold;">class</span>=<span style="color: #483d8b;">&quot;tlog-logout le_btn&quot;</span> href=<span style="color: #483d8b;">&quot;#&quot;</span><span style="color: #66cc66;">&gt;</span>x<span style="color: #66cc66;">&lt;</span>/a<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>/div<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>form action=<span style="color: #483d8b;">&quot;#&quot;</span> method=<span style="color: #483d8b;">&quot;post&quot;</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>label <span style="color: #ff7700;font-weight:bold;">class</span>=<span style="color: #483d8b;">&quot;switch-fb&quot;</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>span <span style="color: #ff7700;font-weight:bold;">class</span>=<span style="color: #483d8b;">&quot;cursor traa&quot;</span><span style="color: #66cc66;">&gt;</span> <span style="color: #66cc66;">&lt;</span>/span<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>input checked=<span style="color: #483d8b;">&quot;&quot;</span> <span style="color: #008000;">id</span>=<span style="color: #483d8b;">&quot;check-switch-fb&quot;</span> name=<span style="color: #483d8b;">&quot;switch-fb&quot;</span> <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;checkbox&quot;</span> value=<span style="color: #483d8b;">&quot;1&quot;</span>/<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>/label<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>/form<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>div <span style="color: #008000;">id</span>=<span style="color: #483d8b;">&quot;headerFbLastActivity&quot;</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>input <span style="color: #008000;">id</span>=<span style="color: #483d8b;">&quot;name_facebook_user&quot;</span> <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;hidden&quot;</span>/<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>div <span style="color: #ff7700;font-weight:bold;">class</span>=<span style="color: #483d8b;">&quot;top-arrow&quot;</span><span style="color: #66cc66;">&gt;&lt;</span>/div<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>div <span style="color: #ff7700;font-weight:bold;">class</span>=<span style="color: #483d8b;">&quot;top&quot;</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>div <span style="color: #ff7700;font-weight:bold;">class</span>=<span style="color: #483d8b;">&quot;top-bg&quot;</span><span style="color: #66cc66;">&gt;&lt;</span>/div<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>div <span style="color: #ff7700;font-weight:bold;">class</span>=<span style="color: #483d8b;">&quot;top-title&quot;</span><span style="color: #66cc66;">&gt;</span>Activité récente<span style="color: #66cc66;">&lt;</span>/div<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>/div<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>div <span style="color: #ff7700;font-weight:bold;">class</span>=<span style="color: #483d8b;">&quot;middle&quot;</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>div <span style="color: #ff7700;font-weight:bold;">class</span>=<span style="color: #483d8b;">&quot;wrap-last-activity&quot;</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>div <span style="color: #ff7700;font-weight:bold;">class</span>=<span style="color: #483d8b;">&quot;entry&quot;</span><span style="color: #66cc66;">&gt;</span>Aucune<span style="color: #66cc66;">&lt;</span>/div<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>/div<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>div <span style="color: #ff7700;font-weight:bold;">class</span>=<span style="color: #483d8b;">&quot;wrap-notification&quot;</span><span style="color: #66cc66;">&gt;&lt;</span>/div<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>/div<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>div <span style="color: #ff7700;font-weight:bold;">class</span>=<span style="color: #483d8b;">&quot;bottom&quot;</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>a <span style="color: #ff7700;font-weight:bold;">class</span>=<span style="color: #483d8b;">&quot;logout&quot;</span> href=<span style="color: #483d8b;">&quot;#logout&quot;</span><span style="color: #66cc66;">&gt;</span>Déconnexion<span style="color: #66cc66;">&lt;</span>/a<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>/div<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>/div<span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&lt;</span>/div<span style="color: #66cc66;">&gt;</span><span style="color: black;">&#93;</span></pre></div></div>

<p>On peut prendre le premier élément de cette liste</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">soup.<span style="color: black;">findAll</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'div'</span>, attrs=<span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;class&quot;</span>:u<span style="color: #483d8b;">&quot;tlog-inner&quot;</span><span style="color: black;">&#125;</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></pre></div></div>

<p>et ne vouloir que la ligne commençant par &#8220;span class&#8221;</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">soup.<span style="color: black;">findAll</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'div'</span>, attrs=<span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;class&quot;</span>:u<span style="color: #483d8b;">&quot;tlog-inner&quot;</span><span style="color: black;">&#125;</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: black;">span</span></pre></div></div>

<p>ce qui affiche</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;span class=&quot;tlog-avatar&quot;&gt;&lt;img height=&quot;30&quot; src=&quot;http://media.canal-plus.com/design/front_office_d8/images/xtrans.gif&quot; width=&quot;30&quot;/&gt;&lt;/span&gt;</pre></div></div>

<p>Voyons le type de donnée</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">type</span><span style="color: black;">&#40;</span>soup.<span style="color: black;">findAll</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'div'</span>, attrs=<span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;class&quot;</span>:u<span style="color: #483d8b;">&quot;tlog-inner&quot;</span><span style="color: black;">&#125;</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: black;">span</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>class <span style="color: #483d8b;">'bs4.element.Tag'</span><span style="color: #66cc66;">&gt;</span></pre></div></div>

<p>et voyons les méthodes disponibles</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">dir</span><span style="color: black;">&#40;</span>soup.<span style="color: black;">findAll</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'div'</span>, attrs=<span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;class&quot;</span>:u<span style="color: #483d8b;">&quot;tlog-inner&quot;</span><span style="color: black;">&#125;</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: black;">span</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'FORMATTERS'</span>, <span style="color: #483d8b;">'__call__'</span>, <span style="color: #483d8b;">'__class__'</span>, <span style="color: #483d8b;">'__contains__'</span>, <span style="color: #483d8b;">'__delattr__'</span>, <span style="color: #483d8b;">'__delitem__'</span>, <span style="color: #483d8b;">'__dict__'</span>, <span style="color: #483d8b;">'__doc__'</span>, <span style="color: #483d8b;">'__eq__'</span>, <span style="color: #483d8b;">'__format__'</span>, <span style="color: #483d8b;">'__getattr__'</span>, <span style="color: #483d8b;">'__getattribute__'</span>,
<span style="color: #483d8b;">'__getitem__'</span>, <span style="color: #483d8b;">'__hash__'</span>, <span style="color: #483d8b;">'__init__'</span>, <span style="color: #483d8b;">'__iter__'</span>, <span style="color: #483d8b;">'__len__'</span>, <span style="color: #483d8b;">'__module__'</span>, <span style="color: #483d8b;">'__ne__'</span>, <span style="color: #483d8b;">'__new__'</span>, <span style="color: #483d8b;">'__nonzero__'</span>, <span style="color: #483d8b;">'__reduce__'</span>, <span style="color: #483d8b;">'__reduce_ex__'</span>, <span style="color: #483d8b;">'__repr__'</span>, <span style="color: #483d8b;">'__setattr__'</span>
, <span style="color: #483d8b;">'__setitem__'</span>, <span style="color: #483d8b;">'__sizeof__'</span>, <span style="color: #483d8b;">'__str__'</span>, <span style="color: #483d8b;">'__subclasshook__'</span>, <span style="color: #483d8b;">'__unicode__'</span>, <span style="color: #483d8b;">'__weakref__'</span>, <span style="color: #483d8b;">'_all_strings'</span>, <span style="color: #483d8b;">'_attr_value_as_string'</span>, <span style="color: #483d8b;">'_attribute_checker'</span>, <span style="color: #483d8b;">'_find_all'</span>,
<span style="color: #483d8b;">'_find_one'</span>, <span style="color: #483d8b;">'_lastRecursiveChild'</span>, <span style="color: #483d8b;">'_last_descendant'</span>, <span style="color: #483d8b;">'append'</span>, <span style="color: #483d8b;">'attribselect_re'</span>, <span style="color: #483d8b;">'attrs'</span>, <span style="color: #483d8b;">'can_be_empty_element'</span>, <span style="color: #483d8b;">'childGenerator'</span>, <span style="color: #483d8b;">'children'</span>, <span style="color: #483d8b;">'clear'</span>, <span style="color: #483d8b;">'contents'</span>,
 <span style="color: #483d8b;">'decode'</span>, <span style="color: #483d8b;">'decode_contents'</span>, <span style="color: #483d8b;">'decompose'</span>, <span style="color: #483d8b;">'descendants'</span>, <span style="color: #483d8b;">'encode'</span>, <span style="color: #483d8b;">'encode_contents'</span>, <span style="color: #483d8b;">'extract'</span>, <span style="color: #483d8b;">'fetchNextSiblings'</span>, <span style="color: #483d8b;">'fetchParents'</span>, <span style="color: #483d8b;">'fetchPrevious'</span>, <span style="color: #483d8b;">'fetchPreviousSi
blings'</span>, <span style="color: #483d8b;">'find'</span>, <span style="color: #483d8b;">'findAll'</span>, <span style="color: #483d8b;">'findAllNext'</span>, <span style="color: #483d8b;">'findAllPrevious'</span>, <span style="color: #483d8b;">'findChild'</span>, <span style="color: #483d8b;">'findChildren'</span>, <span style="color: #483d8b;">'findNext'</span>, <span style="color: #483d8b;">'findNextSibling'</span>, <span style="color: #483d8b;">'findNextSiblings'</span>, <span style="color: #483d8b;">'findParent'</span>, <span style="color: #483d8b;">'findParents
'</span>, <span style="color: #483d8b;">'findPrevious'</span>, <span style="color: #483d8b;">'findPreviousSibling'</span>, <span style="color: #483d8b;">'findPreviousSiblings'</span>, <span style="color: #483d8b;">'find_all'</span>, <span style="color: #483d8b;">'find_all_next'</span>, <span style="color: #483d8b;">'find_all_previous'</span>, <span style="color: #483d8b;">'find_next'</span>, <span style="color: #483d8b;">'find_next_sibling'</span>, <span style="color: #483d8b;">'find_next_sibling
s'</span>, <span style="color: #483d8b;">'find_parent'</span>, <span style="color: #483d8b;">'find_parents'</span>, <span style="color: #483d8b;">'find_previous'</span>, <span style="color: #483d8b;">'find_previous_sibling'</span>, <span style="color: #483d8b;">'find_previous_siblings'</span>, <span style="color: #483d8b;">'format_string'</span>, <span style="color: #483d8b;">'get'</span>, <span style="color: #483d8b;">'getText'</span>, <span style="color: #483d8b;">'get_text'</span>, <span style="color: #483d8b;">'has_attr'</span>, <span style="color: #483d8b;">'has_k
ey'</span>, <span style="color: #483d8b;">'hidden'</span>, <span style="color: #483d8b;">'index'</span>, <span style="color: #483d8b;">'insert'</span>, <span style="color: #483d8b;">'insert_after'</span>, <span style="color: #483d8b;">'insert_before'</span>, <span style="color: #483d8b;">'isSelfClosing'</span>, <span style="color: #483d8b;">'is_empty_element'</span>, <span style="color: #483d8b;">'name'</span>, <span style="color: #483d8b;">'namespace'</span>, <span style="color: #483d8b;">'next'</span>, <span style="color: #483d8b;">'nextGenerator'</span>, <span style="color: #483d8b;">'nextSibling'</span>, <span style="color: #483d8b;">'ne
xtSiblingGenerator'</span>, <span style="color: #483d8b;">'next_element'</span>, <span style="color: #483d8b;">'next_elements'</span>, <span style="color: #483d8b;">'next_sibling'</span>, <span style="color: #483d8b;">'next_siblings'</span>, <span style="color: #483d8b;">'parent'</span>, <span style="color: #483d8b;">'parentGenerator'</span>, <span style="color: #483d8b;">'parents'</span>, <span style="color: #483d8b;">'parserClass'</span>, <span style="color: #483d8b;">'parser_class'</span>, <span style="color: #483d8b;">'prefix'</span>,
<span style="color: #483d8b;">'prettify'</span>, <span style="color: #483d8b;">'previous'</span>, <span style="color: #483d8b;">'previousGenerator'</span>, <span style="color: #483d8b;">'previousSibling'</span>, <span style="color: #483d8b;">'previousSiblingGenerator'</span>, <span style="color: #483d8b;">'previous_element'</span>, <span style="color: #483d8b;">'previous_elements'</span>, <span style="color: #483d8b;">'previous_sibling'</span>, <span style="color: #483d8b;">'previous_sibli
ngs'</span>, <span style="color: #483d8b;">'recursiveChildGenerator'</span>, <span style="color: #483d8b;">'renderContents'</span>, <span style="color: #483d8b;">'replaceWith'</span>, <span style="color: #483d8b;">'replaceWithChildren'</span>, <span style="color: #483d8b;">'replace_with'</span>, <span style="color: #483d8b;">'replace_with_children'</span>, <span style="color: #483d8b;">'select'</span>, <span style="color: #483d8b;">'setup'</span>, <span style="color: #483d8b;">'string'</span>, <span style="color: #483d8b;">'strings'</span>
, <span style="color: #483d8b;">'stripped_strings'</span>, <span style="color: #483d8b;">'tag_name_re'</span>, <span style="color: #483d8b;">'text'</span>, <span style="color: #483d8b;">'unwrap'</span>, <span style="color: #483d8b;">'wrap'</span><span style="color: black;">&#93;</span></pre></div></div>

<p>Nous voulons maintenant juste ce qui suit videoId.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #008000;">dir</span><span style="color: black;">&#40;</span>soup.<span style="color: black;">find</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'div'</span>,attrs=<span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;class&quot;</span>:u<span style="color: #483d8b;">&quot;block-common block-player-programme&quot;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>.<span style="color: black;">find</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'canal:player'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>montre, entre autres choses, que la méthode get est disponible.<br />
Pour récupérer l&#8217;identifiant qui nous intéresse, on peut donc faire</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> soup.<span style="color: black;">find</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'div'</span>,attrs=<span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;class&quot;</span>:u<span style="color: #483d8b;">&quot;block-common block-player-programme&quot;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>.<span style="color: black;">find</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'canal:player'</span><span style="color: black;">&#41;</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'videoid'</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'975153'</span></pre></div></div>

<p>ou utiliser une autre syntaxe</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> soup.<span style="color: black;">find</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'div'</span>,attrs=<span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;class&quot;</span>:u<span style="color: #483d8b;">&quot;block-common block-player-programme&quot;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>.<span style="color: black;">find</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'canal:player'</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'videoid'</span><span style="color: black;">&#93;</span>
<span style="color: #483d8b;">'975153'</span></pre></div></div>

<p>De la même manière, on peut récupérer le titre de la vidéo</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> soup.<span style="color: black;">find</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'h3'</span>,attrs=<span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;class&quot;</span>:u<span style="color: #483d8b;">&quot;bpp-title&quot;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'&lt;h3 class=&quot;bpp-title&quot;&gt;Longmire - Samedi 30 novembre à 20h50&lt;/h3&gt;'</span></pre></div></div>

<p>mais on veut juste le titre, donc</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> soup.<span style="color: black;">find</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'h3'</span>,attrs=<span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;class&quot;</span>:u<span style="color: #483d8b;">&quot;bpp-title&quot;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>.<span style="color: black;">text</span>
<span style="color: #dc143c;">uu</span><span style="color: #483d8b;">'Longmire - Samedi 30 novembre <span style="color: #000099; font-weight: bold;">\x</span>e0 20h50'</span></pre></div></div>

<p>Maintenant que l&#8217;on a le numéro de la vidéo, on peut le passer au site qui contient l&#8217;adresse, et avec un peu de scripting XML, récupérer l&#8217;adresse de la vidéo (un autre article sera consacré au scripting XML)<br />
Selon que la vidéo vient de D8 ou de canal, elle sera sur<br />
<a href="http://service.canal-plus.com/video/rest/getVideosLiees/d8/">vidéo de d8</a><br />
ou<br />
<a href="http://service.canal-plus.com/video/rest/getVideosLiees/cplus/">vidéo de Canal Plus</a><br />
et avec un peu de code</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> lxml <span style="color: #ff7700;font-weight:bold;">import</span> objectify
<span style="color: #ff7700;font-weight:bold;">def</span> get_HD<span style="color: black;">&#40;</span>d8_cplus,vid<span style="color: black;">&#41;</span>:
    root = objectify.<span style="color: black;">fromstring</span><span style="color: black;">&#40;</span>urlopen<span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://service.canal-plus.com/video/rest/getVideosLiees/'</span>+d8_cplus+<span style="color: #483d8b;">'/'</span>+vid<span style="color: black;">&#41;</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> root.<span style="color: #008000;">iter</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> x.<span style="color: black;">tag</span> == <span style="color: #483d8b;">'VIDEO'</span> <span style="color: #ff7700;font-weight:bold;">and</span> x.<span style="color: black;">ID</span>.<span style="color: black;">text</span> == vid:
            <span style="color: #ff7700;font-weight:bold;">for</span> vres <span style="color: #ff7700;font-weight:bold;">in</span> vidattr:
                <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">hasattr</span><span style="color: black;">&#40;</span>x.<span style="color: black;">MEDIA</span>.<span style="color: black;">VIDEOS</span>, vres<span style="color: black;">&#41;</span>:
                    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Resolution :'</span>, vres
                    videoUrl = <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span>x.<span style="color: black;">MEDIA</span>.<span style="color: black;">VIDEOS</span>, vres<span style="color: black;">&#41;</span>.<span style="color: black;">text</span>
                <span style="color: #ff7700;font-weight:bold;">break</span>
        <span style="color: #ff7700;font-weight:bold;">break</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> videoUrl
<span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">'d8'</span>,<span style="color: #483d8b;">'cplus'</span><span style="color: black;">&#93;</span>:
    get_HD<span style="color: black;">&#40;</span>x,vid<span style="color: black;">&#41;</span></pre></div></div>

<p>on peut trouver l&#8217;adresse de la vidéo.<br />
Il reste juste à envoyer la commande rtmpdump, dans ce cas</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">rtmpdump -r rtmp://ugc-vod-fms.canalplus.fr/ondemand/videos/1311/LONGMIRE___BANDE_ANNONCE__131120_UGC_3279_video_HD.mp4 -c 1935 -m 10 -B 1 -o mavideo.mp4</pre></div></div>

<p>Voilà, il reste à noter que BeautifulSoup peut restreindre sa recherche à une partie du document, utiliser <a href="http://www.crummy.com/software/BeautifulSoup/bs4/doc/#a-regular-expression">une regex</a> (même si <a href="http://sametmax.com/comment-parser-de-html-avec-des-regex/">c&#8217;est le mal</a>), on peut <a href="http://www.crummy.com/software/BeautifulSoup/bs4/doc/#the-limit-argument">limiter la taille de la liste renvoyée par findAll</a></p>
<p>Quelles sont les méthodes les plus utiles, si vous avez la flemme de lire toute la doc ?</p>
<ul>
<li>.contents, les enfants d&#8217;un tag sont disponibles dans une liste appelée .contents</li>
<li>.has_key(&#8216;value&#8217;) vous rendra de grands services, associé parfois à

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: black;">&#91;</span><span style="color: #483d8b;">'value'</span><span style="color: black;">&#93;</span> <span style="color: #66cc66;">!</span>= u<span style="color: #483d8b;">''</span></pre></div></div>

</li>
<li>pour extraire un tag sans attribut, par exemple pour un tag p, la syntaxe sera simplement

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">soup.<span style="color: black;">findAll</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'p'</span>, <span style="color: black;">&#123;</span><span style="color: #483d8b;">'class'</span>: <span style="color: #008000;">None</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span></pre></div></div>

</li>
<li>.attrs vous affichera un dictionnaire qui peut être intéressant, par exemple :

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span>soup.<span style="color: black;">head</span>.<span style="color: black;">link</span>
 <span style="color: #483d8b;">'&lt;link href=&quot;http://media.canal-plus.com/design_pack/front_office_d8/css/d8.d25540b7a93dba7baf89e5ca53ef00e5.min.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot;/&gt;'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> soup.<span style="color: black;">head</span>.<span style="color: black;">link</span>.<span style="color: black;">attrs</span>
 <span style="color: black;">&#123;</span><span style="color: #483d8b;">'href'</span>: <span style="color: #483d8b;">'http://media.canal-plus.com/design_pack/front_office_d8/css/d8.d25540b7a93dba7baf89e5ca53ef00e5.min.css'</span>, <span style="color: #483d8b;">'type'</span>: <span style="color: #483d8b;">'text/css'</span>, <span style="color: #483d8b;">'rel'</span>: <span style="color: black;">&#91;</span><span style="color: #483d8b;">'stylesheet'</span><span style="color: black;">&#93;</span><span style="color: black;">&#125;</span></pre></div></div>

</li>
<li>.previousSibling (et .next_sibling) peut être utile, par exemple, avec un simple HTML comme ce qui suit

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;div class=&quot;category_link&quot;&gt;
Category:
&lt;a href=&quot;/category/personal&quot;&gt;Personal&lt;/a&gt;
&lt;/div&gt;</pre></div></div>

<p>    on peut récupérer la chaîne Category : de plusieurs manières, par exemple l&#8217;évident</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> soup.<span style="color: black;">findAll</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'div'</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: black;">contents</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
u<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\n</span>  Category:<span style="color: #000099; font-weight: bold;">\n</span>  '</span></pre></div></div>

<p>	mais aussi en remontant depuis la balise a</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> soup.<span style="color: black;">find</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: black;">&#41;</span>.<span style="color: black;">previousSibling</span>
u<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\n</span>  Category:<span style="color: #000099; font-weight: bold;">\n</span>  '</span></pre></div></div>

<p>	Sinon cela est aussi utile avec un HTML mal foutu comme</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;p&gt;z1&lt;/p&gt;tagada
&lt;p&gt;z2&lt;/p&gt;tsointsoin</pre></div></div>

<p>	Dans ce cas, pour récupérer tagada tsointsoin<br />
	on fera par exemple</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">soup.<span style="color: black;">findAll</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'p'</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: black;">next_sibling</span>
soup.<span style="color: black;">findAll</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'p'</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;">next_sibling</span></pre></div></div>

<p>ou, pour faire plaisir à Sam/Max</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: black;">&#91;</span>p.<span style="color: black;">next_sibling</span> <span style="color: #ff7700;font-weight:bold;">for</span> p <span style="color: #ff7700;font-weight:bold;">in</span> soup.<span style="color: black;">findAll</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'p'</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
<span style="color: black;">&#91;</span>u<span style="color: #483d8b;">'tagada'</span>, u<span style="color: #483d8b;">'tsoitsoin'</span><span style="color: black;">&#93;</span></pre></div></div>

<li>A quoi sert text=True ?<br />
	Simplement à récupérer juste du texte dans du Html, sans toute la syntaxe HTML.<br />
	Un exemple, toujours sur la vidéo de D8 va illustrer cela</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> soup.<span style="color: black;">findAll</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'div'</span>, <span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;class&quot;</span>:<span style="color: #483d8b;">&quot;tmlog-wdrw wdrw&quot;</span><span style="color: black;">&#125;</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: black;">a</span>
<span style="color: #483d8b;">'&lt;a class=&quot;tmlogin-btn&quot; href=&quot;#&quot;&gt;'</span>
<span style="color: #483d8b;">'&lt;span&gt;Se connecter&lt;/span&gt;'</span>
<span style="color: #483d8b;">'&lt;/a&gt;'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> soup.<span style="color: black;">findAll</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'div'</span>, <span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;class&quot;</span>:<span style="color: #483d8b;">&quot;tmlog-wdrw wdrw&quot;</span><span style="color: black;">&#125;</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: black;">a</span>.<span style="color: black;">contents</span>
 <span style="color: black;">&#91;</span>u<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\n</span>'</span>, <span style="color: #66cc66;">&lt;</span>span<span style="color: #66cc66;">&gt;</span>Se connecter<span style="color: #66cc66;">&lt;</span>/span<span style="color: #66cc66;">&gt;</span>, u<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\n</span>'</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> soup.<span style="color: black;">findAll</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'div'</span>, <span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;class&quot;</span>:<span style="color: #483d8b;">&quot;tmlog-wdrw wdrw&quot;</span><span style="color: black;">&#125;</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: black;">a</span>.<span style="color: black;">text</span>
 u<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\n</span>Se connecter<span style="color: #000099; font-weight: bold;">\n</span>'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> soup.<span style="color: black;">findAll</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'div'</span>, <span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;class&quot;</span>:<span style="color: #483d8b;">&quot;tmlog-wdrw wdrw&quot;</span><span style="color: black;">&#125;</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: black;">a</span>.<span style="color: black;">findAll</span><span style="color: black;">&#40;</span>text=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
 <span style="color: black;">&#91;</span>u<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\n</span>'</span>, u<span style="color: #483d8b;">'Se connecter'</span>, u<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\n</span>'</span><span style="color: black;">&#93;</span></pre></div></div>

</li>
<li> Une dernière chose, si vous avez besoin de parser des documents de plusieurs centaines de Mo et donc de performances, oubliez le parser HTML par défaut dans BeautifulSoup, et <a href="http://www.crummy.com/software/BeautifulSoup/bs4/doc/#installing-a-parser">installez</a> le rapide <a href="http://lxml.de/performance.html">lxml</a> ou un autre parser. Si comme moi vous traitez des documents &#8220;petits&#8221;, ça n&#8217;a pas d&#8217;importance.
</ul>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=6161&amp;md5=6ac8150f5a8c26f9d85342a659aceba8" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8885
title: Backstage de ces derniers jours
uri: Backstage-de-ces-derniers-jours
url: http://sametmax.com/backstage-de-ces-derniers-jours/
content:
<pre>vendredi 24 janvier 2014

[15:43:09] Sam: … ho bordel ça buzz sur FB et twitter ton article
-> 20 000 vues en 2 jours. Putain de record. Essentiellement parce
qu'on a été posté par Korben.
[15:43:26] Max: mmm nan je pense que c FB
[15:43:26] Sam:  hey quand même non !!!
 http://sitedeculdemax.com/sprite.jpg   ça déchirrrre !!! ->
 elle est pas black black non plus, plutôt metisse
[15:43:30] Sam: mais c'est vrai que c'est beau
[15:43:46] Sam: oui fb, mais fb nous a connu grace à korben
[15:43:47] Max: hehe
[15:43:53] Max: ha ok
[15:44:07] Sam: suis en train de penser à un truc, faudrait remplacer
la recherche du blog par le widget de recherche google car la
recherche wordpress est nulle et fait bouriner le serveur, et que
google lui a tout indexé comme il faut, à voir si ça cadre avec ta
deontologie :) -> y a peut être une solution alternative
[15:44:20] Sam: il me smeble qu'il y a des services pour ça
[15:44:25] Sam: autre que google
[15:44:33] Sam: car c'est vrai que là c'est super nul
[15:45:06] Max: je dois pouvoir faire mieux en terme de detection de
blur, je viens de trouver des scripts pour detecter les lignes et
quadrillage, faudrait que j'adapte ça à mes images et que je floutte
ces parties pour ne prendre en compte que les formes arrondies
(nichons, fesses, tete de salope), à mon avis ça pourrait améliorer
[15:45:22] Sam: lol
[15:45:24] Max: ben si t'as un autre truc dis, mais là ça sert à rien
c clair
[15:45:25] Sam: que les formes arondies
[15:45:50] Max: vi
[15:45:57] Max: pour detecter ça a pas l'air trop dur
[15:46:33] Max: apres j'aime pas opencv, pas reussi à installer sur
mon mac, il compile plein de trucs, c lourd comme machine, y a ptet
moyen avec PIL, faut voir
[15:48:07] Max: http://sitedeculdemax.com
[15:48:08] Max: c en prod là
[15:48:29] Max: mais faut attendre que je traite toutes les autres
images, ça tourne sur les serveurs pour recalculer blur, etc
[15:48:44] Max: me tâte meme pour rescreenshooter les anciennes
video :)
[15:48:54] Sam: tu sais, si aucune image n'atteind un certain
seuil de qualité
[15:49:04] Sam: tu devrais exclure la video des 3 premières pages
[15:49:12] Max: c fait deja
[15:49:15] Sam: car là il y a 3 / 4 degueu qui ont rien à foutre là
[15:49:24] Max: la premiere page prend que les top quality
[15:49:30] Max: ouais mais certaines passe à travers :/
[15:49:37] Max: genre quand y a des gros pixel
[15:49:44] Max: c compté comme quadrillage
[15:49:49] Sam: logique
[15:49:53] Max: d'où ma necessité d'améliorer
[15:50:00] Max: pareil si y a du carelage, du fishnet, etc
[15:50:14] Max: du coup ça fausse la moyenne
[15:52:13] Max: c quand meme bon là http://sitedeculdemax.com/last
[15:52:46] Sam: clairement mieux qu'avant
[15:54:34] Max: y a des chances que je raplique un peu en aout au
fait, pour faire un fkk, si ça te dit :)
[15:54:41] Max: ou ptet avant meme...
[16:04:19] Sam: pourquoi pas
[16:04:25] Sam: d'ici aout ça fait loin cela dit
[16:04:39] Max: ouais mais je previens quand meme
[16:05:06] Max: en general on se previent avant avec picsou ça
permet de so'rganiser, d'avoir des bons tarifs, mouiiii c pas cher
[16:05:14] Sam: ^^
[16:11:48] Max: hooo putain
[16:11:52] Max: 16000 vues !
[16:11:57] Max: et le serveur tiens le coup :)
[16:12:03] Sam: merci varnish
[16:12:05] Sam: merci Max
[16:12:38] Max: faut que j'aille voir dans quel etat il est :)
[16:12:43] Max: ptet c en train de mourir
[16:13:29] Max: ça tiens le coup
[16:13:36] Max: 2.5 de load average
[16:13:44] Max: ça a l'air stable
[16:13:55] Max: bon on sait qu'on peut faire 15K / jour
[16:14:00] Max: pour 4€ ça va
[16:16:24] Sam: ^^
[16:18:47] Sam: AH oui là c'est clairement facebook
[16:23:36] Max: tin faut mettre une pop under avec du carpédiem ^^
[16:24:33] Sam: en fait, faut arrêter de faire des articles python
 tous les jours
[16:24:36] Sam: juste un article de cul par mois
[16:24:38] Sam: ça suffit
[16:25:08] Max: :)
[16:25:16] Max: par contre le partage c pas top on m'a dit
[16:25:27] Max: un truc mainstream comme ça faut un gros boutons
"partager sur fb"
[16:25:32] Max: on vient de me faire la remarque
[16:25:46] Max: les gens savent pas copier coller une url, savent pas
ce que c une url deja...
[16:25:55] Sam: Ouai, déjà que j'ai horreur de ces boutons, on va pas
non plus leur faire une place spéciale avec un podium
[16:25:57] Max: c con on perd du potentiel là
[16:26:04] Max: le trafic !
[16:26:06] Max: le trafic !
[16:26:06] Sam: c'est très bien si ça filtre les abrutis
[16:26:08] Sam: m'en fout
[16:26:12] Max: le trafic !
[16:26:14] Sam: je veux pas du traffic d'abrutis sur ce blog
[16:26:18] Max: c'est l'or noir du webmaster
[16:26:22] Max: le saint graal !
[16:26:25] Sam: ranafout
[16:26:28] Max: le fromage de tête !
[16:26:35] Sam: on a un super publique
[16:26:41] Sam: c'est entre autre parcequ'on écrème les cons
[16:26:41] Max: t'es pas commercial pour un sou :)
[16:26:48] Sam: au contraire
[16:26:51] Sam: je suis comme cartman
[16:26:58] Sam: et son park d'atttraction
[16:27:02] Max: oui c vrai, mais bon là ça va attirer les cons
[16:27:02] Sam: c'est une stratégie commerciale
[16:27:06] Sam: "vous pouvez pas rentrer"
[16:27:08] Max: j'attends caroline fourest...
[16:27:20] Max: stan et kule en particulier
[16:27:33] Sam: plus je regarde cette série
[16:27:38] Sam: plus je trouve qu'elle a du génie
[16:28:26] Max: depuis le temps que je le dis...
[16:28:33] Max: ça et al bamby...
[16:28:39] Max: tout le reste c'est à jetter
[16:28:40] Sam: Ouai mais je te fais jamais confiance
[16:28:46] Sam: avec toi y a un ratio de 1 sur 100
[16:28:51] Sam: le 1 est de l'or
[16:28:53] Sam: j'avoues
[16:28:56] Sam: mais ça fait beaucoup à filtrer
[16:28:57] Max: nan c'est l'instinc :)
[16:33:08] Max: sur les 16000 vis, pas un connard c'est inscrit à la
newsletter, c vrai que c du traf de merde quand meme
[17:07:16] Max: 20k !
[17:07:18] Max: ça va péter !
[17:07:24] Max: le serveur chie des bulles là
[17:07:27] Max: alerte rouge !
[17:07:32] Sam: lol
[17:07:51] Sam: ça va il répond toujours vite
[17:07:56] Max: je vais tout rediriger sur sitedeculdemax.com ^^
[17:07:59] Sam: lol
[17:08:35] Max: pinaise c mortel ces buzzs quand même
[17:10:16] Max: une fois j'avais fait un buzz comme ça avec un truc
de téléphone geoloc, ct monté à 100k, si ça fait pareil ça va chier
 pour le serv
[17:10:27] Max: par contre de nos jours le hic c que le buzz retombe
et paf
[17:10:41] Max: avant ça faisait du backlink dans les forums, les
blogs etc
[17:11:01] Max: depuis FB et twitters les buzzs ne font plus gagner
de PR, ça s'etouffe dans le gouffre de l'internet
[17:13:02] Sam: ça s'étouffe dans le gouffre de facebook
[17:13:06] Sam: car facebook est une boite noire
[17:13:12] Sam: non indexée par les moteurs de recherche
[17:13:15] Sam: avec de l'info jetable
[17:13:20] Max: ben vouais
[17:13:21] Sam: que personne n'ira relire, comme sur un forum
[17:13:22] Max: c triste
[17:16:02] Sam: je crois que je vais poster cette conversation sur le
 blog
[17:16:16] Sam: ça fait longtemps qu'on a pas eu un post "en couliss"
[17:20:19] Max: tin g tjrs pas trouvé la bonne cochonne pour l'aricle
du gode en pyrex...
[17:21:46] Sam: je l'attend de pied ferme
[17:30:56] Max: mouiii
[17:31:08] Max: ça existe un snippet pour avoir un manager pour foutre
 du code en cache ?
[17:31:20] Max: genre là dans le model de Video on a pas mal de trucs
 en caches
[17:31:46] Max: mais à chaque on appelle REDIS.set ... ou on utilise
le cache django mais un manager ça serait ptet pas mal
[17:32:00] Sam: oui, y a django-cache-machine et johny-cache font ça
via des managers
[17:32:09] Max: ha, mais ct l'usine non ?
[17:32:16] Sam: ah oui faut pas rêver
[17:32:22] Max: on els avaient pas utilisé pour leur côté compliqué
 il me semble ?
[17:32:29] Max: mouais
[17:32:33] Sam: forcément, un modèle c'est compliqué
[17:32:38] Sam: y a des relations dans tous les sens
[17:32:41] Max: vouais
[17:32:43] Sam: pour avoir un cas généralisable à tout
[17:32:48] Sam: faut un truc costaus
[17:32:59] Max: d :)
[17:33:12] Max: ouais faut couvrir toutes les possibilités
[...]
[17:43:16] Sam: ah, ça y est, S&#038;m est en 500
[17:44:26] Max: il a pas tenu le coup
[17:44:30] Max: paix à son âme
[17:48:12] Max: je stoppe varnish et php qui continue à être à 100% de
 cpu...
[17:48:21] Sam: forcément
[17:48:23] Max: tin faut un blog en python homemade
[17:48:36] Sam: c'est mort, on code pas un blog
[17:50:01] Max: bon g redem php
[17:50:04] Max: c lent maisça marche
[17:50:09] Max: faudrait augmenter le timeout de nginx
[17:50:25] Max: mais ça veut dire aussi plus de cnx // qui attendent
et embourbe le tout
[18:46:48] Max: y a rien à faire Mr Sam
[18:46:52] Max: on a tout essayé
[18:47:06] Max: il est mort sur le coup suite à une longue intoxication
[18:47:20] Sam: c'est la vie
[18:47:30] Sam: on saura jamais combien de personnes sont vraiment venues
[18:47:39] Sam: et le blog sera inaccessible jusqu'à demain
[18:48:03] Max: au moins ouais
[18:48:09] Max: en meme temps c pas fait pour ça
[18:48:13] Max: ptit serveur
[18:48:18] Max: il chie sa mere là
[19:20:42] Max: y a vraiment quelqu'un qui tape à mort dans le feed
[19:20:43] Max:     46.44 RxURL
/beaucoup-de-femmes-sont-de-mauvais-coups/
    35.45 RxURL          /feed/
[19:20:57] Max: à gauche c le nb de requete sur l'url ces 60
dernieres seconds
[19:21:10] Max: presque une req / s sur l'url du feed
[19:46:30] Max: bon le site est reup car j'ai forbidden les /feed/
et /beaucoup de femme..../ , ces pages sont doncs réduites au silence
 pour éviter que tout le site en patisse
[20:16:57] Max: bon g fait une modif asser marrante, je force le
serveur à servir les pages en foutant un timeout infin, du coup le
site est up, la page se charge au bout de très lgtps mais au moins
elle se charge, j'ai le serveur sous les yeux pour voir quand il va
 brûler, là 7 de load average, il peut mieux faire :)
[20:17:32] Max: ce qui ne vous tue pas vous rend plus fort.. courage
 français, ça va zouker !!
[20:36:06] Max: cawpitain cawpitain ça tiens lew coup !!

samedi 25 janvier 2014

[13:30:58] Sam: ça a tenu
[13:31:03] Sam: tu as remis le feed up ?
[13:31:54] Max: si senior
[13:31:59] Sam: good
[13:32:10] Max: g augmenté le timeout fastcgi sur nginx
[13:32:30] Max: du coup ça a tenu, sauf que le serv est monté à 7/8 de load
[13:32:37] Max: mais bon, pas grave
[13:32:39] Sam: c'est poétique
[13:32:52] Max: c à 10k là
[13:33:10] Max: on dirait qu'il y a une rémanence :)
[13:33:14] Sam: il est que midi
[13:33:39] Sam: J'aurais pas du posté l'article sur beautiful soup
 hier
[13:33:44] Sam: j'aurais du en mettre un moins important
[13:33:50] Sam: car je pense que du coup il a perdu en visibilité
[13:34:07] Sam: alors que y a un sacré boulot dessus
[13:34:34] Max: clair
[13:34:45] Sam: sinon j'ai vu "sunshine" en film hier
[13:34:48] Sam: très très bon
[13:34:50] Sam: je te le recommande
[13:34:58] Max: bé il est vieux
[13:34:59] Sam: ouai
[13:35:02] Max: ouais pas trop mal
[13:35:43] Sam: ah, au fait, tu sais on se demandait quoi offrir pour
le prochain concourt
[13:35:48] Sam: ben on m'a donné une super idée
[13:35:52] Sam: un GROS fromage
[13:36:02] Max: bé on avait dit xxxx
[13:36:09] Max: un gros fromage ?
[13:36:11] Sam: un gros fromage
[13:36:18] Sam: genre une roue de parmesan
[13:36:22] Sam: un truc bien gros
[13:36:28] Sam: parceque le fromage, c'est bon
[13:36:39] Sam: et y en a marre des trucs electronique
[13:37:09] Sam: et je pense qu'il faut sensibiliser le lectorat à la
beauté du fromage
[13:37:31] Sam: d'ailleurs, ça te manque pas le fromage chez les thai ?
[13:38:21] Max: nan y a tout ce qui faut en fromage ici, des ryaons
entiers, de l'import
[13:38:39] Max: une roue de parmesan ça doit couter dans les 500 / 1000 €
[13:38:53] Max: deja le petit bout de merde 100 grs c'est 4€ au leclerc
[13:39:01] Sam: ouai c'était pour l'exemple
[13:39:06] Sam: le parmesan c'est hors de nos moyen
[13:39:09] Max: sans compter le poids du merdie en terme de tarif de
livraison
[13:39:16] Sam: c'est clair
[13:39:20] Max: enfin bon ça se périme déjà
[13:39:29] Max: donc c mort, si le mec est celib ça partira à la poubelle
[13:39:40] Max: mais la bouffe bof
[13:39:44] Sam: ça se garde super bien le fromage, t'abuse
[13:39:49] Max: bcp de gens sont "spéciaux"
[13:39:52] Sam: moi j'étais super enthousiaste
[13:39:53] Max: pas une fois ouvert
[13:40:07] Sam: ou alors on laisse le choix : fromage ou xxxxx ?
[13:40:08] Sam: lol
[13:40:13] Max: si tu ouvre un sachet de parmesan ou meme un morceaud
e parmesans sous vide faut le consommer rapidos
[13:40:17] Max: :)
[13:40:18] Sam: une proposition unique dans une vie
[13:40:25] Max: bcp de gens aiment pas ça
[13:40:36] Sam: et ben c'est tous des nuls
[13:40:39] Sam: ils méritent pas un cadeau
[13:40:46] Max: certains ont meme des lubbies, genre regime dukan,
vegetariens, vegetaliens, etc... :)
[...]
[13:41:21] Max: et pis bon la bouffe c'est plus la france, maintenant
c macdo et cie
[13:41:23] Sam: c'est pas possible
[13:41:29] Sam: c'est pas faux
[13:41:55] Max: les epicuriens sont tres rares
[13:42:02] Max: c un coup de poker je trouve
[13:42:09] Max: pis c con d'annoncer le cadeau à l'avance
[13:42:13] Max: la suprise c chouette aussi
[13:42:24] Max: sinon un resto atype mais bon faut l'adresse
[13:42:32] Sam: je passe
[13:42:42] Sam: def sam(): pass
[13:42:49] Max: d'ailleurs ptit resto francais hier
[13:42:53] Max: endives au jambon avec bechamel
[13:43:05] Max: jamais j'ai eu droit à de la vrai béchamel en france,
 tjrs de la conserve
[13:43:06] Sam: bon en tout cas, xxxxx je sens que ça va foirer,
[13:43:09] Sam: faut trouver autre chose
[13:43:12] Max: ha
[13:43:49] Sam: ben oui : genre on tombe pas sur un codeur mais un
policier, un biologiste ou, dieu nous en garde, un hipster
[13:44:55] Sam: y a pas tant de codeurs que ça sur le blog finalement
[13:45:05] Max: mouiii
[13:45:07] Sam: et dans le lot, plein ont des ide qu'ils préfèrent
[13:45:11] Max: je réfléchis
[13:45:22] Sam: va faire caca, ça te réussi
[13:45:46] Sam: j'aurais bien offert un stage de survie chez david
manise, mais c'est un peu cher
[13:45:52] Sam: par contre c'est super cool
[13:46:23] Sam: le casque que j'ai acheter dernièrement est
fantastique cela dit
[13:46:27] Sam: et tout le monde aime les casques
[13:46:39] Sam: tout le monde en a besoin pour un truc ou un autre
[13:46:44] Max: ouais y avait ça ou la jambox
[13:46:44] Sam: et il est à 60 euros
[13:46:49] Sam: la jambox c'est hors budget
[13:46:53] Max: mais bon c classique
[13:46:55] Sam: clair
[13:46:59] Sam: ça maque d'attrait
[13:47:43] Max: un gode en pyrex fait main
[13:48:15] Sam: j'aime l'idée, mais je pense qu'on a pas non plus une
 majorité de chauds lapins qui vont jouer
[13:48:36] Sam: généralement la capacité à résoudre un casse tête est
 inversement proportionnel à la capacité à chopper
[13:48:39] Max: bon je vais chier
[13:48:41] Max: ça s'impose
[13:48:47] Sam: je vais me faire à bouffer
[13:48:49] Sam: moi je rentre
[13:48:50] Sam: toi tu sors
[13:48:53] Sam: on est syncro
[...]
[16:18:47] Max: j'ai trouvé ces cookies:

http://www.pepperidgefarm.com/ProductDetail.aspx?catID=723&#038;prdID=112059

[16:18:52] Max: c horrible chui accroc
[16:18:56] Max: pourtant j'aime pas le sucre
[16:19:07] Sam: c'est vrai qu'ils sont bons
[16:19:14] Max: 10 grs de sucre pour un cookie de 26 grs...
</pre>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8885&amp;md5=b6dc07f344c7f14fd575251df0183e87" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8896
title: La différence entre paramètres et arguments
uri: La-différence-entre-paramètres-et-arguments
url: http://sametmax.com/la-difference-entre-parametres-et-arguments/
content:
<p>On a tendance à utiliser l&#8217;un pour l&#8217;autre, et inversement. Moi-même je le fais régulièrement, y compris dans plein d&#8217;articles de ce blog. Mais il y a pourtant une différence sémantique, bien que dans la pratique on s&#8217;y retrouve.</p>
<p>Les paramètres sont les noms que l&#8217;on spécifie dans la signature de la fonction :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> ma_fonction<span style="color: black;">&#40;</span>arg1, arg2=<span style="color: #483d8b;">'valeur'</span>, <span style="color: #66cc66;">*</span>args<span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># faire un truc</span></pre></div></div>

<p>Ici <code>arg1</code>, <code>arg2</code> et <code>args</code> sont des paramètres. Ce sont les noms des différents points d&#8217;entrée de données dans la fonction.</p>
<p>Les arguments sont les valeurs passées à l&#8217;appel de la fonction :</p>

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

<p><code>'foo'</code> et <code>'bar'</code> sont des arguments. C&#8217;est ce que l&#8217;on passe via les différents points d&#8217;entrée dans la fonction, au moment de son utilisation.</p>
<p>Maintenant, pour les tatillons, ce n&#8217;est valable que pour ceux qui aiment les anglicismes. Car en français, normalement, on a que le mot &#8220;paramètre&#8221;, et on utilise :</p>
<ul>
<li>&#8220;Paramètre formel&#8221; traduire &#8220;parameter&#8221;. </li>
<li>&#8220;Paramètre effectif&#8221; pour traduire &#8220;argument&#8221;.</li>
</ul>
<p>Certaines personnes, qui aiment bien embrouiller les choses, parlent d&#8217;&#8221;argument muet&#8221; pour traduire &#8220;parameter&#8221;. Mais on va pas trop se plaindre, car les anglais ont <a href="https://en.wikipedia.org/wiki/Independent_variable#Independent_variable">encore plus de synonymes la con</a> pour parler des paramètres et arguments.</p>
<p>Bref, en résumé : on <strong>définit</strong> des paramètres, et on <strong>passe</strong> des arguments. Je continuerai probablement à mélanger les deux moi-même, alors détendez-vous du slip.</p>

<!-- iframe plugin v:2.3 - wordpress.org/extend/plugins/iframe/ -->
<iframe width="420" height="315" src="//www.youtube.com/embed/lItyCpRny-E" frameborder="0" scrolling="no" class="iframe-class"></iframe>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8896&amp;md5=7a83399d6d2d90a85c732cad83151bed" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8903
title: Cog, l’anti langage de template Python
uri: Cog-l-anti-langage-de-template-Python
url: http://sametmax.com/cog-lanti-langage-de-template-python/
content:
<p><a href="http://nedbatchelder.com/code/cog/">Cog</a> est un outil Python en ligne de commande qui permet d&#8217;insérer du code Python dans un fichier, afin qu&#8217;il génère une partie de ce fichier.</p>
<p>A priori, ça ressemble à un langage de template. Là où ça diffère, c&#8217;est que cog ne cherche pas à générer un fichier différent, il insère le code généré dans le fichier original, et garde le code de génération.</p>
<p>Exemple, vous avez envie d&#8217;insérer un warning en haut de plusieurs fichiers de code. Vos choix :</p>
<ul>
<li>Copier-coller le warning.</li>
<li>Créer un script de build qui insère le warning.</li>
</ul>
<p>L&#8217;alternative des bricoleurs qui ont juste besoin de quelques insertions, c&#8217;est Cog. Par exemple, votre fichier contient :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># [[[cog for l in open('warning.txt'): cog.out(&quot;# &quot; + l) ]]]</span>
<span style="color: #808080; font-style: italic;"># [[[end]]]</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> vostrucs
&nbsp;
vostrucs.<span style="color: black;">faire_vos_machins</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Après un <code>cog.py -r votre_fichier.py</code>, votre fichier sera :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># [[[cog for l in open('warning.txt'): cog.out(&quot;# &quot; + l) ]]]</span>
<span style="color: #808080; font-style: italic;"># Attention, ceci est un avertissmement super important.</span>
<span style="color: #808080; font-style: italic;"># Ce logiciel ne vient avec aucune garantie. Il vomira dans votre salon.</span>
<span style="color: #808080; font-style: italic;"># Violera votre femme, lui collera l'hépatite C et offrira un CD de one direction</span>
<span style="color: #808080; font-style: italic;"># à vos enfants.</span>
<span style="color: #808080; font-style: italic;"># [[[end]]]</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> vostrucs
&nbsp;
vostrucs.<span style="color: black;">faire_vos_machins</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>cog vient avec plusieurs options, par exemple la possibilité de retirer le code de génération ou de lire le précédent texte généré depuis le code de génération.</p>
<p>La véritable force de l&#8217;outil c&#8217;est qu&#8217;il peut utiliser n&#8217;importe quel module Python, et donc générer du texte à partir d&#8217;un contenu en ligne ou un fichier CSV. Il est d&#8217;ailleurs né parce que l&#8217;auteur était codeur C et avait besoin de générer du code à partir d&#8217;un fichier XML.</p>
<p>Le seul défaut de Cog, c&#8217;est que c&#8217;est verbeux. Et moche.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8903&amp;md5=c0ca287d24dbc08e6b0640087a6ec7fa" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8910
title: C’est l’heure de faire de l’exercice
uri: C-est-l-heure-de-faire-de-l-exercice
url: http://sametmax.com/cest-lheure-de-faire-de-lexercice/
content:
<p>Le <a href="http://sametmax.com/petit-exercice-en-python/">dernier exercice</a> avait bien été apprécié, alors je remet ça.</p>
<p>Consigne :</p>
<p><em><br />
Créer un script de brute force de passwords Unix par dictionnaire.</p>
<p>Puisqu&#8217;on est pas non plus des Kevin Mitnick en puissance, on va supposer que vous êtes connectés sur la machine, que vous avez les droits root dessus et que vous avez localisé les mots de passe comme étant dans &#8220;/etc/shadow&#8221;.</p>
<p>Votre script va vérifier si il possède un dictionnaire de mots de passe. Si ce n&#8217;est pas le cas, il va télécharger celui-ci et le décompresser : <a href="http://xato.net/files/10k%20most%20common.zip">http://xato.net/files/10k%20most%20common.zip.</a></p>
<p>Ensuite vous parcourez le fichier shadow, et vous essayez de trouver quel mot de passe se cache  derrière chaque hash. Si il n&#8217;y a pas de hash, vous pouvez ignorer l&#8217;utilisateur.</p>
<p>Exemple de sortie:</p>
<pre>
Processing password for user "root": no password hash to process.
Processing password for user "daemon": no password hash to process.
Processing password for user "bin": no password hash to process.
Processing password for user "sys": no password hash to process.
Processing password for user "www-data": no password hash to process.
Processing password for user "sam": fail to break password.
Processing password for user "test": password is "cheese".
Processing password for user "messagebus": no password hash to process.
Processing password for user "avahi-autoipd": no password hash to process.
Processing password for user "avahi": no password hash to process.
...</pre>
<p></em></p>
<p>Afin de simplifier l&#8217;exercice, il n&#8217;est pas demandé de gestion d&#8217;erreur ou de passage en a paramètre du script.</p>
<p>Comme d&#8217;habitude, il n&#8217;y a pas de solution ultimate de la mort qui tue, c&#8217;est juste pour le fun.</p>
<p><a href="http://sametmax.com/solution-de-lexercice-dhier-sur-shadow/">La soluce demain.</a></p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8910&amp;md5=31cd416f11850ac5dcbd198c2c995342" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8917
title: Solution de l’exercice d’hier sur shadow
uri: Solution-de-l-exercice-d-hier-sur-shadow
url: http://sametmax.com/solution-de-lexercice-dhier-sur-shadow/
content:
<p>Ça va de soit, mais ça va mieux en le disant, ceci n&#8217;est pas la solution unique de l&#8217;<a href="http://sametmax.com/cest-lheure-de-faire-de-lexercice/#comment-19118">exercice d&#8217;hier</a>, mais une solution possible parmi d&#8217;autres.</p>
<p>On note l&#8217;usage de <a href="http://docs.python.org/2/library/crypt.html?highlight=crypt#crypt">crypt</a>, qui évite de se faire chier à trouver le bon algo de hashing et gère le salt automatiquement. <a href="http://docs.python.org/2/library/spwd.html?highlight=spwd#spwd">spwd</a>, c&#8217;est vraiment pour le grosses larves comme moi qui veulent même pas faire un <code>split</code>.</p>
<p>Et c&#8217;est du Python 3, yo dog !</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> io
<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;">crypt</span>
<span style="color: #ff7700;font-weight:bold;">import</span> spwd
&nbsp;
<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> FancyURLopener
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">zipfile</span> <span style="color: #ff7700;font-weight:bold;">import</span> ZipFile
&nbsp;
PASSWORDS_SOURCE = <span style="color: #483d8b;">&quot;http://xato.net/files/10k%20most%20common.zip&quot;</span>
PASSWORDS_LIST = <span style="color: #483d8b;">'10k most common.txt'</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Le fichier ZIP est derrière cloudflare, qui vous ferme la porte au nez si</span>
<span style="color: #808080; font-style: italic;"># vous n'avez pas de User-Agent. On va donc créer un UrlOpener, un objet qui</span>
<span style="color: #808080; font-style: italic;"># ouvre des ressources en utilisant leurs URLs, qui a un User-Agent 'TA MERE'.</span>
<span style="color: #808080; font-style: italic;"># CloudFlare ne check pas que le UA est valide.</span>
<span style="color: #ff7700;font-weight:bold;">class</span> FFOpener<span style="color: black;">&#40;</span>FancyURLopener<span style="color: black;">&#41;</span>:
   version = <span style="color: #483d8b;">'TA MERE'</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Si le dictionnaire de passwords n'est pas là, on le télécharge</span>
<span style="color: #808080; font-style: italic;"># via FFOpener().open(PASSWORDS_SOURCE).read(). C'est verbeux, c'est urllib.</span>
<span style="color: #808080; font-style: italic;"># Normalement je ferais ça avec requests. Ensuite on lui donne une interface</span>
<span style="color: #808080; font-style: italic;"># file-like object avec io.BytesIO pour que ZipFile puisse le traiter en mémoire</span>
<span style="color: #808080; font-style: italic;"># sans avoir à le sauvegarder dans un vrai fichier sur le disque, et on</span>
<span style="color: #808080; font-style: italic;"># extrait le ZIP.</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>PASSWORDS_LIST<span style="color: black;">&#41;</span>:
    ZipFile<span style="color: black;">&#40;</span>io.<span style="color: black;">BytesIO</span><span style="color: black;">&#40;</span>FFOpener<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: #008000;">open</span><span style="color: black;">&#40;</span>PASSWORDS_SOURCE<span style="color: black;">&#41;</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>.<span style="color: black;">extractall</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># On extrait les mots de passe de la liste sous forme de tuple car c'est rapide</span>
<span style="color: #808080; font-style: italic;"># à lire. Un petit rstrip vire les sauts de ligne.</span>
passwords = <span style="color: #008000;">tuple</span><span style="color: black;">&#40;</span>l.<span style="color: black;">rstrip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> l <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>PASSWORDS_LIST<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># spwd.getspall() nous évite de parser le fichier shadow à la main.</span>
<span style="color: #ff7700;font-weight:bold;">for</span> entry <span style="color: #ff7700;font-weight:bold;">in</span> spwd.<span style="color: black;">getspall</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;">'Processing password for user &quot;%s&quot;: '</span> <span style="color: #66cc66;">%</span> entry.<span style="color: black;">sp_nam</span>, end=<span style="color: #483d8b;">''</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Pas de hash ? On gagne du temps avec 'continue'</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #483d8b;">'$'</span> <span style="color: #ff7700;font-weight:bold;">in</span> entry.<span style="color: black;">sp_pwd</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'no password hash to process.'</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">continue</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># On teste chaque password avec la fonction crypt, qui accepte en deuxième</span>
    <span style="color: #808080; font-style: italic;"># paramètre le hash du mot de passe complet. Pas besoin de se faire chier</span>
    <span style="color: #808080; font-style: italic;"># à le spliter, il va analyser les '$' et se démerder avec ça. On a juste</span>
    <span style="color: #808080; font-style: italic;"># à comparer le résultat avec le hash d'origine.</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> <span style="color: #dc143c;">pwd</span> <span style="color: #ff7700;font-weight:bold;">in</span> passwords:
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">crypt</span>.<span style="color: #dc143c;">crypt</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">pwd</span>, entry.<span style="color: black;">sp_pwd</span><span style="color: black;">&#41;</span> == entry.<span style="color: black;">sp_pwd</span>:
            <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'password is &quot;%s&quot;.'</span> <span style="color: #66cc66;">%</span> <span style="color: #dc143c;">pwd</span><span style="color: black;">&#41;</span>
            <span style="color: #808080; font-style: italic;"># On break pour gagner quelques tours de boucles, et pouvoir</span>
            <span style="color: #808080; font-style: italic;"># utiliser la condition 'else'.</span>
            <span style="color: #ff7700;font-weight:bold;">break</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'fail to break password.'</span><span style="color: black;">&#41;</span></pre></div></div>

<p><a href="https://github.com/sametmax/codes-des-articles/blob/master/2014/janvier/crack_shadow.py">Télécharger le code.</a></p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8917&amp;md5=a1783918d5efb8552ac4659f4ae50c32" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8743
title: ERROR: invalid locale name avec PostGres
uri: ERROR-invalid-locale-name-avec-PostGres
url: http://sametmax.com/error-invalid-locale-name-avec-postgres/
content:
<p>Il suffit de redémarrer PostGres.</p>
<p>Ca arrive quand on met à jour ses locales et que des services tournent. Ils ne reçoivent pas l&#8217;information, et utilisent l&#8217;ancienne locale.</p>
<p>Oui, j&#8217;avais besoin d&#8217;un poste bouche-trou.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8743&amp;md5=a3e3d51b364d4cb9428bd1922787d2e5" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8328
title: Python, meilleur nul part, excellent partout
uri: Python-meilleur-nul-part-excellent-partout
url: http://sametmax.com/python-meilleur-nul-part-excellent-partout/
content:
<p>Je ne sais pas si vous l&#8217;aviez compris, mais <a href="http://sametmax.com/10-raisons-pour-lesquelles-je-suis-toujours-marie-a-python/">j&#8217;aime bien Python</a>. J&#8217;ai essayé de vous le cacher jusqu&#8217;ici, mais je sais que mon secret ne tiendra pas longtemps, alors j&#8217;avoues tout.</p>
<p>Je n&#8217;aime pas Python parce que c&#8217;est le meilleur langage pour X. Je ne pense pas que Python soit le meilleur langage pour quoi que ce soit. Regex ? Perl est meilleur ? IA ? Lisp est meilleur. Embarqué ? C est meilleur. Asynchrone ? Javascript est meilleur.</p>
<p>Non. J&#8217;aime Python parce qu&#8217;il est très bon à X. Presque tous les X. En fait, il existe très peu de X pour lequel Python n&#8217;est pas bon.</p>
<p>Python est excellent pour analyser du texte, pour faire un site Web (même asynchrone), de l&#8217;administration système, des interfaces graphiques, du calcul scientifique, de la 3D, des crawlers, etc. Pas le meilleur. Mais très bon.</p>
<p>Et ceci est fantastique. Cela veut dire que si je commence un projet, n&#8217;importe quel projet, je sais que je peux le commencer en Python. Je ne serai pas bloqué plus tard par tel ou tel besoin. Je sais que je pourrai m&#8217;en sortir agréablement avec Python.</p>
<p>Vous faites un site en JS ? Pour le sysadmin, il va falloir un autre langage.</p>
<p>Des scripts de maintenance en Perl ? J&#8217;espère que vous n&#8217;aurez pas besoin d&#8217;une UI.</p>
<p>Un crawler en PHP ? Pour l&#8217;analyse des données récupérer, vous aller vous amuser&#8230;</p>
<p>De l&#8217;extraction de data en Ruby ? Pourvu qu&#8217;il ne faille pas traiter plusieurs To.</p>
<p>Ce n&#8217;est pas que vous ne pourrez pas. Ils sont tous Turring complet après tout. Mais vous allez vraiment galérer.</p>
<p>Aucun langage n&#8217;est parfait, et Python n&#8217;est pas une exception. </p>
<p>Mais ce qui est génial, c&#8217;est que dans 90% des cas, vous pouvez avoir une solution propre et efficace en Python au problématique que vous ne savez même pas encore que vous aurez. Et le jour où vous atteindrez la limite, alors oui, vous pourrez utiliser une autre techno pour le faire. Mais juste pour cette partie. La plupart du temps ce sera une partie très réduite. En en plus, Python pourra probablement s&#8217;interfacer nativement avec le code de l&#8217;autre langage.</p>
<p>Il y a des tas de raisons de ne pas choisir Python bien entendu, mais probablement la meilleure raison de le choisir, c&#8217;est qu&#8217;il y a peu de chance de se planter.</p>
<p>Bon, évidement si vous voulez écrire un driver de carte graphique&#8230;</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8328&amp;md5=b40c02594ee4a3fe706c3f4f7474a092" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8076
title: Un objet proxy : ce que c’est et à quoi ça sert
uri: Un-objet-proxy-ce-que-c-est-et-à-quoi-ça-sert
url: http://sametmax.com/un-objet-proxy-ce-que-cest-et-a-quoi-ca-sert/
content:
<p>Un objet proxy est un objet qui prend un <strong>autre</strong> objet en paramètre et le sauvegarde dans un de ses attributs. Quand on appelle les méthodes du proxy, le proxy appelle la même méthode de l&#8217;objet qu&#8217;il a en attribut, et retourne le résultat. Quand on set/get/delete un attribut du proxy, il fait la même chose sur l&#8217;autre objet.</p>
<p>Voilà une implémentation très basique d&#8217;un objet proxy en Python :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Proxy<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, obj<span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;"># L'objet passé en paramètre est</span>
        <span style="color: #808080; font-style: italic;"># sauvegardé dans un attribut.</span>
        <span style="color: #808080; font-style: italic;"># On le fait en utilisant </span>
        <span style="color: #808080; font-style: italic;"># object.__setattr__, qui est le</span>
        <span style="color: #808080; font-style: italic;"># __setattr__ du parent, et non directement</span>
        <span style="color: #808080; font-style: italic;"># en faisant self._obj = obj</span>
        <span style="color: #808080; font-style: italic;"># afin d'éviter une boucle infinie car</span>
        <span style="color: #808080; font-style: italic;"># nous écrasons __setattr__ plus bas.</span>
        <span style="color: #008000;">object</span>.<span style="color: #0000cd;">__setattr__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #483d8b;">&quot;_obj&quot;</span>, obj<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># On écrase les méthodes magiques __getattribute__</span>
    <span style="color: #808080; font-style: italic;"># (qui est appelée quand on faire self.nom_attribut), </span>
    <span style="color: #808080; font-style: italic;"># __delattr__ (qui est appelée quand on fait </span>
    <span style="color: #808080; font-style: italic;"># del self.nom_attribut) et __setattr__ (qui est </span>
    <span style="color: #808080; font-style: italic;"># appelée quand on fait self.nom_attribut = truc)</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__getattribute__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, name<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span><span style="color: #008000;">object</span>.<span style="color: #0000cd;">__getattribute__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #483d8b;">&quot;_obj&quot;</span><span style="color: black;">&#41;</span>, name<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__delattr__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, name<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">delattr</span><span style="color: black;">&#40;</span><span style="color: #008000;">object</span>.<span style="color: #0000cd;">__getattribute__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #483d8b;">&quot;_obj&quot;</span><span style="color: black;">&#41;</span>, name<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__setattr__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, name, value<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">setattr</span><span style="color: black;">&#40;</span><span style="color: #008000;">object</span>.<span style="color: #0000cd;">__getattribute__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #483d8b;">&quot;_obj&quot;</span><span style="color: black;">&#41;</span>, name, value<span style="color: black;">&#41;</span></pre></div></div>

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

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> UnObjetOrdinnaire<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
    attribut = <span style="color: #483d8b;">'VALEUR !'</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> methode<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, param<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> param <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">2</span>
&nbsp;
&nbsp;
objet_ordinnaire = UnObjetOrdinnaire<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># on passe l'objet ordinnaire au proxy</span>
objet_proxy = Proxy<span style="color: black;">&#40;</span>objet_ordinnaire<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Accéder à des méthodes et attribut</span>
<span style="color: #808080; font-style: italic;"># du proxy accède à ceux de l'objet</span>
<span style="color: #808080; font-style: italic;"># derrière le proxy</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>objet_proxy.<span style="color: black;">attribut</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## VALEUR !</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>objet_proxy.<span style="color: black;">methode</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: #808080; font-style: italic;">## 6</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Modifier l'objet proxy modifie</span>
<span style="color: #808080; font-style: italic;"># l'objet derrière le proxy</span>
objet_proxy.<span style="color: black;">attribut</span> = <span style="color: #483d8b;">'une autre valeur'</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>objet_ordinnaire.<span style="color: black;">attribut</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## une autre valeur</span></pre></div></div>

<p>Pour un exemple vraiment à l&#8217;épreuve des balles, il faut prendre en compte tout un tas de <a href="http://code.activestate.com/recipes/496741-object-proxying/">cas particuliers</a>, ce qui fait qu&#8217;il est bien plus rentable d&#8217;utiliser une <a href="https://pypi.python.org/pypi/ProxyTypes">lib solide</a> pour ça.</p>
<p><strong>Attention, un objet proxy peut très bien avoir des méthodes qui n&#8217;appellent pas celles de l&#8217;objet derrière. On même avoir des méthodes qui appellent des méthodes qui n&#8217;ont pas le même nom, ou plusieurs méthodes&#8230;</strong> Ce que vous voyez en exemple est un proxy très basique.</p>
<h2>Pourquoi voudrait-on obtenir ce résultat ?</h2>
<p>Plusieurs design patterns font appel à des objets proxy. Par exemple, le design pattern &#8220;adapter&#8221; consiste à créer un objet proxy qui accepte plusieurs types d&#8217;objets en paramètres afin de présenter toujours la même interface.</p>
<p>Imaginez que vous ayez plusieurs objets qui servent à s&#8217;authentifier :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Login<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
    _is_logged = <span style="color: #008000;">False</span> 
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> is_logged<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>._is_logged
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> login<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #dc143c;">email</span>, password<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>._is_logged = <span style="color: #008000;">True</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> LoginWithUsername<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
    _is_logged = <span style="color: #008000;">False</span> 
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> is_logged<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>._is_logged
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> login<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, username, password<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>._is_logged = <span style="color: #008000;">True</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> SignIn<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
    _is_logged = <span style="color: #008000;">False</span> 
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> is_logged<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>._is_logged
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> signin<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #dc143c;">email</span>, password<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>._is_logged = <span style="color: #008000;">True</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> LoginWithKey<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
    _is_logged = <span style="color: #008000;">False</span> 
&nbsp;
    key = <span style="color: #483d8b;">&quot;jfjkdlmqfjdmqsjdk&quot;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> is_logged<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>._is_logged
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> login<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, username<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>._is_logged = <span style="color: #008000;">True</span></pre></div></div>

<p>Et vous avez un algo de parsing, qui attend un objet d&#8217;authentification. Si vous mettez le code qui permet de choisir la bonne API dans l&#8217;algo de parsing, vous liez l&#8217;algo (qui n&#8217;a rien à voir avec l&#8217;authentification) à toutes ces implémentations.</p>
<p>Une des manières de faire, est d&#8217;utiliser un adaptateur, dont  voici une esquisse :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> AuthAdapter<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, obj<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">object</span>.<span style="color: #0000cd;">__setattr__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #483d8b;">&quot;_obj&quot;</span>, obj<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__getattribute__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, name<span style="color: black;">&#41;</span>:
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">try</span>:
            <span style="color: #808080; font-style: italic;"># Si l'attribut existe sur le proxy, on l'utilise</span>
            <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">object</span>.<span style="color: #0000cd;">__getattribute__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, name<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">AttributeError</span>:
            <span style="color: #808080; font-style: italic;"># Sinon on tente le coup sur l'objet derrière le proxy</span>
            <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span><span style="color: #008000;">object</span>.<span style="color: #0000cd;">__getattribute__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #483d8b;">&quot;_obj&quot;</span><span style="color: black;">&#41;</span>, name<span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> login<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, id_=<span style="color: #008000;">None</span>, secret=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;"># Le login est différent pour chaque classe,</span>
        <span style="color: #808080; font-style: italic;"># donc on s'arrange avec.</span>
        <span style="color: #ff7700;font-weight:bold;">try</span>:
            <span style="color: #008000;">self</span>._obj.<span style="color: black;">login</span><span style="color: black;">&#40;</span>id_, secret<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">AttributeError</span>:
            <span style="color: #008000;">self</span>._obj.<span style="color: black;">signin</span><span style="color: black;">&#40;</span>id_, secret<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">TypeError</span>:
            <span style="color: #008000;">self</span>._obj.<span style="color: black;">login</span><span style="color: black;">&#40;</span>id_<span style="color: black;">&#41;</span></pre></div></div>

<p>En gros, si on essaye d&#8217;appeler <code>login()</code>, il va lisser les contours et nous donner toujours la même interface, même si derrière l&#8217;objet peut marcher complètement différement. En revanche, si on appelle n&#8217;importe quel autre attribut ou méthode (par exemple <code>is_logged</code>, mais il pourrait y en avoir des dizaines d&#8217;autres dans la vrai vie vivante), ça tape directement dans l&#8217;objet derrière le proxy.</p>
<p>Donc si j&#8217;applique l&#8217;adaptateur systématiquement, quelle que soit la classe derrière, le comportement est toujours le même : j&#8217;appelle <code>login(un id, un secret)</code>, et il se logge.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">all_auth = <span style="color: black;">&#40;</span>Login, LoginWithUsername, SignIn, LoginWithKey<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> auth <span style="color: #ff7700;font-weight:bold;">in</span> all_auth:
    <span style="color: #808080; font-style: italic;"># 'auth' est une des 4 classes de login. On l'instancie et</span>
    <span style="color: #808080; font-style: italic;"># on met l'instance derrière le proxy</span>
    auth = AuthAdapter<span style="color: black;">&#40;</span>auth<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><span style="color: #483d8b;">&quot;Testing '%s'&quot;</span> <span style="color: #66cc66;">%</span> auth.__class__.__name__<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;Is logged : %s&quot;</span> <span style="color: #66cc66;">%</span> auth.<span style="color: black;">is_logged</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># Le login se passe toujours de la même manière, quelle que soit la classe</span>
    auth.<span style="color: black;">login</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'id'</span>, <span style="color: #483d8b;">'secret'</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;Is logged after logging : %s&quot;</span> <span style="color: #66cc66;">%</span> auth.<span style="color: black;">is_logged</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></div></div>

<p> Comme d&#8217;habitude, ceci est un exemple naval. Il est bateau quoi. Mais cela vous démontre le principe.</p>
<p> Le design pattern façade ressemble à l&#8217;adapter, en fait c&#8217;est une spécialisation de l&#8217;adapter. Il s&#8217;agit juste d&#8217;exposer une interface plus simple, de l&#8217;objet derrière le proxy.</p>
<p>Un proxy peut aussi servir à hacker une lib. Par exemple, la lib attend un objet d&#8217;une ancienne version d&#8217;une autre lib dont l&#8217;auteur a déprécié un attribut. Avec un proxy, vous pouvez toujours faire semblant que l&#8217;attribut est toujours là : enrobez l&#8217;objet dans un proxy qui possède cet attribut, tout le reste de l&#8217;API sera la même.</p>
<p>Un proxy peut également être utile si vous voulez effectuer des actions quand l&#8217;objet est manipulé.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">logging</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> ProxyLogger<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, obj<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">object</span>.<span style="color: #0000cd;">__setattr__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #483d8b;">&quot;_obj&quot;</span>, obj<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__getattribute__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, name<span style="color: black;">&#41;</span>:
        obj = <span style="color: #008000;">object</span>.<span style="color: #0000cd;">__getattribute__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #483d8b;">&quot;_obj&quot;</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># On lance un warning à chaque accès à un attribut de l'objet</span>
        <span style="color: #808080; font-style: italic;"># derrière le proxy</span>
        <span style="color: #dc143c;">logging</span>.<span style="color: black;">warning</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;%s.%s has been called&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>obj.__class__.__name__, name<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span>obj, name<span style="color: black;">&#41;</span></pre></div></div>

<p>Maintenant, supposons que vous avez un objet d&#8217;une lib externe (que vous ne pouvez donc pas modifier) sur lequel vous avez besoin d&#8217;infos :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> ObjetExterne<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> ahahah<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
o = ProxyLogger<span style="color: black;">&#40;</span>ObjetExterne<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
o.<span style="color: black;">ahahah</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## WARNING:root:ObjetExterne.ahahah has been called</span></pre></div></div>

<p>Vous pouvez refiler le proxy à n&#8217;importe quel objet de sa lib d&#8217;origine, si le proxy est bien fait, elle ne vera pas la différence.</p>
<p>On finit sur une note culture, puisque le pattern decorator utilise souvent aussi un proxy. Cette fois d&#8217;une fonction sur un autre objet (en générale une autre fonction). Mais le principe est le même. Donc quand vous voyez <a href="http://sametmax.com/comprendre-les-decorateurs-python-pas-a-pas-partie-1/">@un_decorateur</a>, il est peut être en train d&#8217;appliquer un proxy à la fonction.</p>
<p>D&#8217;ailleurs on dit souvent que le proxy <strong>décore</strong> l&#8217;objet qui est derrière. </p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8076&amp;md5=c70995e246355b07b339e3e26fe0c923" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8939
title: Python a le don d’Ubiquité : Multiprocessing
uri: Python-a-le-don-d-Ubiquité-Multiprocessing
url: http://sametmax.com/python-ubiuite-multiprocessing/
content:
<blockquote><p>Ceci est un post invité de <a href="http://sametmax.com/author/foxmask" target="_blank">Foxmask </a>posté sous licence <a href="http://creativecommons.org/licenses/by/3.0/" target="_blank">creative common 3.0 unported</a>.</p></blockquote>
<p>Tout récemment j&#8217;ai voulu donner un coup de fouet à mon <a href="https://github.com/foxmask/django-th/blob/d91e443795429c85decf0ccf5e1f8470df7d11c4/fire.py">script de traitement</a> de <a href="http://www.foxmask.info/tag/triggerhappy/">Trigger Happy</a> (que je fais tourner sur ma &#8220;raspberry pi&#8221; parce que chuis un w4rl0rdZ:P) que j&#8217;estimais être trop long dans ses traitements de données.</p>
<p>Actuellement avec <a href="https://pypi.python.org/pypi/django_th/">Trigger Happy</a>, j&#8217;ai 30 sources de données (essentiellement des flux rss), que je parcours, et quand un nouvel item arrive, je l&#8217;envoi à pétaouchnock (Evernote ;) Le tout prend <strong>7min</strong>, soit 14secondes par source. La loose totale.</p>
<p>Voici le corps du délit :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
<span style="color: #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: #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;">time</span>
&nbsp;
<span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span>.<span style="color: black;">setdefault</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;DJANGO_SETTINGS_MODULE&quot;</span>, <span style="color: #483d8b;">&quot;django_th.settings&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">from</span> django_th.<span style="color: black;">services</span> <span style="color: #ff7700;font-weight:bold;">import</span> default_provider
<span style="color: #ff7700;font-weight:bold;">from</span> django_th.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> TriggerService
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">utils</span>.<span style="color: black;">log</span> <span style="color: #ff7700;font-weight:bold;">import</span> getLogger
&nbsp;
<span style="color: #808080; font-style: italic;"># create logger</span>
logger = getLogger<span style="color: black;">&#40;</span><span style="color: #483d8b;">'django_th.trigger_happy'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> go<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
        run the main process
    &quot;&quot;&quot;</span>
    trigger = TriggerService.<span style="color: black;">objects</span>.<span style="color: #008000;">filter</span><span style="color: black;">&#40;</span>status=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> trigger:
        <span style="color: #ff7700;font-weight:bold;">for</span> service <span style="color: #ff7700;font-weight:bold;">in</span> trigger:
<span style="color: black;">&#91;</span>...<span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;No trigger set by any user&quot;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    default_provider.<span style="color: black;">load_services</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># let's go</span>
    go<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
&nbsp;
    main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Mais avant que je ne me penche sur le code du script pour l&#8217;améliorer, je me suis dit que plutôt que de chercher à corriger un problème, autant chercher la source de celui-ci d&#8217;abord (normal hein).</p>
<p>Un HTOP m&#8217;a révélé :</p>
<ol>
<li>que le CPU était à 100% tout le temps, que le script tourne ou pas</li>
<li>quye la raison était double : rabittmq et celery&#8230; </li>
</ol>
<p>Une fois shootés ces derniers, tout va pour le mieux :P<br />
Je ne dis pas que ceux ci sont de la merde, mais que, pour mon cas, la crontab se suffit à elle-même.</p>
<p>Donc une fois désinstallés c&#8217;est 2 (sur)consommateurs de ressources, je relance le script pour tomber à un temps de traitement à <strong>5mn</strong></p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">2014-02-02 14:40:51,693 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - News Sam et Max nothing new
2014-02-02 14:40:53,865 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - News de Numerama nothing new
2014-02-02 14:40:56,013 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de La Ferme du Web nothing new
2014-02-02 14:41:01,005 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - flux de Paulds nothing new
2014-02-02 14:41:20,098 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux d'un Odieux Connard nothing new
2014-02-02 14:41:22,142 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de Strict minimum nothing new
2014-02-02 14:41:25,868 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Humeurs Illustrées nothing new
2014-02-02 14:41:33,497 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux du Journalisme Total nothing new
2014-02-02 14:41:35,658 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de Kernel Panic nothing new
2014-02-02 14:41:44,897 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de AngularJS nothing new
2014-02-02 14:41:49,016 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de Odeon nothing new
2014-02-02 14:41:54,186 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de Nicolargo nothing new
2014-02-02 14:42:12,525 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de JEEK nothing new
2014-02-02 14:42:21,349 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de Recher nothing new
2014-02-02 14:42:31,266 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de Un blog d'adminsys Libres nothing new
2014-02-02 14:42:35,824 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - flux de Le bloc-notes de Gee nothing new
2014-02-02 14:42:36,647 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de mere code (atom) nothing new
2014-02-02 14:42:39,616 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de Alex Mac Caw nothing new
2014-02-02 14:42:42,985 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de Yearofmoo Articles nothing new
2014-02-02 14:43:42,732 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - News Novapost nothing new
2014-02-02 14:43:46,722 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - News Les Numériques nothing new
2014-02-02 14:43:58,303 INFO fire 5142 date 2014-02-02 13:00:00 &gt;= date triggered 2014-02-02 09:02:36 title Test du Quechua Phone 5, le smartphone des montagnards ?
2014-02-02 14:44:08,010 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - News Frandroid = 1 new data
2014-02-02 14:44:17,624 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de TechCrunch Mobile nothing new
2014-02-02 14:44:20,339 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux Django annonces nothing new
2014-02-02 14:44:20,744 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - La Hyène - Python nothing new
2014-02-02 14:44:24,237 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - News de PCInpact nothing new
2014-02-02 14:44:29,055 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - PointGPhone nothing new
2014-02-02 14:44:31,299 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - HumanCoders Python nothing new
2014-02-02 14:44:52,751 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - HauteFeuille Lab (python) nothing new
2014-02-02 14:44:58,850 INFO fire 5142 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de Python Plone Planet nothing new</pre></div></div>

<p>Comme je suis un éternel insatisfait de bibi, j&#8217;ai cherché <a href="http://sametmax.com/remplacer-les-threads-avec-le-module-multiprocessing-en-python/">des moyens</a> <a href="http://www.hautefeuille.eu/python-parallelism-multiprocessing.html">un peu partout</a>, jusqu&#8217;à ce que Sam me souffle une suggestion ;)</p>
<p>A présent donc <a href="https://github.com/foxmask/django-th/blob/master/fire.py">une version modifiée pour exploiter le multiprocessing</a> est la suivante :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
<span style="color: #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: #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;">time</span>
<span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span>.<span style="color: black;">setdefault</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;DJANGO_SETTINGS_MODULE&quot;</span>, <span style="color: #483d8b;">&quot;th.settings&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> django_th.<span style="color: black;">services</span> <span style="color: #ff7700;font-weight:bold;">import</span> default_provider
<span style="color: #ff7700;font-weight:bold;">from</span> django_th.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> TriggerService
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">utils</span>.<span style="color: black;">log</span> <span style="color: #ff7700;font-weight:bold;">import</span> getLogger
&nbsp;
<span style="color: #808080; font-style: italic;"># create logger</span>
logger = getLogger<span style="color: black;">&#40;</span><span style="color: #483d8b;">'django_th.trigger_happy'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> go<span style="color: black;">&#40;</span>service<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;
        run the main process
    &quot;&quot;&quot;</span>
    <span style="color: black;">&#91;</span>...<span style="color: black;">&#93;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    default_provider.<span style="color: black;">load_services</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># let's go</span>
    trigger = TriggerService.<span style="color: black;">objects</span>.<span style="color: #008000;">filter</span><span style="color: black;">&#40;</span>status=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> trigger:
        <span style="color: #ff7700;font-weight:bold;">from</span> multiprocessing <span style="color: #ff7700;font-weight:bold;">import</span> Pool
        pool = Pool<span style="color: black;">&#40;</span>processes=<span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>
        result = pool.<span style="color: #008000;">map</span><span style="color: black;">&#40;</span>go, trigger<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: #483d8b;">&quot;No trigger set by any user&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
&nbsp;
    main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>fait tomber le temps de traitement à &#8230; <strong>1min</strong> &#8230;:</p>

<div class="wp_syntax"><div class="code"><pre class="shell" style="font-family:monospace;">$ date &amp;&amp; ./fire.sh &amp;&amp; date 
dimanche 2 février 2014, 14:58:38 (UTC+0100)
2014-02-02 14:58:48,221 INFO fire 5334 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de La Ferme du Web nothing new
2014-02-02 14:58:48,243 INFO fire 5336 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Humeurs Illustrées nothing new
2014-02-02 14:58:48,256 INFO fire 5337 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de Kernel Panic nothing new
2014-02-02 14:58:48,283 INFO fire 5333 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - News Sam et Max nothing new
2014-02-02 14:58:48,907 INFO fire 5335 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux d'un Odieux Connard nothing new
2014-02-02 14:58:49,267 INFO fire 5334 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - flux de Paulds nothing new
2014-02-02 14:58:49,446 INFO fire 5336 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux du Journalisme Total nothing new
2014-02-02 14:58:49,713 INFO fire 5333 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - News de Numerama nothing new
2014-02-02 14:58:49,847 INFO fire 5335 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de Strict minimum nothing new
2014-02-02 14:58:50,209 INFO fire 5334 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de Odeon nothing new
2014-02-02 14:58:50,353 INFO fire 5337 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de AngularJS nothing new
2014-02-02 14:58:50,830 INFO fire 5333 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de Un blog d'adminsys Libres nothing new
2014-02-02 14:58:51,338 INFO fire 5336 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de JEEK nothing new
2014-02-02 14:58:51,396 INFO fire 5334 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de Nicolargo nothing new
2014-02-02 14:58:51,476 INFO fire 5337 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de Yearofmoo Articles nothing new
2014-02-02 14:58:51,735 INFO fire 5333 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - flux de Le bloc-notes de Gee nothing new
2014-02-02 14:58:52,148 INFO fire 5335 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de mere code (atom) nothing new
2014-02-02 14:58:52,640 INFO fire 5336 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de Recher nothing new
2014-02-02 14:58:52,971 INFO fire 5335 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de Alex Mac Caw nothing new
2014-02-02 14:58:53,416 INFO fire 5334 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - News Les Numériques nothing new
2014-02-02 14:58:53,474 INFO fire 5333 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de TechCrunch Mobile nothing new
2014-02-02 14:58:53,870 INFO fire 5337 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - News Novapost nothing new
2014-02-02 14:58:54,072 INFO fire 5335 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - PointGPhone nothing new
2014-02-02 14:58:54,316 INFO fire 5333 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux Django annonces nothing new
2014-02-02 14:58:54,853 INFO fire 5336 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - La Hyène - Python nothing new
2014-02-02 14:58:55,111 INFO fire 5335 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - HumanCoders Python nothing new
2014-02-02 14:58:55,222 INFO fire 5334 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - News Frandroid nothing new
2014-02-02 14:58:55,380 INFO fire 5337 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - HauteFeuille Lab (python) nothing new
2014-02-02 14:58:55,696 INFO fire 5336 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - News de PCInpact nothing new
2014-02-02 14:59:02,214 INFO fire 5337 user: foxmask - provider: ServiceRss - consummer: ServiceEvernote - Flux de Python Plone Planet nothing new
dimanche 2 février 2014, 14:59:02 (UTC+0100)</pre></div></div>

<p>Comme on l&#8217;aura remarqué la différence entre les 2 versions est l&#8217;appel fait à a fonction go </p>
<p>avant :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    default_provider.<span style="color: black;">load_services</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># let's go</span>
    go<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>après :</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    default_provider.<span style="color: black;">load_services</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># let's go</span>
    trigger = TriggerService.<span style="color: black;">objects</span>.<span style="color: #008000;">filter</span><span style="color: black;">&#40;</span>status=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> trigger:
        <span style="color: #ff7700;font-weight:bold;">from</span> multiprocessing <span style="color: #ff7700;font-weight:bold;">import</span> Pool
        pool = Pool<span style="color: black;">&#40;</span>processes=<span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>
        result = pool.<span style="color: #008000;">map</span><span style="color: black;">&#40;</span>go, trigger<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: #483d8b;">&quot;No trigger set by any user&quot;</span></pre></div></div>

<p>du coup l&#8217;appel de la fonction &#8220;go&#8221; implique de changer sa signature en lui filant comme <a href="http://sametmax.com/la-difference-entre-parametres-et-arguments/">argument</a> &#8220;trigger&#8221; (le QuerySet de l&#8217;appli Django)</p>
<p>A présent donc <strong>pool.map</strong> fait l&#8217;itération des données trouvées dans le modele <strong>TriggerService</strong> et exécute tout le tintouin. *<:o)</p>
<p>ps : @Sam : chose promise chose dûe ;)</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8939&amp;md5=9114c0c05f7ef60e6f4fb45b22129faf" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8950
title: Les ventes aux enchères publiques
uri: Les-ventes-aux-enchères-publiques
url: http://sametmax.com/les-ventes-aux-encheres-publiques/
content:
<p>Petite digression de la ligne éditoriale, billet d&#8217;humeur, des fois il faut écrire ce qui sort.</p>
<p>Quand j&#8217;étais gosse mon père m&#8217;avait trainé à des ventes aux enchères, et c&#8217;était une vraie corvée : rester assis sur place pendant des heures pour un môme, c&#8217;est complètement con (pensez à l&#8217;école&#8230;) et mon pouvoir d&#8217;achat était négligeable. En plus on ne pouvait même pas toucher les objets.</p>
<p>Mais en grandissant, le premier cheveux blanc arrive, on se met à aimer les cornichons et les vides greniers. Et on fini par retourner aux enchères.</p>
<p>Pour ceux qui ne savent pas, il existe ce qu&#8217;on appelle des enchères publiques, dans lesquelles des personnes physiques ou morales, souvent endettées, parfois carrément en faillite, vendent leurs biens. On y trouve aussi quantité d&#8217;objets non réclamés à la poste. L&#8217;avantage de la chose, c&#8217;est qu&#8217;on trouve des objets de toutes sortes de domaines, potentiellement à un tiers du prix conseillé et possiblement neufs.</p>
<p>Ça se passe ainsi : on se pointe à l&#8217;exposition, dans laquelle on a le droit de regarder les choses qui vont être en vente. Ça peut aller de l&#8217;écran plat au four à pain de boulanger en passant par une caravane, des bijoux, du matériel d&#8217;escalade et une collection de cartes pokémon.</p>
<p>En générale quand on arrive, on sait où regarder car maintenant, magie de l&#8217;internet, on a un listing en ligne des biens vendus des jours avant la vente sur les sites des <a href="http://commissaires-priseurs.com/trouver-un-commissaire-priseur-judiciaire/">commissaires priseurs</a> ou des <a href="media/8cfc08c7.annuaire-cvv.pdf" data-original-source="http://www.conseildesventes.fr/sites/default/files/annuaire-cvv.pdf">OVV</a>. Dans tous les cas, on peut obtenir la liste imprimée sur place, mais certaines salles le facturent une somme symbolique.</p>
<p>Tout le monde peut se pointer, c&#8217;est publique, et tout le monde se pointe. Une enchère est socialement très transversale : vous avez des vieux, des jeunes, des jaunes, des blancs, des chauves, des moustachus, des pros, des amateurs, des élégants, des dépareillés&#8230; Mais le profile type est un homme de plus de 35 ans.</p>
<p>Dans beaucoup de salles, on a pas le droit d&#8217;approcher les objets, exposés derrière des barrières, et groupés par lots numérotés. Quand on est intéressé par un lot, on le signale à un assistant qui va vous le chercher (sauf si c&#8217;est un bateau, évidement) pour que vous l&#8217;examiniez sous ses yeux.</p>
<p>Au bout d&#8217;un temps prévu à l&#8217;avance, on va donner un chèque en blanc et une pièce d&#8217;identité pour récupérer un numéro d&#8217;enchérisseur sur un petit panneau. Ceci dit si vous ne le faites pas, on vous laisse souvent enchérir quand même à main levée, et on vous donne le panneau à la première enchère remportée.</p>
<p>Ensuite on s&#8217;assoie, un mec avec un costume datant du temps de votre grand père monte sur un podium avec un marteau et répète à tout le monde une bonne 30aine de fois qu&#8217;il lui faut du silence. Il recommencera tout au long de la vente, c&#8217;est une tradition.</p>
<p>Là, l&#8217;équipe commencent à présenter les lots, on annonce le prix de départ et chacun lève joyeusement son petit panneau ou sa mimine pour enchérir. Pour des petits lots, on enchérie par tranches de 2, 5, 10, 20 ou 50 euros. La taille des tranche peut augmenter au fur et à mesure que l&#8217;enchère augmente. Si vous enchérissez sur un bien bien plus cher, l&#8217;enchère peut monter par tranche de 100, 500, 1000&#8230; Si vous êtes dans le domaine du luxe, les tranches sont un mois ou un an de salaire pour vous.</p>
<p>Si il n&#8217;y a pas d&#8217;acheteur, le commissaire priseur va proposer un prix à la baisse. Hé oui, la mise à prix peut diminuer.</p>
<p>La vente peut durer des heures. Ma dernière vente a duré 3h, avec une 1h d&#8217;expo, 1/2h pour y aller, 1/2h pour en revenir, soit 5h monopolisées en plein lundi. Tout le monde ne peut pas se le permettre. Heureusement aujourd&#8217;hui, on peut enchérir en ligne, sans avoir à se déplacer. Même si personnellement je préfère voir les lots en direct, car c&#8217;est dur de se faire une idée.</p>
<p>Histoire que vous puissiez évaluer le contenu d&#8217;une vente, voici un extrait (il y avait des <strong>centaines</strong> de lots, ce ne sont quelques uns) de ce qui est parti à la dernière.</p>
<table>
<tbody>
<tr>
<td>Lot</td>
<td>Prix de départ</td>
<td>Adjugé pour</td>
<td>Prix frais compris</td>
<td>Prix en magasin</td>
<td>Notes</td>
</tr>
<tr>
<td>Carton de 100 clés USB</td>
<td>40</td>
<td>426</td>
<td>511,2</td>
<td>?</td>
<td>Je n&#8217;ai pas vérifié la taille des clés</td>
</tr>
<tr>
<td><a href="http://www.darty.com/nav/achat/informatique/ordinateur_portable-portable/portable/asus_touch_taichi31-cx010h.html">PC ASUS TAICHI 30</a></td>
<td>300</td>
<td>600</td>
<td>720</td>
<td>1207
</td>
<td>Ce genre de matos part assez cher, mais notez que c&#8217;est du neuf. Presque 500€ d&#8217;économisé sur l&#8217;achat d&#8217;un portable de ce genre, ce n&#8217;est pas rien.
</td>
</tr>
<tr>
<td>Carton de 80 montres fantasies</td>
<td>100</td>
<td>220</td>
<td>264</td>
<td>?</td>
<td>«&nbsp;fantasie&nbsp;» = casio, diesel, etc.<br />
Acheté par un mec fashion qui voulait sans doute une montre par jour à<br />
porter.</td>
</tr>
<tr>
<td><a href="http://www.territoirewhisky.fr/fr/nos-whiskies/825-chivas-regal-25-ans.html">2 bouteilles de Chivas 25 ans d&#8217;age</a></td>
<td>?</td>
<td>210</td>
<td>252</td>
<td>508
</td>
<td>
</td>
</tr>
<tr>
<td>20 bouteilles de liqueurs</td>
<td>100</td>
<td>100</td>
<td>120</td>
<td>?</td>
<td>Le lot est vraiment parti pour rien, ça fait<br />
partie de ces «&nbsp;coups de bol&nbsp;» car ça valait 20 fois ce prix<br />
si ont souhaite le vendre en magasin.</td>
</tr>
<tr>
<td>12 bouteilles apéro</td>
<td>50</td>
<td>100</td>
<td>120</td>
<td>?</td>
<td>Type «&nbsp;vodka, manzana, pastis, cointreau,<br />
etc&nbsp;». Pour un BDE, c&#8217;est intéressant.</td>
</tr>
<tr>
<td><a href="http://www.marionnaud.fr/Marionnaud/Marques/CHANEL/PARFUMS-FEMME/N%C2%B05/Eau-de-Parfum/p/BP_100005086">Parfum Chanel N°5, 200ml</a></td>
<td>50</td>
<td>115</td>
<td>138</td>
<td>177
</td>
<td>Ce genre de produit part à des prix bien moins intéressant. Les acheteurs à petit budgets sont généralement<br />
les moins bons en enchères, ils &#8220;tentent le coup&#8221; sur un produit coup de coeur et montent les prix beaucoup trop haut, sans stratégie d&#8217;achat.</td>
</tr>
<tr>
<td><a href="http://www.priceminister.com/offer/buy/75258602/Xp-Copie-Stratocaster-Bl-Guitare-Electrique-Xp-Instrument.html">Guitar Electrique XP</a> + <a href="media/9e089449.3-GClass.pdf" data-original-source="http://haytrade.fr/catalogue/3-GClass.pdf">Guitar<br />
accoustique STOL</a></td>
<td>80</td>
<td>80</td>
<td>96</td>
<td>
</td>
<td>Même si les instruments ne sont pas de qualités<br />
incroyables, c&#8217;est bien plus rentable de les acheter ici. Surtout que<br />
beaucoup de gens abandonnent la musique en cours de route. Il y a aussi quelques pièces de très grande qualité. Deux luth sont partis à 1300 euros.</td>
</tr>
<tr>
<td><a href="http://www.sebim-instrument.com/index.php?route=product/product&#038;path=31_143&#038;product_id=7152">Violon Taille Sebim taille ½</a></td>
<td>50</td>
<td>60</td>
<td>72</td>
<td>?
</td>
<td>?
</td>
</tr>
<tr>
<td><a href="http://www.airsoftworld.net/warrior-l96-mk-3-sniper-rifle-and-bi-pod-black.html">Fusil Sniper Airsoft MB01</a></td>
<td>40</td>
<td>65</td>
<td>78</td>
<td>175
</td>
<td>Ce genre de matos ultra spécialisé est rare, et<br />
du coup il y a moins de connaisseurs et on peut tomber sur des lots très sympas.</td>
</tr>
</tbody>
</table>
<p>Notez que le prix sur lequel on enchérie n&#8217;est pas celui qu&#8217;on paie. C&#8217;est la grande enculade des ventes aux enchères, puisque ces frais additionnels doivent être calculés de tête en permanence. Et plein de gens ne le font pas, transformant votre enchère &#8220;bonne affaire&#8221; en &#8220;achat au supermarcher&#8221;. Mémé a gagné, elle vous regarde en souriant victorieusement, et vous êtes dégoutés car vous avez raté un super prix, et elle a acheté plus cher que le prix sur le bon coin parce qu&#8217;elle est nul en calcul mental. C&#8217;est très chiant, mais c&#8217;est la jeu ma pauv&#8217; lucette.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8950&amp;md5=73c611e7473f1647314bf0f3c051e2a2" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8958
title: Trouvez l’intrus…
uri: Trouvez-l-intrus
url: http://sametmax.com/trouvez-lintrus/
content:
<p>J&#8217;adore les mots-clefs d&#8217;hier. Le troisième en particulier&#8230;</p>
<p>Cependant un intrus s&#8217;est glissé dans le décors, saurez-vous le retrouver ?</p>
<blockquote><p>sexy teacher<br />
sam et max<br />
levrette avec une vache<br />
abreviation escort<br />
escort girj cjm<br />
masturbation feminine video<br />
passe partout fort boyard<br />
video masturbation femme<br />
partouze<br />
maison close pute<br />
scene de masturbation en directe<br />
fellation tuto<br />
fkk allemagne<br />
jeune fille rentre chez elle et se masturbe video francaise<br />
truc de cul hard<br />
fonction exponentielle dans la vie de tous les jours<br />
démonstration de mastubation féminine<br />
club fkk
</p></blockquote>
<p>PS: Moi aussi je peux faire des posts bouches-trous :p<br />
PS2: Je me demande de quelle revue hautement scientifico-intellectuelle on va se faire virer maintenant.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8958&amp;md5=f53226847e96ceb87b8b175ae037c48d" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8963
title: Virtualenv EnvironmentError: mysql_config not found sous MAC OSX
uri: Virtualenv-EnvironmentError-mysql_config-not-found-sous-MAC-OSX
url: http://sametmax.com/virtualenv-environmenterror-mysql_config-not-found-sous-mac-osx/
content:
<p>Comme le post précédent est inutile j&#8217;en fait un autre qui doit concerner au moins 0.00001% de la population.</p>
<p>A vous qui essayez depuis 2 heures de configurer MySQL-python sous votre virtualenv, cet article vous est dédié.</p>
<p>Cette erreur vicieuse m&#8217;arrive à chaque fois que j&#8217;installe MySQL-python dans un nouvel environnement virtuel. Ceci dit vous l&#8217;aurez peut-être sous un autre OS. Sur centos j&#8217;avais qu&#8217;à faire un <em>yum install mysql-devel</em> mais sous Mac c&#8217;est autre chose. Plus de puissance engendre plus de responsabilités&#8230;</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">&nbsp;
Max $  pip <span style="color: #c20cb9; font-weight: bold;">install</span> MySQL-python
Downloading<span style="color: #000000; font-weight: bold;">/</span>unpacking MySQL-python
  Downloading MySQL-python-1.2.5.zip <span style="color: #7a0874; font-weight: bold;">&#40;</span>108Kb<span style="color: #7a0874; font-weight: bold;">&#41;</span>: 108Kb downloaded
  Running setup.py egg_info <span style="color: #000000; font-weight: bold;">for</span> package MySQL-python
    <span style="color: #c20cb9; font-weight: bold;">sh</span>: mysql_config: <span style="color: #7a0874; font-weight: bold;">command</span> not found
    Traceback <span style="color: #7a0874; font-weight: bold;">&#40;</span>most recent call <span style="color: #c20cb9; font-weight: bold;">last</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>:
      File <span style="color: #ff0000;">&quot;&lt;string&gt;&quot;</span>, line <span style="color: #000000;">14</span>, <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000; font-weight: bold;">&lt;</span>module<span style="color: #000000; font-weight: bold;">&gt;</span>
      File <span style="color: #ff0000;">&quot;/Users/Max/.virtualenvs/zooscator/build/MySQL-python/setup.py&quot;</span>, line <span style="color: #000000;">17</span>, <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000; font-weight: bold;">&lt;</span>module<span style="color: #000000; font-weight: bold;">&gt;</span>
        metadata, options = get_config<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
      File <span style="color: #ff0000;">&quot;setup_posix.py&quot;</span>, line <span style="color: #000000;">43</span>, <span style="color: #000000; font-weight: bold;">in</span> get_config
        libs = mysql_config<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #ff0000;">&quot;libs_r&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
      File <span style="color: #ff0000;">&quot;setup_posix.py&quot;</span>, line <span style="color: #000000;">25</span>, <span style="color: #000000; font-weight: bold;">in</span> mysql_config
        raise EnvironmentError<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #ff0000;">&quot;%s not found&quot;</span> <span style="color: #000000; font-weight: bold;">%</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mysql_config.path,<span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
    EnvironmentError: mysql_config not found
    Complete output from <span style="color: #7a0874; font-weight: bold;">command</span> python setup.py egg_info:
    <span style="color: #c20cb9; font-weight: bold;">sh</span>: mysql_config: <span style="color: #7a0874; font-weight: bold;">command</span> not found
&nbsp;
Traceback <span style="color: #7a0874; font-weight: bold;">&#40;</span>most recent call <span style="color: #c20cb9; font-weight: bold;">last</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>:
&nbsp;
  File <span style="color: #ff0000;">&quot;&lt;string&gt;&quot;</span>, line <span style="color: #000000;">14</span>, <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000; font-weight: bold;">&lt;</span>module<span style="color: #000000; font-weight: bold;">&gt;</span>
&nbsp;
  File <span style="color: #ff0000;">&quot;/Users/Max/.virtualenvs/zooscator/build/MySQL-python/setup.py&quot;</span>, line <span style="color: #000000;">17</span>, <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000; font-weight: bold;">&lt;</span>module<span style="color: #000000; font-weight: bold;">&gt;</span>
&nbsp;
    metadata, options = get_config<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
&nbsp;
  File <span style="color: #ff0000;">&quot;setup_posix.py&quot;</span>, line <span style="color: #000000;">43</span>, <span style="color: #000000; font-weight: bold;">in</span> get_config
&nbsp;
    libs = mysql_config<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #ff0000;">&quot;libs_r&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
&nbsp;
  File <span style="color: #ff0000;">&quot;setup_posix.py&quot;</span>, line <span style="color: #000000;">25</span>, <span style="color: #000000; font-weight: bold;">in</span> mysql_config
&nbsp;
    raise EnvironmentError<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #ff0000;">&quot;%s not found&quot;</span> <span style="color: #000000; font-weight: bold;">%</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>mysql_config.path,<span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
&nbsp;
EnvironmentError: mysql_config not found
&nbsp;
<span style="color: #660033;">----------------------------------------</span>
Command python setup.py egg_info failed with error code <span style="color: #000000;">1</span>
Storing <span style="color: #7a0874; font-weight: bold;">complete</span> log <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000; font-weight: bold;">/</span>Users<span style="color: #000000; font-weight: bold;">/</span>Max<span style="color: #000000; font-weight: bold;">/</span>.pip<span style="color: #000000; font-weight: bold;">/</span>pip.log</pre></div></div>

<p>Il faut éditer votre fichier <strong>activate</strong> qui se trouve dans le répertoire bin de votre environnement virtuel: ex &#8220;/Users/Max/.virtualenvs/zooscator/bin/activate&#8221;</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">vi</span> <span style="color: #000000; font-weight: bold;">/</span>Users<span style="color: #000000; font-weight: bold;">/</span>Max<span style="color: #000000; font-weight: bold;">/</span>.virtualenvs<span style="color: #000000; font-weight: bold;">/</span>zooscator<span style="color: #000000; font-weight: bold;">/</span>bin</pre></div></div>

<p><strong>Trouvez les lignes suivantes et ajoutez:</strong></p>
<blockquote><p>PATH=&#8221;$PATH:/opt/local/lib/mysql5/bin/&#8221;
</p></blockquote>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">...
<span style="color: #007800;">_OLD_VIRTUAL_PATH</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$PATH</span>&quot;</span>
<span style="color: #007800;">PATH</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$VIRTUAL_ENV</span>/bin:<span style="color: #007800;">$PATH</span>&quot;</span>
<span style="color: #007800;">PATH</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$PATH</span>:/opt/local/lib/mysql5/bin/&quot;</span>
<span style="color: #7a0874; font-weight: bold;">export</span> PATH
...</pre></div></div>

<p>Chez moi le chemin vers mysql est /opt/local/lib/mysql5/bin/, si vous ne connaissez pas le vôtre utilisez la commande <em>locate</em>: ex <em>locate mysql</em></p>
<p><strong>Une fois le fichier <em>activate</em> édité il faut le resourcer:<br />
</strong></p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">source</span> <span style="color: #000000; font-weight: bold;">/</span>Users<span style="color: #000000; font-weight: bold;">/</span>Max<span style="color: #000000; font-weight: bold;">/</span>.virtualenvs<span style="color: #000000; font-weight: bold;">/</span>zooscator<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>activate</pre></div></div>

<p><strong>Et vous pourrez alors installer MySQL-python tranquillou billou:<br />
</strong></p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">Max $  pip <span style="color: #c20cb9; font-weight: bold;">install</span> MySQL-python
&nbsp;
Downloading<span style="color: #000000; font-weight: bold;">/</span>unpacking MySQL-python
  Running setup.py egg_info <span style="color: #000000; font-weight: bold;">for</span> package MySQL-python
&nbsp;
Installing collected packages: MySQL-python
  Running setup.py <span style="color: #c20cb9; font-weight: bold;">install</span> <span style="color: #000000; font-weight: bold;">for</span> MySQL-python
<span style="color: #7a0874; font-weight: bold;">&#91;</span>....................<span style="color: #7a0874; font-weight: bold;">&#93;</span>
Successfully installed MySQL-python
Cleaning up...</pre></div></div>

<p>Je vais nourir mon cochon d&#8217;Inde.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8963&amp;md5=c153ddb9ef35528707273f7e6d6bc2fe" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=9061
title: Grosse mise à jour de la partie “cours et tutos”
uri: Grosse-mise-à-jour-de-la-partie-cours-et-tutos
url: http://sametmax.com/grosse-mise-a-jour-de-la-partie-cours-et-tutos/
content:
<p>J&#8217;ai passé la journée à trier les articles et à les classer. On a maintenant une partie &#8220;cours et tutos&#8221; bien plus structurée.</p>
<p>C&#8217;est là que je me suis aperçu de la quantité proprement monstrueuse de contenu qui a été produit sur ce blog au fil des mois.</p>
<p>Merci encore et toujours aux contributeurs et correcteurs. </p>
<p>Merci à ceux qui prennent le temps d&#8217;écrire des commentaires qui enrichissent vraiment l&#8217;article. </p>
<p>Merci aux autres bloggers qui continuent de nous linker ou carrément autoblogger. Je pense notament à un renard pirate, un bateau fantome, un bébé avec des lunettes et un gros oeil vert mal dessiné.</p>
<p><a href="http://sametmax.com/cours-et-tutos/">Faites tourner le listing, il commence à vraiment valoir la peine.</a></p>
<p>Pour l&#8217;occasion, j&#8217;ai mis à jour le <a href="https://github.com/sametmax/miroir-du-blog">dump du blog et des tweets</a> pour la consultation hors ligne.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9061&amp;md5=91fd90f6dc5fcfbd63b9881dbc73128a" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=9067
title: Listez vos formateurs
uri: Listez-vos-formateurs
url: http://sametmax.com/listez-vos-formateurs/
content:
<p>Trouver une bonne formation, c&#8217;est pas évident. Donc je me dis qu&#8217;il faudrait que j&#8217;ai une page sur le site avec un listing de bonnes adresses. Le truc, c&#8217;est que je ne peux pas vraiment le faire à partir d&#8217;adresses que je connais, car mes clients me grilleraient dans la seconde.</p>
<p>Donc voilà le plan : </p>
<p><strong>Si vous avez fait une formation Python / Django / Git (et rien d&#8217;autre) dont vous avez été satisfait, donnez en commentaire le site de l&#8217;entreprise ou du formateur indépendant avec qui vous l&#8217;avez faite.</strong> Ajoutez un petit texte d&#8217;explication sur le sujet de la formation, la date, la durée et une appréciation. Sans ça on ignorera le commentaire. Il n&#8217;y a PAS de limite de zone géographique.</p>
<p><strong>Si vous êtes un formateur INDEPENDANT (pas un organisme de formation ou une grosse boîte Python), mettez un lien vers votre site Web</strong> afin qu&#8217;on vous donne un petit coup de pouce. Si vous n&#8217;avez pas de site ou êtes limités à une zone géographique, ajoutez des précisions. Précisez aussi si vous acceptez le DIF.</p>
<p>Une fois que j&#8217;aurais quelques liens, je ferai une page permanente sur le site qui va permettre à ceux qui cherchent de tomber sur des bonnes formations. Et ceux qui sont des petits formateurs pourront bénéficier un peu de notre ref, car je sais que c&#8217;est pas facile pour eux.</p>
<p>Attention, si vous faites partie d&#8217;un organisme de formation et que vous essayez de tricher en vous faisant passer pour un client, vous prenez un risque. Si vous vous faites choper, on fera en sorte que toute la communauté Python française sache que vous êtes des connards. A bon entendeur&#8230;</p>
<p>Si vous avez un doute sur le fait que vous soyez acceptable ou pas dans le listing, postez un commentaire avec la question, on ne vous mordra pas. Vouloir un lien vers son site n&#8217;est pas un crime.</p>
<p>On ne mettra pas d&#8217;organisme de formation, ou de société spécialisée dans le Python qui fait aussi des formations, sous prétexte qu&#8217;ils ont bonne réputation. Par exemple : Logilab est une très belle société Python pour laquelle j&#8217;ai beaucoup de respect. Mais si personne ne donne un témoignage de formation avec eux, je ne les mettrai pas dans le listing. De toute façon je pense qu&#8217;ils n&#8217;en ont pas besoin :)</p>
<p>Vous avez tout à fait le droit de demander à un de vos anciens clients de venir exprès poster sur le site pour apparaitre dans le listing. Un client satisfait reste un client satisfait.</p>
<p>Il n&#8217;y a pas de limite de temps, si vous revenez dans 6 mois pour poster un truc ici, je mettrai la liste à jour.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9067&amp;md5=349d21c9f4dcdfcefac6d5d36d4916df" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=9084
title: Installer Python 2.7.x sur CentOS 6.x les doigts dans le nez
uri: Installer-Python-2-7-x-sur-CentOS-6-x-les-doigts-dans-le-nez
url: http://sametmax.com/installer-python-2-7-x-sur-centos-6-x-les-doigts-dans-le-nez/
content:
<p>J&#8217;ai la vieille habitude de bosser sur CentOS pour des raisons personnelles absolument infondées et grotesques mais les habitudes ont la vie dure comme on dit.<br />
Et ainsi va la vie, qui évolue au fil du temps, et python aussi, et les apps aussi, et un jour il faut pour des raisons de vie ou de mort passer à une version plus récente de Python.<br />
Sam a tenté cette folie il y a quelques temps, avec comme seules réserves un pot de glace ben&#038;jerry et un ouvre-boîte à bouteilles. Bien mal lui en a pris, il a passé des heures sur le serveur, a tout pété et a fini sous exomil.<br />
Suite à ça je n&#8217;ai jamais osé tenter le coup jusqu&#8217;à hier, en tombant sur <a href="https://github.com/0xdata/h2o/wiki/Installing-python-2.7-on-centos-6.3.-Follow-this-sequence-exactly-for-centos-machine-only">cet article</a> que je me propose de vous traduire.</p>
<p>CentOS 6.x vient avec Python 2.6.6, si vous tentez une mise à jour comme ça par des paquets ou en compilant les sources sans faire attention vous risquez de tout péter, car Yum utilise python lui aussi, mais la 2.6.6.</p>
<p>Je précise que le tuto à la base est pour CentOS 6.3 et Python 2.7.3 et que moi j&#8217;ai testé Python 2.7.5 sur CentOS 6.5, je pense donc que c&#8217;est bon pour à peu près toutes les versions voisines.</p>
<p>L&#8217;astuce consiste à compiler la nouvelle version de Python et de l&#8217;installer en tant que version alternative sans désinstaller celle présente sur le serveur.</p>
<p><strong>Les paquets nécessaires:<br />
</strong></p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">yum groupinstall <span style="color: #ff0000;">&quot;Development tools&quot;</span>
yum <span style="color: #660033;">-y</span> zlib-devel bzip2-devel openssl-devel ncurses-devel</pre></div></div>

<p>On télécharge la version de Python à installer, pour ma part c&#8217;était Python 2.7.5 pour pouvoir utiliser opencv. Normalement les autres versions devraient passer aussi.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #000000; font-weight: bold;">/</span>opt
<span style="color: #c20cb9; font-weight: bold;">wget</span> http:<span style="color: #000000; font-weight: bold;">//</span>www.python.org<span style="color: #000000; font-weight: bold;">/</span>ftp<span style="color: #000000; font-weight: bold;">/</span>python<span style="color: #000000; font-weight: bold;">/</span>2.7.5<span style="color: #000000; font-weight: bold;">/</span>Python-2.7.5.tar.bz2 <span style="color: #660033;">--no-check-certificate</span>
<span style="color: #c20cb9; font-weight: bold;">tar</span> xvf Python-2.7.5.tar.bz2
<span style="color: #7a0874; font-weight: bold;">cd</span> Python-2.7.5
.<span style="color: #000000; font-weight: bold;">/</span>configure <span style="color: #660033;">--prefix</span>=<span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span><span style="color: #7a0874; font-weight: bold;">local</span> <span style="color: #660033;">--enable-shared</span>
<span style="color: #c20cb9; font-weight: bold;">make</span> <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> <span style="color: #c20cb9; font-weight: bold;">make</span> altinstall</pre></div></div>

<p><strong>ATTENTION! Deux choses à ne pas oublier:</strong></p>
<p><strong><em>&#8211;enable-shared</em></strong>: Certaines applications (comme opencv) ont besoin d&#8217;avoir accès à des librairies partagées d&#8217;autres applications, c&#8217;est le fameux fichier libpython2.7.so qui fait merder vos compilations 1 fois sur deux, si si rappelez-vous&#8230;</p>
<p><strong><em>altinstall</em></strong>: ne pas utiliser install mais bien <strong><span style="color:red;">altinstall</span></strong>. install va écraser votre installation actuelle de python (2.6.6) et tout péter. altinstall va installer votre nouvelle version de python dans un autre répertoire.</p>
<p>Si tout s&#8217;est bien passé vous devriez avoir 2 versions de Python à présent.<br />
La version système 2.6.6 et la version 2.7.x dans /usr/local/bin/python2.7.<br />
Vous pouvez faire un lien symbolique pour mettre la 2.7.x par defaut:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">ln</span> <span style="color: #660033;">-s</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>python2.7 <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>python</pre></div></div>

<p><strong>Verifions que tout est ok:</strong></p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#91;</span>pina<span style="color: #000000; font-weight: bold;">@</span>colada ~<span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #666666; font-style: italic;"># python</span>
Python 2.7.5 <span style="color: #7a0874; font-weight: bold;">&#40;</span>default, Feb  <span style="color: #000000;">8</span> <span style="color: #000000;">2014</span>, 06:<span style="color: #000000;">51</span>:01<span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span>GCC 4.4.7 <span style="color: #000000;">20120313</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>Red Hat 4.4.7-<span style="color: #000000;">4</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> on linux2
Type <span style="color: #ff0000;">&quot;help&quot;</span>, <span style="color: #ff0000;">&quot;copyright&quot;</span>, <span style="color: #ff0000;">&quot;credits&quot;</span> or <span style="color: #ff0000;">&quot;license&quot;</span> <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #c20cb9; font-weight: bold;">more</span> information.
<span style="color: #000000; font-weight: bold;">&gt;&gt;&gt;</span></pre></div></div>

<p>Chez moi ça marche! Yeahhh baby!</p>
<p><strong>Cadeau BONUX! Installation de easy_install et PIP:</strong></p>
<p>Pour finir on va mettre en place le fameux <a href="http://sametmax.com/votre-python-aime-les-pip/">PIP</a> afin de pouvoir ultérieurement installer des apps.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #000000; font-weight: bold;">/</span>opt
<span style="color: #c20cb9; font-weight: bold;">wget</span> http:<span style="color: #000000; font-weight: bold;">//</span>pypi.python.org<span style="color: #000000; font-weight: bold;">/</span>packages<span style="color: #000000; font-weight: bold;">/</span>source<span style="color: #000000; font-weight: bold;">/</span>d<span style="color: #000000; font-weight: bold;">/</span>distribute<span style="color: #000000; font-weight: bold;">/</span>distribute-0.6.27.tar.gz
<span style="color: #c20cb9; font-weight: bold;">tar</span> xf distribute-0.6.27.tar.gz <span style="color: #660033;">--no-check-certificate</span>
<span style="color: #7a0874; font-weight: bold;">cd</span> distribute-0.6.27
python2.7 setup.py <span style="color: #c20cb9; font-weight: bold;">install</span></pre></div></div>

<p>Normallement vous devriez avoir un chemin easy_install version 2.7 pour votre nouvelle version Python2.7 du genre <em>/usr/local/bin/easy_install-2.7</em></p>
<p><strong>Faites un test:</strong></p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#91;</span>pina<span style="color: #000000; font-weight: bold;">@</span>colada ~<span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #666666; font-style: italic;"># ls -ltr /usr/local/bin/easy_install*</span>
<span style="color: #660033;">-rwxr-xr-x</span> <span style="color: #000000;">1</span> root root <span style="color: #000000;">340</span>  <span style="color: #000000;">8</span> févr. 06:04 <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>easy_install-<span style="color: #000000;">2.7</span>
<span style="color: #660033;">-rwxr-xr-x</span> <span style="color: #000000;">1</span> root root <span style="color: #000000;">332</span>  <span style="color: #000000;">8</span> févr. 06:04 <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>local<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>easy_install</pre></div></div>

<p><strong>Installons PIP:</strong></p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">easy_install-<span style="color: #000000;">2.7</span> pip</pre></div></div>

<p><strong>Et testons PIP:</strong></p>
<pre lang="python bash">pip install numpy
</pre>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#91;</span>pina<span style="color: #000000; font-weight: bold;">@</span>colada ~<span style="color: #7a0874; font-weight: bold;">&#93;</span><span style="color: #666666; font-style: italic;"># python</span>
Python 2.7.5 <span style="color: #7a0874; font-weight: bold;">&#40;</span>default, Feb  <span style="color: #000000;">8</span> <span style="color: #000000;">2014</span>, 06:<span style="color: #000000;">51</span>:01<span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span>GCC 4.4.7 <span style="color: #000000;">20120313</span> <span style="color: #7a0874; font-weight: bold;">&#40;</span>Red Hat 4.4.7-<span style="color: #000000;">4</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> on linux2
Type <span style="color: #ff0000;">&quot;help&quot;</span>, <span style="color: #ff0000;">&quot;copyright&quot;</span>, <span style="color: #ff0000;">&quot;credits&quot;</span> or <span style="color: #ff0000;">&quot;license&quot;</span> <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #c20cb9; font-weight: bold;">more</span> information.
<span style="color: #000000; font-weight: bold;">&gt;&gt;&gt;</span> import numpy
<span style="color: #000000; font-weight: bold;">&gt;&gt;&gt;</span> numpy.__version__
<span style="color: #ff0000;">'1.8.0'</span>
<span style="color: #000000; font-weight: bold;">&gt;&gt;&gt;</span></pre></div></div>

<p>Et c&#8217;est parti pour des heures de code afin de conquérir le monde !</p>
<p>La semaine prochaine nous verrons comment faire bouillir des lutins sans que la peau se décolle.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9084&amp;md5=248601037b7ea3a66a2082f5dd139b8e" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=9101
title: Automatiser la conversion de docx en pdf
uri: Automatiser-la-conversion-de-docx-en-pdf
url: http://sametmax.com/automatiser-la-conversion-de-docx-en-pdf/
content:
<p>Dernièrement j&#8217;ai eu le problème suivant : soit un fichier Microsoft Word en .doc ou .docx, créer un programme sous Windows qui permette de convertir ce fichier en .pdf en gardant la mise en page.</p>
<p>Le premier réflexe : &#8220;ben je vais utiliser LibreOffice&#8221;. <a href="http://api.libreoffice.org/examples/examples.html">Une belle API Python</a>, et tout, et tout. Mais couac, quelques fichiers de tests prouveront rapidement que la mise en page pouvait parfois être légèrement différente, ce qui ne remplissait pas le cahier des charges.</p>
<p>Tentative de recherche du côté de <a href="http://johnmacfarlane.net/pandoc/">PanDoc</a> qui prends en charge plus de formats que je ne peux en nommer. Malheureusement, le docx n&#8217;est supporté qu&#8217;en écriture. Diantre.</p>
<p>Une option serait d&#8217;acheter une licence Office et son <a href="http://www.microsoft.com/en-us/download/details.aspx?id=9943">plugin PDF</a> et de scripter ça avec l&#8217;API COM, mais là ça commence à revenir cher et c&#8217;est très lourd. </p>
<p>Finalement j&#8217;ai opté pour un bidouillage : utiliser <a href="http://www.microsoft.com/en-us/download/details.aspx?id=4">Microsoft Word Viewer</a> et son <a href="http://www.microsoft.com/fr-fr/download/details.aspx?id=3">addon pour docx</a>. Ensuite, pour la conversion en PDF, on installe <a href="http://www.softpedia.com/get/Office-tools/PDF/CC-PDF-Converter.shtml">CC PDF Converter</a>, qui va nous mettre une imprimante virtuelle vers du PDF.</p>
<p>Enfin, il fallait trouver un moyen de scripter tout ça. J&#8217;ai tenté <a href="https://code.google.com/p/pywinauto/">pywinauto</a>. Fail. <a href="http://www.autohotkey.com/">AutoHotKey</a>, erreurs aléatoires. Et finalement, <a href="http://www.autoitscript.com/site/autoit/">AutoIt</a>, <a href="http://sebsauvage.net/logiciels/poweruser.html">trouvé via Sebsauvage</a>.</p>
<p>Le langage est de script n&#8217;est pas (trop) horrible, et facile à comprendre :</p>
<pre>
; Matcher le nom des fenêtre par morceau sans se
; soucier de la casse.
AutoItSetOption('WinTitleMatchMode', -2) 

; Chopper les options de la ligne de commande
$VIEWER_EXE = "C:\Program Files (x86)\Microsoft Office\OFFICE11\WORDVIEW.EXE"
$FROM = $CmdLine[1]
$TO = $CmdLine[2]

; Fermer ou force killer tout ce qu'on a pu ouvrir précédement
Winclose('reader')
Winclose('viewer')
Winkill('reader')
Winkill('viewer')

; Ouvrir MS Word Viewer, et répondre "oui" à
; tout pop up qui s'ouvre en appuiyant sur
; Entrée
Run($VIEWER_EXE &#038; " " &#038; $FROM)
WinWaitActive('viewer', '', 2)
Send('{Enter}')

; Utiliser Ctrl + P pour demander une
; impression. Les paramètres par défaut
; sont ok : couleur, 1 copie, le tout
; sur le Bureau.
Send('^p')
WinWaitActive('imprimer', '', 2)
Send('{Enter}')

; On attent qu'apparaisse la fenêtre
; de choix de nom de fichier pour la
; sortie en PDF. Le focus est automatiquement
; sur le champ "name"; on a juste à écrire
; le nom de fichier de dans et à faire
; Entrée.
WinWaitActive('select a filename', '', 2)
Send($TO)
Send('{Enter}')

; Si le fichier existe déjà, il va
; demander confirmation d'écrasement
; ce qu'on fait. Si la fenêtre
; n'apparait pas, Alt+O ne fait rien
; de bien méchant de toute façon.
WinWaitActive('confirmer', '', 2)
Send('!o')

; On attend que le lecteur PDF se lance,
; prouvant que le fichier est prêt.
WinWaitActive('reader')

; Le PDF est prêt. On va pisser un coup.
; On ferme aussi toutes les fenêtres à
; coup de marteau.
Winclose('reader')
Winclose('viewer')
Winkill('reader')
Winkill('viewer')</pre>
<p>Voilà c&#8217;était le code dégueulasse du jour, Max serait fier de moi. Evidement c&#8217;est très fragile : dépendant de la config, de la langue, etc.</p>
<p>Mais zob, j&#8217;ai mon PDF.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9101&amp;md5=0453101d04f2450b1e751c8ebb40da9b" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=9106
title: Utilisez-vous l’anglais pour vos recherches d’informations ?
uri: Utilisez-vous-l-anglais-pour-vos-recherches-d-informations
url: http://sametmax.com/utlisez-vous-langlais-pour-vos-recherches-dinformations/
content:
<p>A l&#8217;heure où internet est l&#8217;outil quasi-indispensable pour trouver une information (technique ou de tous les jours) et où une grande partie de cette dernière est rédigé en anglais la question est:</p>
Note: There is a poll embedded within this post, please visit the site to participate in this post's poll.
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=9106&amp;md5=0cdf1a227b18c7a662d4e67800856b1e" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


feed_id: http://sametmax.com/?p=8748
title: La quête de la contraception masculine
uri: La-quête-de-la-contraception-masculine
url: http://sametmax.com/la-quete-de-la-contraception-masculine/
content:
<p>Aller contre la nature, c&#8217;est toujours très contraignant.</p>
<p>Par exemple, imbriquer deux organes sexuels avec une faible probabilité d&#8217;obtenir une grossesse alors qu&#8217;ils sont faits pour ça, c&#8217;est un vrai challenge.</p>
<p>A ma droite, côté nana, le choix est entre plusieurs &#8220;solutions&#8221; :</p>
<ul>
<li>Prendre un traitement hormonal sur une longue durée. On appelle ça la pilule, et on distribue ça comme si c&#8217;était des MM&#8217;s. On ne met pas sur les posters du planning familiale que ça a un impacte direct et massif sur tout le métabolisme.</li>
<li>Se faire poser un stérilet en cuivre. Beaucoup de femme ne le supportent pas. Avoir un morceau de métal à l’intérieur de soit, volontairement, c&#8217;est pas évident.</li>
<li>Le préservatif féminin. Plus où moins l&#8217;équivalent de faire l&#8217;amour avec un sac plastique Leclerc sur la schneck.</li>
<li>La méthode des températures ou du calendrier. Aussi appelée &#8220;plus près de toi mon Dieu&#8221;.</li>
<li>La ligature des trompes. C&#8217;est comme un tatouage, on risque de regretter en vieillissant..</li>
<li>L&#8217;abstinence. Plus couramment pratiquée qu&#8217;on ne le pense, plus ou moins volontairement.</li>
</ul>
<p>À ma gauche, du côté des mecs, on a :</p>
<ul>
<li>Pas de pilule (il y a un essaie en Australie, d&#8217;ici à ce que ça arrive en France, les kangourous auront migré en région Rhône-Alpes).</li>
<li>La vasectomie. 30 % de chance que ce soit réversible. Vous tentez ?</li>
<li>La capote, qu&#8217;il faut acheter, mettre, surveiller, retirer, et disposer.</li>
<li>Le spermicide, ou &#8220;tue l&#8217;amour&#8221;, qui garantie l’absence de MSOG.</li>
<li>Le caleçon chauffe couille qui transforme vos gonades en marshmallow. <a href="http://www.linternaute.com/science/technologie/dossier/8-inventions-originales-de-demain/avoir-chaud-aux-fesses.shtml">Si, si</a>.</li>
<li>L&#8217;abstinence. Toujours pratiquée moins volontairement que plus, à part chez les moines.</li>
</ul>
<p>Bref, l&#8217;humanité peut envoyer des gens sur la lune, bientôt sur Mars, et c&#8217;est toujours la merde pour tromper sa femme sans faire de bâtard.</p>
<p>Personnellement, j&#8217;ai mis une de mes partenaires enceinte, malgré l&#8217;usage du préservatif. <a href="http://www.larousse.fr/encyclopedie/divers/contraception/36657">4% de chance que ça passe au travers</a>. Je répète, 1 chance sur 25 les gars&#8230;</p>
<p>Ayant bien compris que je ne serai pas vraiment un père enthousiaste, la miss a opté pour l&#8217;IVG. Et franchement, elle a hésité. J&#8217;aime autant vous dire que c&#8217;est pas marrant du tout. Mais alors pas du tout. Déjà, elle en chie à mort car psychologiquement c&#8217;est dur, mais en plus les médocs qu&#8217;ils vous filent, à côté les laxatifs c&#8217;est des skittles.</p>
<p>Je suis très bonbons dans cet article.</p>
<p>Mais en plus vous faites plusieurs passages à l&#8217;hosto, avec tous les deux la culpabilité pour diverses raisons. La meuf, super flippée évidement, ressort de là lessivée. Et le mec garde un super souvenir de ses attentes dans les couloirs des sections &#8220;spécial gonzesse only&#8221; de l&#8217;hopital où on te mate comme le yeti. Il doit pas y avoir beaucoup d&#8217;hommes qui accompagnent leur copine durant la procédure. En tout cas on peut pas participer aux entretiens, on sait pas ce qu&#8217;il se dit, c&#8217;est long, elle peut changer d&#8217;avis durant la longue semaine de réflexion qu&#8217;on lui laisse. Et ça peut rater aussi, faut le savoir.</p>
<p>Bien, ces bases posées, vous voyez que le plaisir de fritouiller, qu&#8217;on aime bien montrer comme simple et naturel, a quand même quelques problématiques cotons. Je n&#8217;aborderais même pas les MST, je laisse ça à Max, c&#8217;est lui l&#8217;expert :)</p>
<p>Du coup, j&#8217;ai choisis l&#8217;option vasectomie. Après deux années de réflexion, je me décide, j&#8217;en parle à tout le monde, et tout le monde me bassine pendant des heures que c&#8217;est une mauvaise idée, que je suis irresponsable, et si ? et si ? et si ?</p>
<p>Toujours les mêmes arguments. Jamais une once d&#8217;esprit critique. Beaucoup de stéréotype et de formatage culturel.</p>
<p>C&#8217;est lassant.</p>
<p>Je me pointe chez le bitologue, et je lui annonce. Il me dit répond : &#8220;M. Saaaam&#8230;&#8221;</p>
<p>Il m&#8217;appelle &#8220;M. Saaaam&#8230;&#8221; en trainant sur les syllabes, sur sa chaise, légèrement surélevée pour pouvoir regarder de haut ses patients.</p>
<p>&#8220;M. Saaaam&#8230;&#8221; donc, &#8220;à votre age. Vous n&#8217;avez pas d&#8217;enfaaaaaaaants&#8230; J&#8217;ai exactement les mêmes arguments que tous vos amiiiis et votre famille sur lesquelles vous avez réfléchi pendant 2 ans et moi 5 minutes car personne n&#8217;est jamais venu se présenter avec cette requête. Bla bla bla. Cot cot cot cot.&#8221;</p>
<p>&#8220;Bref, vous n&#8217;avez pas les bonnes chaussures. Ça va pas être possible. 75 euros s&#8217;il vous plait.&#8221;</p>
<p>Je déprime un peu.</p>
<p>Depuis quelques années, je suis le projet <a href="http://fr.wikipedia.org/wiki/Risug">RISUG</a>, un truc indien encore expérimental qui consiste à injecter un polymère dans le spermiducte (ça s&#8217;appelle comme ça, juré !). Pour le moment, on a un ratio de 1 grossesse sur 250 mecs, et au max ça a tenu 10 ans. C&#8217;est réversible.</p>
<p>Ça ne protège pas des maladies (quoi que des tests sont en cours pour vérifier si ça n’arrête pas la transmission du VIH mâle => femelle), évidement, mais il n&#8217;y a pas d&#8217;effets secondaires constatés, pas de bidule à faire avant, pendant ou après l&#8217;acte, pas d&#8217;hormone à prendre pour qui que ce soit.</p>
<p>Comment ça marche ? Ça fonctionne comme un taser chimique, envoyant une charge électriques aux nageurs, annulant la leur et les rendant inertes. Imaginez Cartman à la sortie de vos couilles en train de crier &#8220;respectez mon autorité&#8221; en grillant tous les têtards qui passent.</p>
<p>Une bonne nouvelle donc, si on se sent l&#8217;âme d&#8217;un aventurier volontaire pour proposer ses bijoux de famille comme cobayes. Non je ne ferai pas de blague raciste sur le curry.</p>
<p>J&#8217;ai bien envie de me laisser tenter. Un voyage en Inde, 1000 balles. Si je me lance, je ferai un article ici pour détailler le moment où mes testicules vont devenir vertes, pourrir et se détacher. Promis.</p>
 <p><a href="http://sametmax.com/?flattrss_redirect&amp;id=8748&amp;md5=3227b313d9f41aee72f9417d620ccb6b" title="Flattr" target="_blank"><img src="media/fc229d00.flattr-badge-large.png" data-original-source="http://sametmax.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>


