Journal pyAggr3g470r

21
21
avr.
2014

Présentation

pyAggr3g470r est un agrégateur de nouvelles très simple écrit en Python et est sous licence AGPL v3.0.

Il utilise le micro-framework Flask, et Bootstrap comme framework front-end. SQLAlchemy est utilisé pour la gestion de la base de données et Gevent pour le téléchargement des flux.

Il est possible de le déployer assez facilement sur votre serveur ou en mode PaaS (Platform as a Service) sur Heroku. Plusieurs utilisateurs peuvent profiter d'une même instance (avec des comptes utilisateurs et administrateurs).

Il est capable de résoudre les URLs des articles (pratique avec les flux qui fournissent des adresses du type feedproxy.google.com) et peut être configuré pour passer par un proxy HTTP (par exemple Privoxy/Tor pour les paranoïaques) lorsqu'il n'est pas déployé sur Heroku.

Il est également possible d'effectuer des recherches grâce au projet Whoosh. Cette fonctionnalité est désactivé sur Heroku. Ce problème sera contourné dans une version futur.

Prochaines étapes

Les principales prochaines étapes sont l'internationalisation, la recherche full-text pour Heroku et le faire à nouveau fonctionner avec Python 3 (oui, je travail à l'envers).

Un peu d'historique

Le projet date en fait déjà de 2010 et à l'époque utilisait CherryPy avec une base SQLite. L'interface était moins soignée (et je sais qu'elle est encore largement perfectible). J'ai donc eu l'occasion de tester pas mal de choses, même des algorithmes de classification.
J'ai par la suite abandonné SQLite pour MongoDB (avec PyMongo puis MongoEngine, pour tester…). Maintenant j'utilise une base PostgreSQL.
La base contient environ 80.000 articles (voici un export assez récent) et les performances sont plutôt bonnes. J'ai utilisé cette base pour comparer ma solution utilisant Whoosh à ElasticSearch. À ma surprise Whoosh était plus rapide pour rechercher des articles (mais bien plus lent pour indexer la base de données). Ceci dit, même si ElasticSearch avait été plus rapide je serai resté avec Whoosh car je préfère une solution plus Pythonesque et préfère éviter d'obliger l'utilisateur d'installer un serveur Java uniquement pour effectuer des recherches.

Le projet est bien entendu ouvert aux contributions (il dispose aussi d'un dépôt sur GitHub).
J'espère que ce billet d'autopromotion aura été un minimum intéressant.

  • # :)

    Posté par . Évalué à 2.

    Le screenshot ! Le screenshot ! Le screenshot !

  • # Flask ?

    Posté par . Évalué à 3.

    Qu'est-ce qui t'a motivé pour passer à Flask ?

    J'ai l'impression que le passage vers python 3 n'est pas pour demain.

    • [^] # Re: Flask ?

      Posté par (page perso) . Évalué à 1.

      C'est en partie à cause de Flask que j'ai du abandonner Python 3, en effet.
      Mais je crois que Flask a avancé depuis. Le problème c'est aussi les extensions de Flask (que j'adore).
      Faudrait que je fasse un état des modules dont j'ai besoin. Si ça se trouve, je pourrais déjà à nouveau utiliser Python 3.

      J'aimais bien CherryPy mais là il faut dire que je suis assez fan de Flask. Je trouve la documentation très bien faite, j'aime bien les extensions même si certaines semblent ne pas servir à grand chose. Au passage à Flask j'ai aussi laissé tombé Mako pour Jinja. J'aime bien aussi.

      En fait, je n'ai pas trop envie de critiquer les projets que j'ai cessé d'utiliser car je n'ai pas d'arguments assez forts. Si maintenant je préfère Flask et Jinja, c'est je pense surtout parce que je code beaucoup plus avec (pas que pour des projets perso).
      Par exemple j'aime bien ce qu'il est possible de faire avec les filtres de Jinja. Mais si ça se trouve, il y a pareil avec Mako… Faut bien faire un choix…
      Et il est vrai que Flask est assez hype en ce moment. Il y a qu'à voir la documentation sur Heroku…

      • [^] # Re: Flask ?

        Posté par . Évalué à 2.

        Si l'on s'en tient à cette page:
        http://flask.pocoo.org/docs/advanced_foreword/#the-status-of-python-3
        et surtout celle-ci:
        http://flask.pocoo.org/docs/python3/#python3-support

        On a plutôt l'impression que ce n'est pas une priorité pour eux et qu'il laisse les "autres" essuyer les plâtres.
        Bon nombre de frameworks ont pourtant sauté le pas.

        Pour moi, investir dans un framework en sachant que je devrai reprendre mon code (même avec toutes les précautions nécessaires) et en n'ayant aucune certitude qu'il suivra le mouvement est assez rédhibitoire.
        Django malgré toute sa complexité et son aspect monolithique gère au moins ce passage puisqu'il ne fait pas appel à moultes dépendances.
        Pyramid s'en sort très bien avec une philosophie encore plus modulaire.

      • [^] # Re: Flask ?

        Posté par . Évalué à 1.

        As-tu évalué Pyramid ? (Y a une dépêche en cours de rédaction pour ceux qui voudraient donner un coup de pouce…)

  • # Démo

    Posté par . Évalué à 2.

    Y'a t'il un compte invité sur le site de la démo ?
    Merci

    • [^] # Re: Démo

      Posté par (page perso) . Évalué à 1.

      J'y ai pensé, le problème est que j'ai un compte gratuit sur Heroku. Donc un espace très limité. Actuellement nous sommes deux utilisateurs.
      Bon, je pourrai créer une instance spécial démo, c'est vrai…

      Tu peux aussi tester rapidement avec un compte Heroku gratuit et suivre ces instructions. C'est très simple.

      • [^] # Re: Démo

        Posté par . Évalué à 3.

        Je te remercie.

        Même si j'utilise un boîte mail poubelle, je trouve assez fastidieux l'inscription a tous les sites de démo ou gratuit à l'heure dOAuth2 et d'OpenID Connect.

        Si tu avais la bonté de créer un compte démo, je pense que tu aurais peut-être quelques retours (de moi en tout cas)
        Les aggrégateurs RSS online en python m'intéressent particulièrement en ce moment.

        • [^] # Re: Démo

          Posté par (page perso) . Évalué à 0.

          OK, allons-y de toute façon tout est temporaire…
          As-tu un moyen de contact privé (mail, xmpp, bitmessage, etc.)?

          • [^] # Re: Démo

            Posté par . Évalué à 2.

            C'était mieux à vent quand il y avait les MPs sous DLFP.

            krazybug chez "don't be evil" point com
            Merci

  • # Retour d'experience

    Posté par . Évalué à 3.

    J'ai par la suite abandonné SQLite pour MongoDB (avec PyMongo puis MongoEngine, pour tester…). Maintenant j'utilise une base PostgreSQL.

    Tiens qu'estce qui t'a fait passer de MongoDB à Psotgres ? Les bases orientés documents me semblent bien adaptés à cette problématique mais j'ai pas vraiment d'expérience dans le domaine.

    Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

    • [^] # Re: Retour d'experience

      Posté par (page perso) . Évalué à 1.

      En effet, ma version avec MongoDB (simplement avec pymongo), que j'utilise toujours localement d'ailleurs, est vraiment performante et il ma fallut un peu de temps avant de retrouver ces performances lorsque je suis passé à MongoEngine puis à SQLAlchemy (PostgreSQL).
      J'ai surtout perdu en performance au passage de pymongo à MongoEngine (sur une base de test d'environ 80.000 articles). Peut-être que je l'utilisais mal…
      Globalement, j'ai utilisé MongoDB de 2010 à 2013.

      J'ai décidé de tester PostgreSQL en partie car:
      - on en lit beaucoup de bien sur Internet;
      - l'extension sur Heroku est gratuite;
      - il fallait que je résolve ma perte de performance du au passage à MongoEngine. Et en effet maintenant je n'ai plus de problèmes de performances, y compris avec la gestion de plusieurs utilisateurs (ce qui était le problème principal).

      Mais je n'ai rien contre MongoDB. Et je l'utilise assez dans d'autres projets…

  • # Le nom....

    Posté par (page perso) . Évalué à 7.

    Pourquoi pyAggr3g470r ? Quitte à faire du leet, autant aller juste qu'au bout : pyA99r3970r.

    Plus sérieusement, je trouve le nom illisible. Mais ce n'est qu'un avis personnel et concernant le nom uniquement et non le travail sous-jacent ;)

    • [^] # Re: Le nom....

      Posté par (page perso) . Évalué à 0.

      Je suis d'accord. On ma déjà fait remarquer que le nom n'était pas génial. Je me suis habitué depuis le temps. À l'époque je voulais simplement pyAggregator, mais le nom est utilisé.
      Et c'était un projet vraiment pour mes besoins, d'où une interface aussi assez critiquée ;-)

    • [^] # Re: Le nom....

      Posté par (page perso) . Évalué à 1.

      s/pyA99r3970r/py4992394702/ je me disais bien qu'il manquait une lettre et je ne voyais pas pourquoi il restait un A (converti pour l'autre et un r :D)

  • # Rapide retour

    Posté par (page perso) . Évalué à 3.

    Un rapide retour car je n'ai pas été très loin.

    Installation sur un petit netbook sous debian Wheezy avec dans l'idée de tester avec SQLite (SQLAlchemy est fait pour ça après tout).

    Suppression de psycopg2 dans requirements.txt et ajout de whoosh qui est manquant.

    Un p'tit coup de apt-get pour pouvoir compiler lxml qui est une dépendance de feedparser et opml semble-t-il.

    $ sudo apt-get install libxml2-dev libxslt1-dev

    Configuration de la base

    [database]
    uri = sqlite+pysqlite:///pyaggr.db

    Pas d'erreur lors du db_create.py.

    Le serveur se lance sans erreurs, pas contre je n'arrive pas à me logger avec admin/root …

    La suite au prochain épisode et merci pour ce projet qui semble intéressant.

    Benoît

    • [^] # Re: Rapide retour

      Posté par (page perso) . Évalué à 2.

      Merci pour le retour. Je n'ai jamais testé avec SQLite depuis que j'utilise SQLAlchemy.

      Le login par défaut est root@pyAggr3g470r.localhost et le mot de passe root (voir le README).

      Si tu as une adresse email, je peux te créer un compte de test sur mon instance Heroku.

      En effet, le requirements.txt est surtout pour Heroku. Whoosh ne peut pas vraiment y être utilisé.
      Par contre sur Heroku sans psycopg2, ça plante…
      En tout cas merci, je vais quand même ajouter Whoosh.

      • [^] # Re: Rapide retour

        Posté par (page perso) . Évalué à 1.

        Salut,

        Le login par défaut est root@pyAggr3g470r.localhost et le mot de passe root (voir le README).

        Arf, j'ai raté ça dans le REAME, on dira que j'étais fatigué, désolé.

        Si tu as une adresse email, je peux te créer un compte de test sur mon instance Heroku.

        Merci mais j'aime autant tester en local.

        En effet, le requirements.txt est surtout pour Heroku. Whoosh ne peut pas vraiment y être utilisé.
        Par contre sur Heroku sans psycopg2, ça plante…
        En tout cas merci, je vais quand même ajouter Whoosh.

        En fait les dépendances devraient être surtout dans un setup.py mais je ne sais pas comment on fait pour les dépendances optionnelles. Tu es intéressé par un retour sur ce point ?

        Tu n'a pas activé les "issues" sur bitbucket donc j'ajoute un "bug" ici.

        Juste après le premier "fecth", effectuer une recherche sans avoir cliqué sur le bouton "Index database" provoque une belle Traceback. L'index n'est pas du tout mis à jour automatiquement ?

        Traceback (most recent call last):
          File "/home/blaurent/depots/pyaggr3g470r/lib/python2.7/site-packages/flask/app.py", line 1836, in __call__
            return self.wsgi_app(environ, start_response)
          File "/home/blaurent/depots/pyaggr3g470r/lib/python2.7/site-packages/flask/app.py", line 1820, in wsgi_app
            response = self.make_response(self.handle_exception(e))
          File "/home/blaurent/depots/pyaggr3g470r/lib/python2.7/site-packages/flask/app.py", line 1403, in handle_exception
            reraise(exc_type, exc_value, tb)
          File "/home/blaurent/depots/pyaggr3g470r/lib/python2.7/site-packages/flask/app.py", line 1817, in wsgi_app
            response = self.full_dispatch_request()
          File "/home/blaurent/depots/pyaggr3g470r/lib/python2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
            rv = self.handle_user_exception(e)
          File "/home/blaurent/depots/pyaggr3g470r/lib/python2.7/site-packages/flask/app.py", line 1381, in handle_user_exception
            reraise(exc_type, exc_value, tb)
          File "/home/blaurent/depots/pyaggr3g470r/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
            rv = self.dispatch_request()
          File "/home/blaurent/depots/pyaggr3g470r/lib/python2.7/site-packages/flask/app.py", line 1461, in dispatch_request
            return self.view_functions[rule.endpoint](**req.view_args)
          File "/home/blaurent/depots/pyaggr3g470r/lib/python2.7/site-packages/flask_login.py", line 758, in decorated_view
            return func(*args, **kwargs)
          File "/home/blaurent/depots/pyaggr3g470r/pyaggr3g470r/views.py", line 461, in search
            results, nb_articles = fastsearch.search(query)
          File "/home/blaurent/depots/pyaggr3g470r/pyaggr3g470r/search.py", line 107, in search
            raise EmptyIndexError
        EmptyIndexError
        
        • [^] # Re: Rapide retour

          Posté par (page perso) . Évalué à 0.

          L'index n'est pas du tout mis à jour automatiquement ?

          Il l'était (les articles étaient ajouté après le fetch…). Mais plus depuis qu'il est désactivé pour Heroku (je dois encore tester .

          J'ai activé les issues. C'est mieux qu'ici. Merci!
          Je traiterai ce problème un peu plus tard.

          En fait les dépendances devraient être surtout dans un setup.py mais je ne sais pas comment on fait pour les dépendances optionnelles. Tu es intéressé par un retour sur ce point ?

          C'est bon merci. Je vois globalement comment faire. Mais pour l'instant je vais laisser ça comme ça (avec le requirements.txt pour Heroku).

    • [^] # Re: Rapide retour

      Posté par (page perso) . Évalué à 1.

      Je viens de tester, ça semble bien fonctionner avec SQLite. Cool.

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.