IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Communiquer entre process qui ne se connaissent pas


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Billets dans le blog
    1
    Par défaut Communiquer entre process qui ne se connaissent pas
    Bonjour,

    je me tords les neurones sur un script qui doit communiquer avec d'autres instances de lui-même mais qui en ignore l'existence et le nombre.

    Je m'explique :

    Mon script est lancé depuis différents process du système (je n'ai aucun contrôle là dessus, mais en gros, ils sont tous lancés en même temps (dans la même demie seconde)).
    Chaque instance reçoit un paramètre (sur sa ligne de commande).
    Je voudrais :
    1 - trouver un critère qui me permette de distinguer une des instances pour en faire le maître (les autres devenant les esclaves)
    2 - que chaque esclave envoie son paramètre au maître.

    J'ai déjà créé une solution qui marchotte...
    Chaque instance va essayer d'ouvrir un fichier en écriture.
    Quand un script échoue à ouvrir le fichier, il fait un sleep et réessaye plus tard.
    Quand un script arrive à ouvrir le fichier, il regarde sa taille : si elle est nulle, c'est qu'il est le premier => il est le maître.
    Si la taille n'est pas nulle, c'est un esclave : il écrit son paramètre à la fin du fichier, le referme et se termine.
    Pendant ce temps, le maître, scrute la taille du fichier.
    Quand elle reste stable pendant (disons) 300ms, il considère que tous les esclaves ont fini.
    Enfin, il ouvre à nouveau le fichier pour en extraire tous les paramètres.

    J'ai essayé d'autres variantes en utilisant les mmap mais dans tous les cas, ma solution n'est pas satisfaisante.
    Dès que trop d'instances sont en concurrence ou que le CPU ou le disque dur sont un peu débordés, ça échoue :
    --> le maître "rate" certains esclaves et leur paramètre est perdu
    --> il a plusieurs instances qui se croient maître
    En gros, à partir d'une vingtaine d'instance, ça commence à débloquer.
    On est loin des 100 ou 200 que j'aimerais pouvoir lancer.

    Si je viens vous embêter avec ça, c'est parce que je suis sûr de ne pas être le premier à avoir ce genre de besoin.
    Il existe sûrement des solutions propres et de bonnes pratiques en la matière.
    Mais peut-on le faire en python et de manière portable (Linux/Windows) ?

    Merci d'avance.

  2. #2
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Bonjour,

    Je te propose dans un premier temps une solution simple sur la base de xmlrpclib/SimpleXMLRPCServer(xmlrpc.server attention au passage Python 2 / 3) (ou socket mais c'est légèrement plus compliqué).
    Chaque client ayant un thread client et tente de lancer un thread serveur sur une plage de port prédéfinie (localhost).
    Si le port est occupé le client tente de se 'présenter'. C'est bon: Le process sur le port en question est le maitre. C'est pas bon on continu.

    @+

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    103
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 103
    Par défaut
    Utiliser un fichier pour synchroniser les différentes instances peut poser quelques problèmes :
    - comment assurer que 2 instances n'essaient pas en même temps d'écrire dans le même fichier ? la librairie python-lockfile fournit la base pour résoudre ce genre de problème.
    - comment nettoyer le fichier à l'arrêt des instances ? En cas de plantage ? Est-ce un problème dans ton cas ?

    J'aurais tendance à faire communiquer les différences instances via xmpp ou AMQP ... petite contrainte, ça oblige à faire tourner un serveur xmpp ou AMQP mais ça permet :
    - de faire tourner tes instances sur une ou plusieurs machines
    - c'est scalable jusqu'à au moins 100/200 d'instances
    - la seule information à fournir aux instances est l'adresse du serveur.

    Sinon tu peux peut-être utiliser une base sqlite ?

  4. #4
    Membre Expert Avatar de pacificator
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 074
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 074
    Par défaut
    Bonjour,

    tu peux aussi jeter un oeil sur zeromq.

    Bon python

  5. #5
    Membre éclairé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Billets dans le blog
    1
    Par défaut
    comment assurer que 2 instances n'essaient pas en même temps d'écrire dans le même fichier ?
    Je fais confiance à l'OS. En principe 2 process ne peuvent ouvrir le même fichier en écriture en même temps. C'est même sur cette hypothèse que je me base. D'ailleurs, de tous les problèmes que je rencontre, aucun ne vient d'une faille à ce niveau.

    comment nettoyer le fichier à l'arrêt des instances ? En cas de plantage ?
    C'est le process qui est devenu maître qui s'en occupe. Grâce aux exceptions, c'est plantage-proof (enfin, je crois).

    Je te propose dans un premier temps une solution simple sur la base de xmlrpclib/SimpleXMLRPCServer
    Je suis à fond !

  6. #6
    Membre éclairé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Billets dans le blog
    1
    Par défaut
    Ayé !
    Finalement, je suis parti sur un bon vieux serveur TCP et j'ai obtenu un truc qui marche pas mal (il arrive à tenir une centaine d'instance. après je commence à avoir plusieurs maîtres)
    Voici à quoi ça ressemble :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    def try_master ( port,param ):
        import SocketServer
     
        class TCPHandler ( SocketServer.BaseRequestHandler ):
            def handle(self):
                server.res.append( self.request.recv( 2000 ).strip())
        try:
            def timed_out () : server.is_alive = False
            server = SocketServer.TCPServer(('localhost',port),TCPHandler )
            server.res            = [param]
            server.timeout        = 0.5
            server.is_alive       = True
            server.handle_timeout = timed_out
            while server.is_alive :
                server.handle_request()
            return server.res
        except:
            return None
     
    def try_slave ( port,param ):
        import socket
        try:
            sock = socket.socket( socket.AF_INET,socket.SOCK_STREAM )
            sock.connect(('localhost',port))
            sock.sendall( param )
        finally:
            sock.close()        
     
    def merge_params ( param ):
        return try_master( 56789,param ) or try_slave( 56789,param )
     
    files = merge_params( sys.argv[1] )
    if files :
        print files
    On essaye d'abord de créer le serveur :
    si on n'y arrive pas : on devient esclave, on envoie son paramètre et on sort.
    si on y arrive : on est le maître en écoute des paramètres des esclaves.
    Si le maître reste 0.5s sans rien recevoir, on considère que tous les esclaves ont fini => on revoie la liste de tous les paramètres reçus.
    Le seul paramètre à régler c'est le 0.5s de timeout.
    Avec 1s ça résiste à plus d'instances, mais si il y en a peu, on attend pour rien.
    Le seul hic : il faut esperer qu'il n'y a personne sur le port 56789
    En tout cas, c'est beaucoup plus élégant et concis que ma solution à base de fichier partagé...

    Merci les gars
    Néanmoins, si vous voyez des trucs à améliorer, n'hésitez pas...

  7. #7
    Membre éclairé
    Avatar de Captain'Flam
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2011
    Messages
    273
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Février 2011
    Messages : 273
    Billets dans le blog
    1
    Par défaut
    Petit oubli : merci pacificator mais j'aime mieux une solution à base de lib standard.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Liaison entre listes qui ne s'affiche pas
    Par crazylia dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 16/04/2010, 11h34
  2. Variables d'entrée sortie qui ne se remplissent pas
    Par brunoperel dans le forum Prolog
    Réponses: 5
    Dernier message: 06/12/2009, 22h14
  3. [VB2005] Process qui ne se termine pas ?
    Par Kropernic dans le forum Windows Forms
    Réponses: 4
    Dernier message: 10/07/2008, 13h16
  4. [VB6]Process qui ne se ferme pas
    Par marsup54 dans le forum VB 6 et antérieur
    Réponses: 6
    Dernier message: 19/04/2006, 13h57
  5. 2 SELECT Qui ne s'entendent pas très bien entre eux :(
    Par moutanakid dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 05/08/2004, 16h46

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo