<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet href="http://programmation-python.org/rss.css" type="text/css"?>
<rdf:RDF
  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns="http://purl.org/rss/1.0/"
  xmlns:xhtml="http://www.w3.org/1999/xhtml">

  <channel rdf:about="http://programmation-python.org/sections/blog/exportrss">
    <title>programmation-python.org - Tarek Ziadé</title>
    <description>RSS 1.0 export from the folder 'programmation-python.org - Tarek Ziadé'.</description>
    <link>http://programmation-python.org/sections/blog/exportrss</link>

    <items>
      <rdf:Seq>
        <rdf:li rdf:resource="http://programmation-python.org/sections/blog/2007_09_30_afpysprint-dijon" />
        <rdf:li rdf:resource="http://programmation-python.org/sections/blog/2007_09_13_dijon-capitale-du-v" />
        <rdf:li rdf:resource="http://programmation-python.org/sections/blog/2007_08_20_recherche-similitudes" />
        <rdf:li rdf:resource="http://programmation-python.org/sections/blog/2007_08_13_ressources-python" />
        <rdf:li rdf:resource="http://programmation-python.org/sections/blog/2007_08_10_widget-flash-pour-luvdit" />
        <rdf:li rdf:resource="http://programmation-python.org/sections/blog/2007_07_30_au-coeur-python-volume-1" />
        <rdf:li rdf:resource="http://programmation-python.org/sections/blog/2007_07_22_site-critiques-livre" />
        <rdf:li rdf:resource="http://programmation-python.org/sections/blog/2007_07_06_joli-trac-pour-mes" />
        <rdf:li rdf:resource="http://programmation-python.org/sections/blog/2007_07_05_service-mailing" />
        <rdf:li rdf:resource="http://programmation-python.org/sections/blog/2007_06_22_mon-voisin" />

      </rdf:Seq>
    </items>

  </channel>


  <item rdf:about="http://programmation-python.org/sections/blog/2007_09_30_afpysprint-dijon">
    <title>AfpySprint à Dijon</title>
    <description>L'A.G. de l'Afpy organisée ce week-end à Dijon, s'est transformée en AfpySprint par manque de monde pour atteindre le quorum. Le nouveau bureau de l'association sera donc voté plus tard :)&lt;br&gt;&lt;br&gt;Entre deux restos et une dégustation de vins, nous avont bossé sur trois ateliers:&lt;br&gt;&lt;ul&gt;&lt;li&gt;préparation des JFP'08, qui a été l'occasion d'une démo par Seb de MinMap pour la prise de note, avec &lt;a href="http://freemind.sourceforge.net/wiki/index.php/Main_Page"&gt;Freemind;&lt;/a&gt;&lt;br&gt;&lt;/li&gt;&lt;li&gt;création d'une application Django (afpy_jobs) pour les offres d'emplois du site, qui deviendra &lt;i&gt;jobs.afpy.org&lt;/i&gt; à terme;&lt;/li&gt;&lt;li&gt;reprise du taf sur mailwoman, qui doit nous permettre à terme de fusionner &lt;a href="http://www.gnu.org/software/mailman/index.html"&gt;mailman&lt;/a&gt; et le forum web du site.&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;Pour info, l'association a maintenant son propre serveur dedibox, et vous pouvez suivre les devs sur le repository  : &lt;a href="http://trac.afpy.org/misc"&gt;http://trac.afpy.org/misc&lt;/a&gt;&lt;br&gt;

&lt;br/&gt;
&lt;div&gt;
&lt;i&gt;&lt;small&gt;
 &lt;a target="_blank" title="envoyer par email" alt="envoyer par email" href="http://www.feedburner.com/fb/a/emailFlare?itemTitle=AfpySprint à Dijon&amp;amp;uri=http://programmation-python.org/sections/blog/2007_09_30_afpysprint-dijon""&gt;envoyer par mail&lt;/a&gt; |
 &lt;a target="_blank" title="poster sur Scoopeo" alt="poster sur Scoopeo" href="http://scoopeo.com/scoop/new?newurl=http://programmation-python.org/sections/blog/2007_09_30_afpysprint-dijon&amp;amp;title=AfpySprint à Dijon"&gt;poster sur Scoopeo&lt;/a&gt;
 &lt;a target="_blank" title="poster sur del.iciou.us" alt="poster sur del.iciou.us" href="http://del.icio.us/post?url=http://programmation-python.org/sections/blog/2007_09_30_afpysprint-dijon&amp;amp;description=AfpySprint à Dijon"&gt;poster sur del.iciou.us&lt;/a&gt;
&lt;/small&gt;&lt;/i&gt;
&lt;/div&gt;
</description>
    <link>http://programmation-python.org/sections/blog/2007_09_30_afpysprint-dijon</link>
    <dc:date>2007-09-30</dc:date>
    <dc:creator>tarek</dc:creator>
    <dc:contributor>Tarek Ziadé</dc:contributor>
    <dc:language>fr</dc:language>
    <dc:subject>afpy</dc:subject>
    <dc:subject>coding</dc:subject>
    <dc:subject>evenements</dc:subject>

  </item>
  <item rdf:about="http://programmation-python.org/sections/blog/2007_09_13_dijon-capitale-du-v">
    <title>Dijon capitale du V.. Libre !</title>
    <description>Hasard du calendrier, le mois de septembre sera riche en évènements open source à Dijon:&lt;br&gt;&lt;a href="http://linuxfr.org/2007/09/11/23082.html"&gt;&lt;br&gt;&lt;/a&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://linuxfr.org/2007/09/11/23082.html"&gt;Rendez-vous cartographique (20 sept)&lt;br&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.afpy.org/wiki/AfpyComputerCamp"&gt;Afpyro Computer Camp (29/20 sept)&lt;br&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://linuxfr.org/2007/09/06/23070.html"&gt;Debian bug squashing Party (29/30 sept)&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;Si vous aimez le vin, il faut aller au #2 ;)&lt;br&gt;

&lt;br/&gt;
&lt;div&gt;
&lt;i&gt;&lt;small&gt;
 &lt;a target="_blank" title="envoyer par email" alt="envoyer par email" href="http://www.feedburner.com/fb/a/emailFlare?itemTitle=Dijon capitale du V.. Libre !&amp;amp;uri=http://programmation-python.org/sections/blog/2007_09_13_dijon-capitale-du-v""&gt;envoyer par mail&lt;/a&gt; |
 &lt;a target="_blank" title="poster sur Scoopeo" alt="poster sur Scoopeo" href="http://scoopeo.com/scoop/new?newurl=http://programmation-python.org/sections/blog/2007_09_13_dijon-capitale-du-v&amp;amp;title=Dijon capitale du V.. Libre !"&gt;poster sur Scoopeo&lt;/a&gt;
 &lt;a target="_blank" title="poster sur del.iciou.us" alt="poster sur del.iciou.us" href="http://del.icio.us/post?url=http://programmation-python.org/sections/blog/2007_09_13_dijon-capitale-du-v&amp;amp;description=Dijon capitale du V.. Libre !"&gt;poster sur del.iciou.us&lt;/a&gt;
&lt;/small&gt;&lt;/i&gt;
&lt;/div&gt;
</description>
    <link>http://programmation-python.org/sections/blog/2007_09_13_dijon-capitale-du-v</link>
    <dc:date>2007-09-13</dc:date>
    <dc:creator>tarek</dc:creator>
    <dc:contributor>Tarek Ziadé</dc:contributor>
    <dc:language>fr</dc:language>
    <dc:subject>evenements</dc:subject>

  </item>
  <item rdf:about="http://programmation-python.org/sections/blog/2007_08_20_recherche-similitudes">
    <title>Recherche des similitudes par inférence Bayesienne</title>
    <description>Le site &lt;a href="http://fr.luvdit.com"&gt;fr.luvdit.com&lt;/a&gt; permet de proposer aux visiteurs une sélection de livres grâce au &lt;a href="http://programmation-python.org/sections/blog/2007_06_22_mon-voisin"&gt;k-NN&lt;/a&gt;, mais il part du principe que ces derniers utilisent avec pertinence les étiquettes, ce qui est loin d'être systèmatique: seuls les geeks et les personnes habituées aux sites comme flickr ou delicious le font correctement.&lt;br&gt;&lt;br&gt;Pour pallier à ce problème, une autre méthode de sélection peut venir renforcer celle du k-NN: &lt;a href="http://fr.wikipedia.org/wiki/Inf%C3%A9rence_bay%C3%A9sienne"&gt;l'inférence bayesienne&lt;/a&gt;. Cette technique permet d'associer à des catégories une liste de mots (==un texte). Lorsqu'une nouvelle liste de mots est rencontrée, le système calcul la probabilité d'appartenance à chacune des catégories existantes, en fonction des listes  de mots déjà croisées. Pour augmenter la pertinence, les mots communs ou courts sont supprimés, pour tenter de conserver l'essence du texte.&lt;br&gt;&lt;br&gt;Elle est appliquée ainsi au site:&lt;br&gt;&lt;ul&gt;&lt;li&gt;Le résumé (==la liste des mots) de chaque livre commenté par un utilisateur est associé à une étiquette correspondant à la note que ce dernier a donné;&lt;/li&gt;&lt;li&gt;de la même manière, le résumé est associé à chaque étiquette que l'utilisateur a donné.&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;Lorsque des nouveaux livres sont ajoutés, le système va calculer pour chaque:&lt;br&gt;&lt;ul&gt;&lt;li&gt;la note que l'utilisateur pourrait donner;&lt;/li&gt;&lt;li&gt;les étiquettes qu'il pourrait mettre.&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;Les propositions obtenues par le k-NN peuvent dès lors être renforcées par ce résultat:&lt;br&gt;&lt;ul&gt;&lt;li&gt;les livres à note possible élevée sont mis en avant;&lt;/li&gt;&lt;li&gt;lorsque l'utilisateur choisi des étiquettes, celles calculées par le systèmes sont proposées.&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;Pour affiner les calculs, l'utilisateur pourra réfuter un livre en indiquant que ce dernier ne l'intéresse pas. Cette action aura pour effet de recalculer les probabilités des catégories. Le code-maquette est ici: &lt;a href="http://hg.programmation-python.org/browser/classifier"&gt;http://hg.programmation-python.org/browser/classifier.&lt;/a&gt; Mais est encore affreusement lent à cause d'une mauvaise conception au niveau du stockage SQL. Il est en cours de refactorisation, mais fonctionne déjà. A terme le paquet &lt;i&gt;classifier&lt;/i&gt; pourra servir à n'importe quel besoin d'inférence bayésienne (et il y en a partout). &lt;a href="http://hg.programmation-python.org/browser/classifier/doc/classifier.txt"&gt;Le doctest montre le fonctionnement&lt;/a&gt;.&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;

&lt;br/&gt;
&lt;div&gt;
&lt;i&gt;&lt;small&gt;
 &lt;a target="_blank" title="envoyer par email" alt="envoyer par email" href="http://www.feedburner.com/fb/a/emailFlare?itemTitle=Recherche des similitudes par inférence Bayesienne&amp;amp;uri=http://programmation-python.org/sections/blog/2007_08_20_recherche-similitudes""&gt;envoyer par mail&lt;/a&gt; |
 &lt;a target="_blank" title="poster sur Scoopeo" alt="poster sur Scoopeo" href="http://scoopeo.com/scoop/new?newurl=http://programmation-python.org/sections/blog/2007_08_20_recherche-similitudes&amp;amp;title=Recherche des similitudes par inférence Bayesienne"&gt;poster sur Scoopeo&lt;/a&gt;
 &lt;a target="_blank" title="poster sur del.iciou.us" alt="poster sur del.iciou.us" href="http://del.icio.us/post?url=http://programmation-python.org/sections/blog/2007_08_20_recherche-similitudes&amp;amp;description=Recherche des similitudes par inférence Bayesienne"&gt;poster sur del.iciou.us&lt;/a&gt;
&lt;/small&gt;&lt;/i&gt;
&lt;/div&gt;
</description>
    <link>http://programmation-python.org/sections/blog/2007_08_20_recherche-similitudes</link>
    <dc:date>2007-08-20</dc:date>
    <dc:creator>tarek</dc:creator>
    <dc:contributor>Tarek Ziadé, root</dc:contributor>
    <dc:language>fr</dc:language>
    <dc:subject>coding</dc:subject>

  </item>
  <item rdf:about="http://programmation-python.org/sections/blog/2007_08_13_ressources-python">
    <title>Ressources Python</title>
    <description>Cette page regroupe une liste de ressources web pour le langage Python, organisées en catégories. Elle démarre à peine et sera mise à jour régulièrement.&lt;br&gt;&lt;br&gt;Catégories:&lt;br&gt;&lt;br&gt;&lt;ul&gt;&lt;li&gt;Référence du langage&lt;br&gt;&lt;/li&gt;&lt;li&gt;Aide-mémoire&lt;/li&gt;&lt;li&gt;Bibliothèques tierces&lt;/li&gt;&lt;li&gt;Frameworks web&lt;br&gt;&lt;/li&gt;&lt;li&gt;Blogs&lt;/li&gt;&lt;li&gt;Sites web&lt;/li&gt;&lt;li&gt;Présentations, tutoriels&lt;br&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;&lt;h2&gt;Référence du langage&lt;br&gt;&lt;/h2&gt;&lt;br&gt;&lt;a href="http://docs.python.org/"&gt;http://docs.python.org/&lt;/a&gt; est le point de départ pour rechercher de la documentation en ligne sur la syntaxe de Python. Les sections les plus importantes sont:&lt;br&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://docs.python.org/lib/lib.html"&gt;La référence de la bibliothèque standard&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://docs.python.org/tut/tut.html"&gt;Un tutoriel qui parcourt les principales fonctionnalités du langage&lt;/a&gt;&lt;br&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;&lt;h2&gt;Aide-mémoire&lt;/h2&gt;&lt;br&gt;Laurent Pointal maintient une &lt;a href="http://www.limsi.fr/Individu/pointal/python/pqrc/"&gt;Quick Reference Card&lt;/a&gt; qui regroupe sur une feuille A4 une cheatsheet.&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;h2&gt;Bibliothèques tierces&lt;/h2&gt;&lt;br&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.sqlalchemy.org/"&gt;SQLAlchemy&lt;/a&gt;, &lt;a href="http://fr.wikipedia.org/wiki/Object-relational_mapping"&gt;ORM&lt;/a&gt; le plus utilisé&lt;br&gt; &lt;/li&gt;&lt;/ul&gt;&lt;br&gt;&lt;br&gt;&lt;h2&gt;Frameworks web&lt;/h2&gt;&lt;br&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.djangoproject.com/"&gt;Django&lt;/a&gt;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Extensions&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Extension &lt;a href="http://code.google.com/p/django-openid/"&gt;django-openid&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Extension &lt;a href="http://code.google.com/p/django-voting/"&gt;django-voting&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Plus d'extensions via &lt;a href="http://www.google.com/search?q=django-+-:inurl:/source+-inurl:/wiki+-inurl:/soc&amp;amp;hl=en&amp;amp;domains=code.google.com&amp;amp;sitesearch=code.google.com&amp;amp;start=0&amp;amp;sa=N"&gt;une recherche google&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Environnement de développement pour Windows: &lt;a href="http://www.instantdjango.com/"&gt;Instant Django&lt;/a&gt;&lt;br&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;a href="http://pylonshq.com/"&gt;Pylons&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://zope.org"&gt;Zope&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://turbogears.org/"&gt;TurboGears&lt;/a&gt;&lt;br&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;&lt;br&gt;Comparatifs en français : &lt;a href="http://www.biologeek.com/journal/index.php/comparaison-de-turbogears-et-django-deux-frameworks-web-python"&gt;Django vs Turbogears&lt;/a&gt;&lt;br&gt;&lt;br&gt;&lt;h2&gt;Blogs&lt;/h2&gt;&lt;br&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.biologeek.com/journal/"&gt;Biologeek&lt;/a&gt;, orienté Django&lt;/li&gt;&lt;li&gt;&lt;a href="http://kib2.webfactional.com/"&gt;Kib's blog&lt;/a&gt;, LaTeX, Django et reSTructuredText&lt;/li&gt;&lt;li&gt;&lt;a href="http://jehaisleprintemps.net/"&gt;Je Hais le Printemps&lt;/a&gt;, Django, Ubuntu&lt;br&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;-&amp;gt; si vous avez un blog, n'hésitez pas à le signaler en commentant&lt;br&gt;&lt;br&gt;&lt;h2&gt;Sites web&lt;/h2&gt;&lt;br&gt;&lt;ul&gt;&lt;li&gt;Le site de l'Afpy (Asssociation Francophone Python) : &lt;a href="http://afpy.org"&gt;http://afpy.org&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.learningpython.com/"&gt;LearningPython&lt;/a&gt;, tutoriel simples et efficaces en anglais&lt;/li&gt;&lt;li&gt;Dive Into Python, &lt;a href="http://diveintopython.org/"&gt;version anglaise&lt;/a&gt;, &lt;a href="http://diveintopython.adrahon.org/"&gt;version française&lt;/a&gt;&lt;br&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;&lt;br&gt;&lt;h2&gt;Présentations, tutoriels&lt;/h2&gt;&lt;br&gt;&lt;ul&gt;&lt;li&gt;Django à Oscon: &lt;a href="http://toys.jacobian.org/presentations/2007/oscon/tutorial/"&gt;http://toys.jacobian.org/presentations/2007/oscon/tutorial/&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;N'hésitez pas à commenter ce billet pour le compléter&lt;br&gt;&lt;br&gt;

&lt;br/&gt;
&lt;div&gt;
&lt;i&gt;&lt;small&gt;
 &lt;a target="_blank" title="envoyer par email" alt="envoyer par email" href="http://www.feedburner.com/fb/a/emailFlare?itemTitle=Ressources Python&amp;amp;uri=http://programmation-python.org/sections/blog/2007_08_13_ressources-python""&gt;envoyer par mail&lt;/a&gt; |
 &lt;a target="_blank" title="poster sur Scoopeo" alt="poster sur Scoopeo" href="http://scoopeo.com/scoop/new?newurl=http://programmation-python.org/sections/blog/2007_08_13_ressources-python&amp;amp;title=Ressources Python"&gt;poster sur Scoopeo&lt;/a&gt;
 &lt;a target="_blank" title="poster sur del.iciou.us" alt="poster sur del.iciou.us" href="http://del.icio.us/post?url=http://programmation-python.org/sections/blog/2007_08_13_ressources-python&amp;amp;description=Ressources Python"&gt;poster sur del.iciou.us&lt;/a&gt;
&lt;/small&gt;&lt;/i&gt;
&lt;/div&gt;
</description>
    <link>http://programmation-python.org/sections/blog/2007_08_13_ressources-python</link>
    <dc:date>2007-08-13</dc:date>
    <dc:creator>tarek</dc:creator>
    <dc:contributor>Tarek Ziadé, root</dc:contributor>
    <dc:language>fr</dc:language>
    <dc:subject>coding</dc:subject>
    <dc:subject>documentation</dc:subject>
    <dc:subject>livre</dc:subject>

  </item>
  <item rdf:about="http://programmation-python.org/sections/blog/2007_08_10_widget-flash-pour-luvdit">
    <title>Un widget flash pour luvdit!</title>
    <description>&lt;a href="http://fantomas.jjteam.info"&gt;Julien&lt;/a&gt; m'a fait un petit widget flash pour &lt;a href="http://fr.luvdit.com"&gt;ludvit!&lt;/a&gt;. Le code récupère un flux xml sur le site, qui permet de lister les 5 derniers items commentés ou ajoutés par un utilisateur donné. Il apparaît sur mon blog à gauche.&lt;br&gt;&lt;br&gt;Voici le code à inclure:&lt;br&gt;
&lt;pre&gt;&amp;lt;object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" &lt;br&gt;        codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" &lt;br&gt;        width="80" height="450" id="widget" align="middle"&amp;gt;&lt;br&gt; &amp;lt;param name="allowScriptAccess" value="sameDomain" /&amp;gt; &lt;br&gt; &amp;lt;param name="FlashVars" value="user=tarek"&amp;gt;&lt;br&gt; &amp;lt;param name="wmode" value="transparent" /&amp;gt;&lt;br&gt; &amp;lt;param name="movie" value="http://fr.luvdit.com/js/widget.swf" /&amp;gt;&lt;br&gt; &amp;lt;param name="loop" value="false" /&amp;gt;&lt;br&gt; &amp;lt;param name="menu" value="false" /&amp;gt;&lt;br&gt; &amp;lt;param name="quality" value="high" /&amp;gt;&lt;br&gt; &amp;lt;param name="bgcolor" value="#ffffff" /&amp;gt;&lt;br&gt; &amp;lt;embed src="http://fr.luvdit.com/js/widget.swf" &lt;br&gt;        FlashVars="user=tarek" loop="false" menu="false" &lt;br&gt;        quality="high" bgcolor="#ffffff" width="80" &lt;br&gt;        height="450" name="widget" align="middle" &lt;br&gt;        allowScriptAccess="sameDomain" &lt;br&gt;        wmode="transparent"&lt;br&gt;        type="application/x-shockwave-flash" &lt;br&gt;        pluginspage="http://www.macromedia.com/go/getflashplayer" /&amp;gt;&lt;br&gt;&amp;lt;br/&amp;gt;&lt;br&gt;&amp;lt;a href="http://fr.luvdit.com"&amp;gt;luvdit!&amp;lt;/a&amp;gt;&lt;br&gt;&lt;/pre&gt;

Si vous avez un compte sur le site, il suffit de remplacer 'tarek' par votre login dans les paramètres du widget.&lt;br&gt;

&lt;br/&gt;
&lt;div&gt;
&lt;i&gt;&lt;small&gt;
 &lt;a target="_blank" title="envoyer par email" alt="envoyer par email" href="http://www.feedburner.com/fb/a/emailFlare?itemTitle=Un widget flash pour luvdit!&amp;amp;uri=http://programmation-python.org/sections/blog/2007_08_10_widget-flash-pour-luvdit""&gt;envoyer par mail&lt;/a&gt; |
 &lt;a target="_blank" title="poster sur Scoopeo" alt="poster sur Scoopeo" href="http://scoopeo.com/scoop/new?newurl=http://programmation-python.org/sections/blog/2007_08_10_widget-flash-pour-luvdit&amp;amp;title=Un widget flash pour luvdit!"&gt;poster sur Scoopeo&lt;/a&gt;
 &lt;a target="_blank" title="poster sur del.iciou.us" alt="poster sur del.iciou.us" href="http://del.icio.us/post?url=http://programmation-python.org/sections/blog/2007_08_10_widget-flash-pour-luvdit&amp;amp;description=Un widget flash pour luvdit!"&gt;poster sur del.iciou.us&lt;/a&gt;
&lt;/small&gt;&lt;/i&gt;
&lt;/div&gt;
</description>
    <link>http://programmation-python.org/sections/blog/2007_08_10_widget-flash-pour-luvdit</link>
    <dc:date>2007-08-10</dc:date>
    <dc:creator>tarek</dc:creator>
    <dc:contributor>Tarek Ziadé</dc:contributor>
    <dc:language>fr</dc:language>
    <dc:subject>coding</dc:subject>

  </item>
  <item rdf:about="http://programmation-python.org/sections/blog/2007_07_30_au-coeur-python-volume-1">
    <title>Au coeur de Python Volume 1</title>
    <description>J'ai reçu la traduction de l'ouvrage de Wesley Chun, "Core Python Programming". La version française se présente en deux tomes, dont voici le premier:&lt;br&gt;&lt;a href="http://fr.luvdit.com/items/17/"&gt;&lt;br&gt;Au coeur de Python, Tome 1, Notions fondamentales&lt;/a&gt;&lt;br&gt;&lt;br&gt;Si vous l'avez lu, n'hésitez pas à commenter la fiche&lt;br&gt;

&lt;br/&gt;
&lt;div&gt;
&lt;i&gt;&lt;small&gt;
 &lt;a target="_blank" title="envoyer par email" alt="envoyer par email" href="http://www.feedburner.com/fb/a/emailFlare?itemTitle=Au coeur de Python Volume 1&amp;amp;uri=http://programmation-python.org/sections/blog/2007_07_30_au-coeur-python-volume-1""&gt;envoyer par mail&lt;/a&gt; |
 &lt;a target="_blank" title="poster sur Scoopeo" alt="poster sur Scoopeo" href="http://scoopeo.com/scoop/new?newurl=http://programmation-python.org/sections/blog/2007_07_30_au-coeur-python-volume-1&amp;amp;title=Au coeur de Python Volume 1"&gt;poster sur Scoopeo&lt;/a&gt;
 &lt;a target="_blank" title="poster sur del.iciou.us" alt="poster sur del.iciou.us" href="http://del.icio.us/post?url=http://programmation-python.org/sections/blog/2007_07_30_au-coeur-python-volume-1&amp;amp;description=Au coeur de Python Volume 1"&gt;poster sur del.iciou.us&lt;/a&gt;
&lt;/small&gt;&lt;/i&gt;
&lt;/div&gt;
</description>
    <link>http://programmation-python.org/sections/blog/2007_07_30_au-coeur-python-volume-1</link>
    <dc:date>2007-07-30</dc:date>
    <dc:creator>tarek</dc:creator>
    <dc:contributor>Tarek Ziadé</dc:contributor>
    <dc:language>fr</dc:language>
    <dc:subject>documentation</dc:subject>

  </item>
  <item rdf:about="http://programmation-python.org/sections/blog/2007_07_22_site-critiques-livre">
    <title>Un site de critiques de livre</title>
    <description>J'ai commencé à regrouper sur un &lt;a href="http://fr.luvdit.com"&gt;site&lt;/a&gt; toutes mes lectures. L'application qui fait fonctionner ce site reprend tous les principes énoncés dans les billets suivants:&lt;br&gt;&lt;br&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://programmation-python.org/sections/blog/2007_07_05_service-mailing"&gt;Service de mailing asynchrone&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://programmation-python.org/sections/blog/2007_06_22_mon-voisin"&gt;Qui est mon voisin ?&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://programmation-python.org/sections/blog/2007_06_18_cache-local-pour"&gt;Cache local pour des ressources tierces&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://programmation-python.org/sections/blog/2007_06_12_serveur-d-indexation"&gt;Serveur d'indexation Xapian&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://programmation-python.org/sections/blog/2007_06_07_indexation-facile-rapide"&gt;Indexation facile avec Xapian&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;Un widget en flash permet aussi d'afficher sur un blog (regardez à gauche) ses 5 dernières critiques (merci Julien).&lt;br&gt;&lt;br&gt;Et c'est &lt;a href="http://www.djangoproject.com/"&gt;Django&lt;/a&gt; Powered. Si vous aimez bien lire et partager, rejoignez moi sur &lt;a href="http://fr.luvdit.com"&gt;fr.luvdit.com&lt;/a&gt;, même s'il n'est pas tout à fait terminé, il est déjà utilisable.&lt;br&gt;

&lt;br/&gt;
&lt;div&gt;
&lt;i&gt;&lt;small&gt;
 &lt;a target="_blank" title="envoyer par email" alt="envoyer par email" href="http://www.feedburner.com/fb/a/emailFlare?itemTitle=Un site de critiques de livre&amp;amp;uri=http://programmation-python.org/sections/blog/2007_07_22_site-critiques-livre""&gt;envoyer par mail&lt;/a&gt; |
 &lt;a target="_blank" title="poster sur Scoopeo" alt="poster sur Scoopeo" href="http://scoopeo.com/scoop/new?newurl=http://programmation-python.org/sections/blog/2007_07_22_site-critiques-livre&amp;amp;title=Un site de critiques de livre"&gt;poster sur Scoopeo&lt;/a&gt;
 &lt;a target="_blank" title="poster sur del.iciou.us" alt="poster sur del.iciou.us" href="http://del.icio.us/post?url=http://programmation-python.org/sections/blog/2007_07_22_site-critiques-livre&amp;amp;description=Un site de critiques de livre"&gt;poster sur del.iciou.us&lt;/a&gt;
&lt;/small&gt;&lt;/i&gt;
&lt;/div&gt;
</description>
    <link>http://programmation-python.org/sections/blog/2007_07_22_site-critiques-livre</link>
    <dc:date>2007-07-22</dc:date>
    <dc:creator>tarek</dc:creator>
    <dc:contributor>Tarek Ziadé</dc:contributor>
    <dc:language>fr</dc:language>
    <dc:subject>coding</dc:subject>
    <dc:subject>django</dc:subject>
    <dc:subject>documentation</dc:subject>
    <dc:subject>litterature</dc:subject>
    <dc:subject>livre</dc:subject>

  </item>
  <item rdf:about="http://programmation-python.org/sections/blog/2007_07_06_joli-trac-pour-mes">
    <title>Un joli trac pour mes projets</title>
    <description>J'ai insallé un trac pour mes projets, avec &lt;a href="http://trac.edgewall.org/wiki/TracMercurial"&gt;le plugin Mercurial&lt;/a&gt;.&lt;br&gt;&lt;br&gt;&lt;a href="http://hg.programmation-python.org/"&gt;http://hg.programmation-python.org/&lt;/a&gt;&lt;br&gt;&lt;br&gt;L'interface est beaucoup pus agréable que le browser web par défaut de Mercurial.&lt;br&gt;&lt;br&gt;Joie.&lt;br&gt;

&lt;br/&gt;
&lt;div&gt;
&lt;i&gt;&lt;small&gt;
 &lt;a target="_blank" title="envoyer par email" alt="envoyer par email" href="http://www.feedburner.com/fb/a/emailFlare?itemTitle=Un joli trac pour mes projets&amp;amp;uri=http://programmation-python.org/sections/blog/2007_07_06_joli-trac-pour-mes""&gt;envoyer par mail&lt;/a&gt; |
 &lt;a target="_blank" title="poster sur Scoopeo" alt="poster sur Scoopeo" href="http://scoopeo.com/scoop/new?newurl=http://programmation-python.org/sections/blog/2007_07_06_joli-trac-pour-mes&amp;amp;title=Un joli trac pour mes projets"&gt;poster sur Scoopeo&lt;/a&gt;
 &lt;a target="_blank" title="poster sur del.iciou.us" alt="poster sur del.iciou.us" href="http://del.icio.us/post?url=http://programmation-python.org/sections/blog/2007_07_06_joli-trac-pour-mes&amp;amp;description=Un joli trac pour mes projets"&gt;poster sur del.iciou.us&lt;/a&gt;
&lt;/small&gt;&lt;/i&gt;
&lt;/div&gt;
</description>
    <link>http://programmation-python.org/sections/blog/2007_07_06_joli-trac-pour-mes</link>
    <dc:date>2007-07-06</dc:date>
    <dc:creator>tarek</dc:creator>
    <dc:contributor>Tarek Ziadé</dc:contributor>
    <dc:language>fr</dc:language>
    <dc:subject>misc</dc:subject>

  </item>
  <item rdf:about="http://programmation-python.org/sections/blog/2007_07_05_service-mailing">
    <title>Service de mailing asynchrone pour Django, Plone, etc..</title>
    <description>Django ne déroge pas à la règle, et fourni dans comme pour la plupart des frameworks web Python, un module pour l'envoi de mail totalement... inutilisable dans des conditions de production. En effet, &lt;i&gt;send_mail&lt;/i&gt; et &lt;i&gt;send_mass_mail&lt;/i&gt;, les deux API de &lt;a href="http://code.djangoproject.org/browser/django/trunk/django/core/mail.py"&gt;&lt;i&gt;django.core.mail&lt;/i&gt;&lt;/a&gt;, envoient tous les deux les mails de manière synchrone. &lt;br&gt;&lt;br&gt;L'effet est relativement désastreux sur les performances du site puisque chaque envoi de mail provoque un blocage du thread en cours, le temps de l'échange avec le serveur SMTP via telnet. Sur un site chargé, ou qui utilise de façon massive les envois de mails, l'emploi de &lt;i&gt;django.core.mail&lt;/i&gt; est donc fortement déconseillé.&lt;br&gt;&lt;br&gt;Plus globalement, tout code qui n'entre pas en ligne de compte pour calculer la page à afficher, ne doit pas s'exécuter de manière synchrone (autres exemples de calculs asynchrones: &lt;a href="http://programmation-python.org/sections/blog/2007_06_22_mon-voisin"&gt;calculs des voisins&lt;/a&gt;, &lt;a href="http://programmation-python.org/sections/blog/2007_06_12_serveur-d-indexation"&gt;indexation&lt;/a&gt;, etc).&lt;br&gt;&lt;br&gt;Zope 3, un peu plus mature et sophistiqué que les autres frameworks sur ce point précis, propose un module d'envoi de mails asynchrone, qui recopie les mails dans un répertoire au format &lt;a href="http://en.wikipedia.org/wiki/Maildir"&gt;&lt;i&gt;Maildir&lt;/i&gt;,&lt;/a&gt; et lance un thread en charge de dépiler les mails du répertoire. L'interêt, outre l'aspect asynchrone qui permet d'accélerer les envois et de libérer le thread qui sert la page immédiatement, est la robustesse: si le serveur tombe, le thread peut reprendre son travail d'envoi lorsqu'il est relancé.&lt;br&gt;&lt;br&gt;Mais cette solution reste liée au serveur d'application car le thread est lié au processus. L'autre défaut est qu'il est nécessaire, si l'on veut ajouter des informations supplémentaires aux mails à traiter, d'ajouter des en-têtes pour respecter le format &lt;a href="http://www.faqs.org/rfcs/rfc2822.html"&gt;RFC-2822&lt;/a&gt; des mails qui sont recopiés dans la maildir (et de les retirer avant l'envoi réel des mails). Enfin, le code devient dépendant du système de fichiers, ce qui peut poser des problèmes d'infrastructure si l'on déploie ce service d'envoi de mails sur une machine tierce au serveur d'application.&lt;br&gt;&lt;br&gt;Une autre solution, beaucoup plus robuste, consiste à déposer ces mails dans une table de base de donnée relationnelle (celle employée par le site dans Django, ou une dédiée pour Zope) qui est lue régulièrement par un service d'envois de mails, totalement indépendant du serveur web.&lt;br&gt;&lt;br&gt;&lt;h3&gt;Deux tables pour le prix d'une&lt;/h3&gt;&lt;br&gt;Pour mettre en place ce service, deux tables sont créées dans la base de données, grâce à SQLAlchemy:&lt;br&gt;
&lt;pre&gt;mail_data = Table('mailer_mail_data', metadata,&lt;br&gt;                   Column('id', Integer, primary_key=True, autoincrement=True),&lt;br&gt;                   Column('subject', String(300)),&lt;br&gt;                   Column('sender', String(300)),&lt;br&gt;                   Column('recipients', String(300)),&lt;br&gt;                   Column('date', DateTime()),&lt;br&gt;                   Column('data', TEXT()))&lt;br&gt;&lt;br&gt;mailed_data = Table('mailer_mailed_data', metadata,&lt;br&gt;                   Column('id', Integer, primary_key=True, autoincrement=True),&lt;br&gt;                   Column('subject', String(300)),&lt;br&gt;                   Column('sender', String(300)),&lt;br&gt;                   Column('original_id', Integer),&lt;br&gt;                   Column('recipients', String(300)),&lt;br&gt;                   Column('error', String(300)),&lt;br&gt;                   Column('data', TEXT()),&lt;br&gt;                   Column('date', DateTime()),&lt;br&gt;                   Column('status', String(10)),)&lt;br&gt;&lt;/pre&gt;

La table &lt;i&gt;mail_data&lt;/i&gt; sert à stocker les informations sur les mails à envoyer, et la table &lt;i&gt;mailed_data&lt;/i&gt; permet de stocker les mails envoyés, avec pour chaque un statut, si jamais l'envoi a échoué. Cette deuxième table permet aux applications de mettre en place du feedback en cas de problème d'envoi.&lt;br&gt;&lt;br&gt;&lt;h3&gt;Travailleuse, travailleur&lt;/h3&gt;&lt;br&gt;Le programme en charge d'envoyer les mails est un thread qui ouvre régulièrement la base pour:&lt;br&gt;&lt;ul&gt;&lt;li&gt;Lire la table &lt;i&gt;mail_data&lt;/i&gt; et envoyer les mails qu'elle contient&lt;/li&gt;&lt;li&gt;Archiver les mails envoyés, avec ou sans erreurs, dans &lt;i&gt;mailed_data&lt;/i&gt;&lt;/li&gt;&lt;li&gt;Supprimer les mails envoyés de la table &lt;i&gt;mail_data&lt;/i&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br&gt;Il est lancé comme programme indépendant vi un script &lt;i&gt;run.py&lt;/i&gt;, qui peut être dameonisé sur le serveur grâce aux &lt;a href="http://cr.yp.to/daemontools.html"&gt;dameontools&lt;/a&gt; par exemple (il y a surement plus simple de nos jours avis aux experts Linux...)&lt;br&gt;
&lt;pre&gt;class MailWorker(Thread):&lt;br&gt;    """reads the SQLDB to do the jobs"""&lt;br&gt;&lt;br&gt;    def __init__(self):&lt;br&gt;        Thread.__init__(self)&lt;br&gt;        self.is_working = False&lt;br&gt;        self.running = False&lt;br&gt;&lt;br&gt;    def _get_mails(self):&lt;br&gt;        """returns lines of mail_data """&lt;br&gt;        return mail_data.select().execute().fetchall()&lt;br&gt;&lt;br&gt;    def _get_message(self, mail):&lt;br&gt;        """returns a Mime"""&lt;br&gt;        msg = MIMEText(b64decode(mail.data))&lt;br&gt;        msg['From'] = mail.sender&lt;br&gt;        msg['To'] = mail.recipients&lt;br&gt;        msg['Subject'] = mail.subject&lt;br&gt;&lt;br&gt;        msg['Date'] = mail.date.isoformat()&lt;br&gt;        return msg&lt;br&gt;&lt;br&gt;    def _send_mail(self, mail):&lt;br&gt;        """sends the mail"""&lt;br&gt;        server = smtplib.SMTP(settings.SMTP_SERVER)&lt;br&gt;        msg = self._get_message(mail)&lt;br&gt;        try:&lt;br&gt;            server.sendmail(msg['From'], msg['To'], msg.as_string())&lt;br&gt;        finally:&lt;br&gt;            server.quit()&lt;br&gt;        logging.debug('mailer:message sent to %s' % msg['To'])&lt;br&gt;&lt;br&gt;    def _store_mail(self, mail, error=None):&lt;br&gt;        """stores the mail"""&lt;br&gt;        if error is not None:&lt;br&gt;            error = str(error)&lt;br&gt;        ins = mailed_data.insert()&lt;br&gt;        ins.execute(subject=mail.subject, sender=mail.sender,&lt;br&gt;                    original_id=mail.id, recipients=mail.recipients,&lt;br&gt;                    error=error, data=mail.data, date=datetime.now(),&lt;br&gt;                    status='processed')&lt;br&gt;&lt;br&gt;        # removes from original table&lt;br&gt;        mail_data.delete().execute(id=mail.id)&lt;br&gt;&lt;br&gt;    def run(self):&lt;br&gt;        """called threaded"""&lt;br&gt;        self.running = True&lt;br&gt;        logging.debug('mailer:launched')&lt;br&gt;&lt;br&gt;        while self.running:&lt;br&gt;            # index&lt;br&gt;            self.is_working = True&lt;br&gt;            try:&lt;br&gt;                # get mails to send&lt;br&gt;                mails = self._get_mails()&lt;br&gt;                for mail in mails:&lt;br&gt;                    try:&lt;br&gt;                        # send then&lt;br&gt;                        self._send_mail(mail)&lt;br&gt;                    except Exception, e:&lt;br&gt;                        logging.debug('mailer:failed to send mail')&lt;br&gt;                        self._store_mail(mail, e)&lt;br&gt;                    else:&lt;br&gt;                        self._store_mail(mail)&lt;br&gt;            finally:&lt;br&gt;                self.is_working = False&lt;br&gt;                time.sleep(.1)&lt;br&gt;&lt;br&gt;        logging.debug('mailer:stopped')&lt;br&gt;&lt;br&gt;worker = None&lt;br&gt;&lt;br&gt;def start_server():&lt;br&gt;    """starts the worker"""&lt;br&gt;    global worker&lt;br&gt;    worker = MailWorker()&lt;br&gt;    worker.start()&lt;br&gt;&lt;br&gt;def stop_server():&lt;br&gt;    """stops the worker"""&lt;br&gt;    global worker&lt;br&gt;    if worker is not None:&lt;br&gt;        worker.running = False&lt;br&gt;        worker.join()&lt;br&gt;        worker = None&lt;br&gt;&lt;br&gt;def is_working():&lt;br&gt;    """tells if the worker works"""&lt;br&gt;    return worker.is_working&lt;br&gt;&lt;br&gt;# will make sure the thread stops when the process quits&lt;br&gt;from atexit import register&lt;br&gt;register(stop_server)&lt;br&gt;&lt;/pre&gt;

&lt;br&gt;&lt;h3&gt;API d'envoi de mail&lt;/h3&gt;&lt;br&gt;Enfin, les applications peuvent se servir du module &lt;i&gt;sender&lt;/i&gt; pour envoyer des mails. Ce dernier injecte dans la table &lt;i&gt;mail_data&lt;/i&gt; le mail et rend la main immédiatement&lt;br&gt;
&lt;pre&gt;def send_mail(sender, recipients, subject, msg):&lt;br&gt;    """sends the mail by storing it into the DB"""&lt;br&gt;    inserter = mail_data.insert()&lt;br&gt;    res = inserter.execute(subject=subject, sender=sender,&lt;br&gt;                          recipients=','.join(recipients),&lt;br&gt;                          data=b64encode(msg), date=datetime.now())&lt;br&gt;&lt;br&gt;    return res.last_inserted_ids()[0]&lt;br&gt;&lt;/pre&gt;
&lt;br&gt;J'utilise cette API dans mes applications pour tous les envois de mail. Dans Django, elle remplace avantageusement &lt;i&gt;django.core.mail&lt;/i&gt;.&lt;br&gt;&lt;br&gt;&lt;h3&gt;Exemple complet &lt;/h3&gt;&lt;br&gt;Voici la docstring du paquet que j'ai conçu&lt;br&gt;
&lt;pre&gt;mailer&lt;br&gt;=====&lt;br&gt;&lt;br&gt;Mailer provides:&lt;br&gt;&lt;br&gt;- a simple method to send mails (eg: store them)&lt;br&gt;- a worker that actually sends them&lt;br&gt;&lt;br&gt;Let's work on a sql data file for the tests:&lt;br&gt;&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; import settings&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; settings.DATABASE = test_db&lt;br&gt;&lt;br&gt;send mails&lt;br&gt;----------&lt;br&gt;&lt;br&gt;To send a mail, the package provides the `sender` module::&lt;br&gt;&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; from sender import send_mail&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; mail_id = send_mail(sender='tarek@ziade.org',&lt;br&gt;    ...                     recipients=['ziade.tarek@gmail.com'],&lt;br&gt;    ...                     subject='hello',&lt;br&gt;    ...                     msg='héllo')&lt;br&gt;&lt;br&gt;&lt;br&gt;The mail is then stored in the database, and the id returned is the&lt;br&gt;mail id in the DB.&lt;br&gt;&lt;br&gt;Another API will give the status of the mail in process::&lt;br&gt;&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; from sender import mail_status&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; mail_status(mail_id)&lt;br&gt;    u'processing'&lt;br&gt;&lt;br&gt;When the id is not given, the whole mailed table is returned::&lt;br&gt;&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; mail_status()&lt;br&gt;    []&lt;br&gt;&lt;br&gt;We can ask for the queue size as well::&lt;br&gt;&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; from sender import mail_queue_size&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; mail_queue_size()&lt;br&gt;    1&lt;br&gt;&lt;br&gt;sending mails, for real&lt;br&gt;-----------------------&lt;br&gt;&lt;br&gt;A worker is in charge of sending mails::&lt;br&gt;&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; from mailer import start_server, stop_server&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; start_server()&lt;br&gt;&lt;br&gt;The mail is then processed::&lt;br&gt;&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; import time&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; while mail_status(mail_id) == u'processing':&lt;br&gt;    ...     time.sleep(0.2)&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; mail_status(mail_id)&lt;br&gt;    u'processed'&lt;br&gt;&lt;br&gt;Let's stop the server::&lt;br&gt;&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; stop_server()&lt;br&gt;&lt;br&gt;And see the status::&lt;br&gt;&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; status = mail_status()&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; status[0]['subject']&lt;br&gt;    u'hello'&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; status[0]['status']&lt;br&gt;    u'processed'&lt;br&gt;&lt;br&gt;&lt;/pre&gt;
&lt;br&gt;Et, Ô joie, le code est disponible, comme d'habitude, sur &lt;a href="http://hg.programmation-python.org"&gt;http://hg.programmation-python.org&lt;/a&gt;, dans le paquet &lt;i&gt;mailer&lt;/i&gt;.&lt;br&gt;&lt;br&gt;

&lt;br/&gt;
&lt;div&gt;
&lt;i&gt;&lt;small&gt;
 &lt;a target="_blank" title="envoyer par email" alt="envoyer par email" href="http://www.feedburner.com/fb/a/emailFlare?itemTitle=Service de mailing asynchrone pour Django, Plone, etc..&amp;amp;uri=http://programmation-python.org/sections/blog/2007_07_05_service-mailing""&gt;envoyer par mail&lt;/a&gt; |
 &lt;a target="_blank" title="poster sur Scoopeo" alt="poster sur Scoopeo" href="http://scoopeo.com/scoop/new?newurl=http://programmation-python.org/sections/blog/2007_07_05_service-mailing&amp;amp;title=Service de mailing asynchrone pour Django, Plone, etc.."&gt;poster sur Scoopeo&lt;/a&gt;
 &lt;a target="_blank" title="poster sur del.iciou.us" alt="poster sur del.iciou.us" href="http://del.icio.us/post?url=http://programmation-python.org/sections/blog/2007_07_05_service-mailing&amp;amp;description=Service de mailing asynchrone pour Django, Plone, etc.."&gt;poster sur del.iciou.us&lt;/a&gt;
&lt;/small&gt;&lt;/i&gt;
&lt;/div&gt;
</description>
    <link>http://programmation-python.org/sections/blog/2007_07_05_service-mailing</link>
    <dc:date>2007-07-05</dc:date>
    <dc:creator>tarek</dc:creator>
    <dc:contributor>Tarek Ziadé</dc:contributor>
    <dc:language>fr</dc:language>
    <dc:subject>coding</dc:subject>
    <dc:subject>django</dc:subject>
    <dc:subject>zope</dc:subject>

  </item>
  <item rdf:about="http://programmation-python.org/sections/blog/2007_06_22_mon-voisin">
    <title>Qui est mon voisin ?</title>
    <description>Dans un site de contenu, pour rechercher les similitudes entre deux documents basée sur les tags qui leur ont été associés, on recherche l'intersection commune. En d'autres termes, on recherche dans le corpus des documents les documents avec le plus grand nombre de tags communs.&lt;br&gt;&lt;br&gt;Les algorithmes de voisinage, qui sont les plus simples à mettre en oeuvre, permettent de trouver rapidement ces similitudes en disposant dans un espace multidimensionnel les documents.  Chaque dimension est un tag et le document se trouve dans cette dimension&lt;br&gt;à la coordonée 0 ou 1 (le document possède ce tag ou non).&lt;br&gt;&lt;br&gt;Une fois cette carte dressée, il est possible de retrouver les "voisins" d'un document, c'est-à-dire les documents les plus proche dans l'espace.&lt;br&gt;&lt;br&gt;Cet algorithme s'appel le &lt;b&gt;k-Nearest Neighbor&lt;/b&gt;, ou &lt;b&gt;k-NN&lt;/b&gt;.&lt;br&gt;&lt;br&gt;&lt;a href="http://www.amazon.fr/dp/0137903952?tag=programmation-21&amp;amp;camp=1414&amp;amp;creative=6410&amp;amp;linkCode=as1&amp;amp;creativeASIN=0137903952&amp;amp;adid=10YGA37DAGT1GYY579DY&amp;amp;"&gt;&lt;img  align="left" src="http://ec1.images-amazon.com/images/I/5194WJ11V1L._AA240_.jpg"&gt;&lt;/a&gt;Le livre de référence en matière de IA ("&lt;a href="http://www.amazon.fr/dp/0137903952?tag=programmation-21&amp;amp;camp=1414&amp;amp;creative=6410&amp;amp;linkCode=as1&amp;amp;creativeASIN=0137903952&amp;amp;adid=10YGA37DAGT1GYY579DY&amp;amp;"&gt;Artificial Intelligence: A Modern Approach&lt;/a&gt;"), propose une implémentation de cet algorthime en Python, disponible sur son &lt;a href="http://aima.eecs.berkeley.edu/code.html"&gt;site&lt;/a&gt;. &lt;br&gt;&lt;br&gt;&lt;h3&gt;Qui sont mes copains ?&lt;/h3&gt;&lt;br&gt;Les cas d'utilisations ne manquent pas pour le k-NN. Il peut par exemple être employé pour rechercher des similitudes entres utilisateurs de la même application. C'est le cas par exemple sur &lt;a href="http://www.last.fm/"&gt;Last.Fm&lt;/a&gt;, qui propose une fonctionnalité de "Voisinage" où la liste des utilisateurs les plus proches de vos choix en matière de Tags, est affichée. Cette liste de personne est susceptible d'avoir des goûts très similaires aux vôtres.&lt;br&gt;&lt;br&gt;&lt;h3&gt;Le paquet neighbors&lt;/h3&gt;&lt;br&gt;Pour une de mes applications, j'ai développé un paquet au dessus du code du livre, qui propose une api simplifié qui permet de retrouver les voisins d'un utilisateur, en fonction des tags utilisés. &lt;br&gt;&lt;br&gt;Il corrige aussi des erreurs (signalées) dans l'implémentation proposée par le livre et fourni un système de persistence en base, qui permet de découpler le travail de calcul des requêtes: une application peut requêter la base pour connaître les voisins d'un utilisateur, pendant qu'un processus se charge de les calculer et les mettre à jour régulièrement.&lt;br&gt;&lt;br&gt;Voici le docstring du paquet:

&lt;pre&gt;=======&lt;br&gt;neartag&lt;br&gt;=======&lt;br&gt;&lt;br&gt;This module implements the k-nearest neighbor algorithme (k-NN) that allows&lt;br&gt;to compute the distance between elements, given a set of value. Each value&lt;br&gt;is a dimension and the set are the coordinates of the element in the multi&lt;br&gt;dimensional space.&lt;br&gt;&lt;br&gt;For tags, the idea is to find neighbours of a given user, depending on the&lt;br&gt;tags she uses. The `NearestByTag` class is instanciated with those tags::&lt;br&gt;&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; from neartag import NearestByTag&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; tags = ["django", "python", "zen", "fun", "scary"]&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; solver = NearestByTag(tags)&lt;br&gt;&lt;br&gt;Then each user is added with her name and tag values (boolean value)::&lt;br&gt;&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; user_1 = 'user 1', ["django", "python"]&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; user_2 = 'user 2', ["zen", "fun", "scary"]&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; user_3 = 'user 3', ["django"]&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; user_4 = 'user 4', ["django", "python"]&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; for user, tags in (user_1, user_2, user_3, user_4):&lt;br&gt;    ...     solver.add_user(user, tags)&lt;br&gt;&lt;br&gt;The class then will give a sorted list of neighbours of a given user::&lt;br&gt;&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; solver.neighbours('user 1')&lt;br&gt;    [(0.16..., 'user 4'), (0.3..., 'user 3'), (1.0, 'user 2')]&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; solver.neighbours('user 2')&lt;br&gt;    [(0.83..., 'user 3'), (1.0, 'user 1'), (1.0, 'user 4')]&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; solver.neighbours('user 3')&lt;br&gt;    [(0.33..., 'user 1'), (0.33..., 'user 4'), (0.83..., 'user 2')]&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; solver.neighbours('user 4')&lt;br&gt;    [(0.16..., 'user 1'), (0.33..., 'user 3'), (1.0, 'user 2')]&lt;br&gt;&lt;br&gt;The smallest the returned value is, the closest the user is.&lt;br&gt;&lt;br&gt;`neighbours` will return at most 10 neighbours, but this size can be changed::&lt;br&gt;&lt;br&gt;    &amp;gt;&amp;gt;&amp;gt; solver.neighbours('user 1', 1)&lt;br&gt;    [(0.16..., 'user 4')]&lt;br&gt;&lt;br&gt;This class works in-memory, since the loaded values are small enough to fit.&lt;br&gt;&lt;br&gt;How to use it with an application&lt;br&gt;=================================&lt;br&gt;&lt;br&gt;Tags changes all the time in an application. The best use is to instanciate&lt;br&gt;the class over data retrieved from a database and to compute the distances,&lt;br&gt;then to save them within a dedicated table. Since the computation can take&lt;br&gt;time, a thread worker can update those distances from time to time in the&lt;br&gt;background.&lt;br&gt;&lt;/pre&gt;

Le paquet neighbors est disponible sur mon repository Mercurial:&lt;a href="http://hg.programmation-python.org/repositories/public/"&gt; http://hg.programmation-python.org/repositories/public/&lt;/a&gt; (il faut vraiment que je fasse une autre interface web que celle par défaut de Mercurial...)&lt;br&gt;&lt;br&gt;Merci à &lt;a href="http://www.dailymotion.com/video/x27vnx_dr-gumby-ia-avec-scientific-python"&gt;Olivier&lt;/a&gt; pour ses précieux conseils en IA !&lt;br&gt;&lt;br&gt;&lt;br&gt;

&lt;br/&gt;
&lt;div&gt;
&lt;i&gt;&lt;small&gt;
 &lt;a target="_blank" title="envoyer par email" alt="envoyer par email" href="http://www.feedburner.com/fb/a/emailFlare?itemTitle=Qui est mon voisin ?&amp;amp;uri=http://programmation-python.org/sections/blog/2007_06_22_mon-voisin""&gt;envoyer par mail&lt;/a&gt; |
 &lt;a target="_blank" title="poster sur Scoopeo" alt="poster sur Scoopeo" href="http://scoopeo.com/scoop/new?newurl=http://programmation-python.org/sections/blog/2007_06_22_mon-voisin&amp;amp;title=Qui est mon voisin ?"&gt;poster sur Scoopeo&lt;/a&gt;
 &lt;a target="_blank" title="poster sur del.iciou.us" alt="poster sur del.iciou.us" href="http://del.icio.us/post?url=http://programmation-python.org/sections/blog/2007_06_22_mon-voisin&amp;amp;description=Qui est mon voisin ?"&gt;poster sur del.iciou.us&lt;/a&gt;
&lt;/small&gt;&lt;/i&gt;
&lt;/div&gt;
</description>
    <link>http://programmation-python.org/sections/blog/2007_06_22_mon-voisin</link>
    <dc:date>2007-06-22</dc:date>
    <dc:creator>tarek</dc:creator>
    <dc:contributor>Tarek Ziadé</dc:contributor>
    <dc:language>fr</dc:language>
    <dc:subject>coding</dc:subject>

  </item>


  <xhtml:script id="js" type="text/javascript" src="http://programmation-python.org/rss.js" />

</rdf:RDF>
