Sam & Max » foxmask http://sametmax.com Du code, du cul Sat, 07 Nov 2015 10:56:13 +0000 en-US hourly 1 http://wordpress.org/?v=4.1 Prendre le contrôle d’internet ? C’est possible ! Dégainez & Tirez avec Trigger Happy 4 http://sametmax.com/prendre-le-controle-dinternet-cest-possible-degainez-tirez-avec-trigger-happy/ http://sametmax.com/prendre-le-controle-dinternet-cest-possible-degainez-tirez-avec-trigger-happy/#comments Sun, 28 Dec 2014 06:45:36 +0000 http://sametmax.com/?p=12972 Ceci est un post invité de foxmask posté sous licence creative common 3.0 unported.

“C’est l’histoire d’un mec qu’est su’l’pont de l’Alma et regarde dans” … le python, et comme il débute, se demande mais putain de bordel, des projets à la con à pondre pour se lancer à l’assaut d’un langage, c’est toujours les mêmes trucs chiants que plus personne n’a envie de voir tels : forum, blog, wiki, cms. Alors comment être novateur un poil plus que ces projets sans (plus aucun) défit technique ?

A cette question je me suis dit, pourquoi ne pas produire “simplement” (toute proportion gardée) un équivalent libre au célébrissime IFTTT ?

Mais qu’est-ce ?

IFTTT est un service qui vous permet de brancher entre eux, les services internet où vous possédez un compte, comme Twitter, Facebook pour ne citer qu’eux (parce que la liste est longue comme un python au moins;) Et donc quand un évènement défini se produit sur votre compte twitter, genre un tweet de votre poto tombe, le service réagit au quart de tour pour rebalancer les données ailleurs, sur Facebook, un blog et n’importe quoi qui vous chante.

Hé bien cet équivalent libre est Trigger Happy, et ce “principe” décrit ci-dessus défini un ESB (Entreprise Service Bus, très connu du monde Java), un BUS qui récupère des données de droite et vous les expédie à gauche.

Wikipedia le défini ainsi :

L’enterprise service bus (ESB) est une technique informatique intergicielle. Son but est avant tout de permettre la communication des applications qui n’ont pas été conçues pour fonctionner ensemble

Pourquoi un tel projet ?

3 aspects :

  • Avec ce projet je me suis lancé le défit d’arriver à cerner au mieux Django et abordé au mieux Python.
  • Comme tout ce que j’entreprends, se produit par pur réaction allergique à un truc qui m’a gonflé, explications les zamis :
    Au début on fait (plus ou moins) comme tout le monde, sa veille techno à partir de flux RSS de sites web choisis, avec un lecteur de flux RSS moins bien choisi comme iGoogle à une certaine époque ou encore … Google Reader.
    Là le truc qui m’a pris le chou, ce fut d’avoir dans Evernote, le résultats des flux RSS de mes sites favoris complètement atrophiés.
    Du genre “il a été à l’école” devenait “il a t l’cole”. Or le problème ne vient pas d’Evernote qui affiche parfaitement nos chers caractères latins, mais de IFTTT qui les bouffait au passage. Outre IFTTT il existe des versions payantes de services mais qui sont vite très vite limitées dans le nombre de triggers déclenchés que sont Zapier et CloudWork.
  • Le dernier aspect concerne sa chère vie privé.
    Oui en effet, pour que IFTTT puisse récupérer des donnés d’un service à l’autre, il faut que vous ayez un compte sur chaque service comme Twitter et Facebook. Pourquoi IFTTT en a besoin ? Pour que, “en votre nom”, avec les accréditations que vous leur octroyez, puisse lire/écrire les informations de part et d’autre.
    Mais pourquoi faire confiance à IFTTT / Cloudwork / Zapier ? Pourquoi leur offrir NOS accréditations les yeux fermés ?
    Trigger Happy repond à la question puisque l’application vous appartient, les accréditations obtenues de Twitter, Facebook etc, sont stockées dans VOTRE application Trigger Happy. Et personne n’ira les exploiter pour voir ce que vous faites sur vos comptes.

Comment fonctionne le projet ?

Dans la version simplifiée ceci donne :

Trigger Happy wokring process

Image tirée de ma main “gauche” gauche, enfin la gauche pas adroite


De part et d’autres (dans les nuages) on a les services qui nous intéressent
Les éclairs oranges sont les connecteurs qui permettent de dialoguer avec les services
Au milieu .. (non ne coule pas une rivière) le moteur Trigger Happy qui gère, via les connecteurs, l’échange des données.

Dans la version complète ceci donne :

Trigger Happy Micro ESB

Trigger Happy Micro ESB

On a au milieu un “tube” (pipeline) qui va permettre, via des “command” & settings & url & service provider, d’identifier les services “django th 1, 2, 3, 4″.
A un moment donné, à l’entrée du tube, arrive un “flux” de donnés identifié pour admettons “django th 1″ aka un flux RSS (au pif) puis on identifie une destination, admettons “django th 2″ aka “twitter”, et les données collectées repartent donc du tube vers twitter, comme le service s’attend à les recevoir.

Dans la vraie vie comment ça se passe ?

Ça se passe bien mon zami : je m’en va (la fote est volontaire tout comme l’reste;) vous montrer la création d’un trigger, permettant d’extraire les billets du flux de mon blog et de les renvoyer sur Twitter en 5 étapes :

Ici en premier lieu vous pouvez voir la liste des services que Trigger Happy gere pour l’utilisateur courant (mézigues)

Trigger Happy : services activés

Trigger Happy : services activés

Puis l’accueil de l’appli où on remarquera que je suis radin en nombre de trigger affichés par page parce que … je me sers de l’appli via un browser sur mon smartphone m’sieur ‘dames :

Trigger Happy : Accueil

Trigger Happy : Accueil

Etape 1:

Trigger Happy : Etape 1 de la création d'un trigger

Choix du service fournissant les données

Etape 2:

Trigger Happy : Etape 2 de la création d'un trigger

nommage du service et fourniture de l’origine des données

Etape 3:

Trigger Happy : Etape 3 de la création d'un trigger

Choix du service accueillant les données

Etape 4:

Trigger Happy : Etape 4 de la création d'un trigger

Trigger Happy : Etape 4 de la création d’un trigger

Ensuite le moment venu, se déclenche ce trigger, et pour en voir le résultat, on peut consulter le billet que j’avais préparé le mois dernier pour une présentation Django Paris. Et qui au moment de la publication du billet, à 19h15 pétantes, est tombé sur twitter directement et Evernote dans la foulée.

Voilà !

Le défit est parti et n’attend plus qu’à ce que le nombre de services croissent. Pour cela rien de plus simple, j’ai fait une doc expliquant comment pondre un module django qui exploite le service de votre choix tel Buffer, Trello, Dropbox et j’en passe et des meilleurs. Tout ce dont on a besoin : l’API du service visé en python, créer un compte pour avoir accès au service et suivre le howto sur readthedoc

Last but not least aux dev : ca tourne avec django 1.7 / Python 2.7 et 3.4

Dernier détail: comme je suis sûr que vous vous demandez pourquoi ce nom de projet ? C’est un perso de la franchise Skylander auquel joue mon fils et comme le projet “trigger” à tirelarigot sur l’net, ca collait pile poil :)

]]>
http://sametmax.com/prendre-le-controle-dinternet-cest-possible-degainez-tirez-avec-trigger-happy/feed/ 4
Python a le don d’Ubiquité : Multiprocessing 7 http://sametmax.com/python-ubiuite-multiprocessing/ http://sametmax.com/python-ubiuite-multiprocessing/#comments Sun, 02 Feb 2014 16:41:23 +0000 http://sametmax.com/?p=8939

Ceci est un post invité de Foxmask posté sous licence creative common 3.0 unported.

Tout récemment j’ai voulu donner un coup de fouet à mon script de traitement de Trigger Happy (que je fais tourner sur ma “raspberry pi” parce que chuis un w4rl0rdZ:P) que j’estimais être trop long dans ses traitements de données.

Actuellement avec Trigger Happy, j’ai 30 sources de données (essentiellement des flux rss), que je parcours, et quand un nouvel item arrive, je l’envoi à pétaouchnock (Evernote ;) Le tout prend 7min, soit 14secondes par source. La loose totale.

Voici le corps du délit :

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import os
import datetime
import time
 
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_th.settings")
from django_th.services import default_provider
from django_th.models import TriggerService
from django.utils.log import getLogger
 
# create logger
logger = getLogger('django_th.trigger_happy')
 
def go():
    """
        run the main process
    """
    trigger = TriggerService.objects.filter(status=True)
    if trigger:
        for service in trigger:
[...]
    else:
        print "No trigger set by any user"
 
 
def main():
    default_provider.load_services()
    # let's go
    go()
 
if __name__ == "__main__":
 
    main()

Mais avant que je ne me penche sur le code du script pour l’améliorer, je me suis dit que plutôt que de chercher à corriger un problème, autant chercher la source de celui-ci d’abord (normal hein).

Un HTOP m’a révélé :

  1. que le CPU était à 100% tout le temps, que le script tourne ou pas
  2. quye la raison était double : rabittmq et celery…

Une fois shootés ces derniers, tout va pour le mieux :P
Je ne dis pas que ceux ci sont de la merde, mais que, pour mon cas, la crontab se suffit à elle-même.

Donc une fois désinstallés c’est 2 (sur)consommateurs de ressources, je relance le script pour tomber à un temps de traitement à 5mn

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 >= 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

Comme je suis un éternel insatisfait de bibi, j’ai cherché des moyens un peu partout, jusqu’à ce que Sam me souffle une suggestion ;)

A présent donc une version modifiée pour exploiter le multiprocessing est la suivante :

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import os
import datetime
import time
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "th.settings")
 
from django_th.services import default_provider
from django_th.models import TriggerService
from django.utils.log import getLogger
 
# create logger
logger = getLogger('django_th.trigger_happy')
 
def go(service):
    """
        run the main process
    """
    [...]
 
 
def main():
    default_provider.load_services()
    # let's go
    trigger = TriggerService.objects.filter(status=True)
    if trigger:
        from multiprocessing import Pool
        pool = Pool(processes=5)
        result = pool.map(go, trigger)
    else:
        print "No trigger set by any user"
 
if __name__ == "__main__":
 
    main()

fait tomber le temps de traitement à … 1min …:

$ date && ./fire.sh && 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)

Comme on l’aura remarqué la différence entre les 2 versions est l’appel fait à a fonction go

avant :

def main():
    default_provider.load_services()
    # let's go
    go()

après :

def main():
    default_provider.load_services()
    # let's go
    trigger = TriggerService.objects.filter(status=True)
    if trigger:
        from multiprocessing import Pool
        pool = Pool(processes=5)
        result = pool.map(go, trigger)
    else:
        print "No trigger set by any user"

du coup l’appel de la fonction “go” implique de changer sa signature en lui filant comme argument “trigger” (le QuerySet de l’appli Django)

A présent donc pool.map fait l’itération des données trouvées dans le modele TriggerService et exécute tout le tintouin. *<:o)

ps : @Sam : chose promise chose dûe ;)

edit: apres de moult nouveaux essais sur le sujet, seul SQLite supporte cette façon de faire. MySQL, PostgreSQL non. La faute au multiprocessing, qui m’a-t-on confirmé de ci de là ne convient pas du tout pour gérer des connexions aux bases.

]]>
http://sametmax.com/python-ubiuite-multiprocessing/feed/ 7