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 :

Envoi cadencé de trames


Sujet :

Python

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 28
    Points : 25
    Points
    25
    Par défaut Envoi cadencé de trames
    Bonjour à tous,
    je débute en Python et on me demande d'envoyer des trames ethernet à intervalle régulier mais court (de l'ordre du centième de seconde).
    Je cherche la meilleure solution (évidemment!).
    J'ai utilisé un time.sleep(tempo) mais mon problème est que la préparation de la trame (calculs...) avant de faire le sendMsg prend un temps non négligeable vis à vis de la tempo.
    L'idéal serait que cette préparation se fasse en temps masqué pendant l'attente de la tempo.
    Merci pour votre aide
    Begude

  2. #2
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Points : 970
    Points
    970
    Par défaut
    Bonjour,

    je verrais une utilisation du module threading et queue.

    1 thread qui alimente la queue
    1 thread qui prend un message de la queue et qui se met en pause pdt une seconde.

  3. #3
    Membre éprouvé
    Avatar de afranck64
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2009
    Messages
    592
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Cameroun

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2009
    Messages : 592
    Points : 1 006
    Points
    1 006
    Par défaut
    Bonsoir,
    vous avez également la possibilité te chronométré le temps de traitement, préparation du message, et d'en tenir compte dans le "sleep".
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    tempo = 0.1
    t1 = time()
    #traitement...
    t2 = time()
    sleep(tempo-(t2-t1))
    #envoi du message
    Bien entendu, le temps de traitement doit être inférieur au tempo.
    Win 10 64 bits / Linux Mint 18, - AMD A6 Quad: Py27 / Py35
    CONTENU D'UNE QUESTION
    Exemples:
    - Configuration (système d'exploitation, version de Python et des bibliothèques utilisées)
    - Code source du morceau de programme où il y a un bogue
    - Ligne de code sur laquelle le bogue apparaît
    - Erreur complète retournée pas l'interpréteur Python
    - Recherche déjà effectuée (FAQ, Tutoriels, ...)
    - Tests déjà effectués

  4. #4
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Points : 1 384
    Points
    1 384
    Par défaut
    Un exemple qui suit le modèle proposé par kango.
    J'en ai profité pour définir une classe Every, qui fonctionne comme Timer mais répète l'appel tant qu'on n'appelle pas la méthode cancel.

    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
    from threading import _Timer
    from queue import Queue, Empty
     
    class Every(_Timer):
        def run(self):
            self.finished.wait(self.interval)
            while not self.finished.is_set():
                self.function(*self.args, **self.kwargs)
                self.finished.wait(self.interval)
     
    def send(q):
        try:
            frame = q.get_nowait()
            q.task_done()
            print("frame sent:", frame)
        except Empty:
            pass
     
    q = Queue()
    e = Every(0.5, send, (q,))
    e.start()
     
    for i in range(10):
        q.put(i)
     
    q.join()
    e.cancel()
    [EDIT] gestion de l'arrêt de l'envoi dans l'exemple
    Ce code est pour Python 3; en Python 2.x, le module queue s'appelle Queue (avec une majuscule)

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 28
    Points : 25
    Points
    25
    Par défaut
    Merci à tous pour vos réponses,
    je ne dormais pas mais je suis en train de traiter une autre demande...
    Je vais regarder de près le code de dividee.
    Je ne connaissais pas la classe Queue et je débute dans les Thread
    J'ai du pain sur la planche.
    @+
    Begude

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 28
    Points : 25
    Points
    25
    Par défaut
    J'ai fait quelques tests avec le code de dividee dans lequel j'ai mis qq commentaires et un enregistrement de l'heure de "l'envoi".
    Si l'interval est à 0.5, pas de souci :
    2011-08-25 14:31:00.397000 frame sent: 0
    2011-08-25 14:31:00.897000 frame sent: 1
    2011-08-25 14:31:01.397000 frame sent: 2
    2011-08-25 14:31:01.897000 frame sent: 3
    2011-08-25 14:31:02.397000 frame sent: 4
    2011-08-25 14:31:02.897000 frame sent: 5
    2011-08-25 14:31:03.397000 frame sent: 6
    2011-08-25 14:31:03.897000 frame sent: 7
    2011-08-25 14:31:04.397000 frame sent: 8
    2011-08-25 14:31:04.897000 frame sent: 9
    par contre, si je descends à 0.1, l'écart mesuré est plutôt à 0.11
    2011-08-25 14:32:02.553000 frame sent: 0
    2011-08-25 14:32:02.662000 frame sent: 1
    2011-08-25 14:32:02.772000 frame sent: 2
    2011-08-25 14:32:02.881000 frame sent: 3
    2011-08-25 14:32:02.990000 frame sent: 4
    2011-08-25 14:32:03.100000 frame sent: 5
    2011-08-25 14:32:03.209000 frame sent: 6
    2011-08-25 14:32:03.319000 frame sent: 7
    2011-08-25 14:32:03.428000 frame sent: 8
    2011-08-25 14:32:03.537000 frame sent: 9
    Je pensais que l'on pouvait attendre une meilleure précision jusqu'à des intervalles de qq centième au vu de ce qu'il y a d'executé dans "send".
    Qu'en pensez vous ?

    Begude

    PS : Je remets le code utilisé pour les tests :
    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    # -*- coding: utf-8 -*-
    from threading import _Timer
    from Queue import Queue, Empty
    import time
    import datetime
     
    class Every(_Timer):
        def run(self):
            self.finished.wait(self.interval)
            while not self.finished.is_set():
                self.function(*self.args, **self.kwargs)
                self.finished.wait(self.interval)
     
    def send(q, lst):
        try:
            # renvoie un element de la queue et le supprime de la queue
            frame = q.get_nowait() 
     
            lst.append( "%s frame sent: %s" % (datetime.datetime.now(), frame) )
     
            # indique que la tache dans la queue a ete terminee
            q.task_done()
     
        except Empty:
            # si la queue est vide
            pass
     
    # queue FIFO
    q = Queue()
     
    lst = []
    e = Every(0.1, send, (q,lst))
    e.start()
     
    for i in range(10):
        # place i dans la queue
        q.put(i)
     
    # bloque jusqu'a ce que tous les elements de la queue aient ete traites
    q.join()
     
    e.cancel()
     
    for l in lst:
        print l

  7. #7
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Points : 1 384
    Points
    1 384
    Par défaut
    Euh.. Je ne sais pas trop, avec ton code j'obtiens le résultat suivant:
    2011-08-25 19:36:38.585000 frame sent: 0
    2011-08-25 19:36:38.685000 frame sent: 1
    2011-08-25 19:36:38.785000 frame sent: 2
    2011-08-25 19:36:38.885000 frame sent: 3
    2011-08-25 19:36:38.985000 frame sent: 4
    2011-08-25 19:36:39.085000 frame sent: 5
    2011-08-25 19:36:39.185000 frame sent: 6
    2011-08-25 19:36:39.285000 frame sent: 7
    2011-08-25 19:36:39.385000 frame sent: 8
    2011-08-25 19:36:39.485000 frame sent: 9
    Moi ça me semble assez proche de 0,1 sec

    et en passant à 0,01 secondes:
    2011-08-25 19:38:33.875000 frame sent: 0
    2011-08-25 19:38:33.885000 frame sent: 1
    2011-08-25 19:38:33.895000 frame sent: 2
    2011-08-25 19:38:33.905000 frame sent: 3
    2011-08-25 19:38:33.915000 frame sent: 4
    2011-08-25 19:38:33.925000 frame sent: 5
    2011-08-25 19:38:33.935000 frame sent: 6
    2011-08-25 19:38:33.945000 frame sent: 7
    2011-08-25 19:38:33.955000 frame sent: 8
    2011-08-25 19:38:33.965000 frame sent: 9

  8. #8
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Points : 1 384
    Points
    1 384
    Par défaut
    Pour plus de précision dans la mesure du temps, il vaut mieux utiliser time.clock:
    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
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    # -*- coding: utf-8 -*-
    from threading import _Timer
    from Queue import Queue, Empty
    from time import clock
     
    class Every(_Timer):
        def run(self):
            self.finished.wait(self.interval)
            while not self.finished.is_set():
                self.function(*self.args, **self.kwargs)
                self.finished.wait(self.interval)
     
    def send(q, lst):
        global last
        try:
            # renvoie un element de la queue et le supprime de la queue
            frame = q.get_nowait() 
            now = clock()
            lst.append( "%6f frame sent: %s" % (now-last, frame) )
            last = now
            # indique que la tache dans la queue a ete terminee
            q.task_done()
     
        except Empty:
            # si la queue est vide
            pass
     
    # queue FIFO
    q = Queue()
     
    lst = []
    e = Every(0.01, send, (q,lst))
    last = clock()
    e.start()
     
    for i in range(10):
        # place i dans la queue
        q.put(i)
     
    # bloque jusqu'a ce que tous les elements de la queue aient ete traites
    q.join()
     
    e.cancel()
     
    for l in lst:
        print l
    Résultat:
    0.010471 frame sent: 0
    0.009979 frame sent: 1
    0.010000 frame sent: 2
    0.009991 frame sent: 3
    0.010015 frame sent: 4
    0.010018 frame sent: 5
    0.009987 frame sent: 6
    0.010013 frame sent: 7
    0.010031 frame sent: 8
    0.009964 frame sent: 9

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 28
    Points : 25
    Points
    25
    Par défaut
    Bonjour à tous,
    merci pour ton aide dividee.

    C'est vraiment bizarre, quand j'exécute le dernier code sur ma machine :
    0.009796 frame sent: 0
    0.018551 frame sent: 1
    0.009762 frame sent: 2
    0.018555 frame sent: 3
    0.018556 frame sent: 4
    0.009777 frame sent: 5
    0.018547 frame sent: 6
    0.018548 frame sent: 7
    0.009763 frame sent: 8
    0.018558 frame sent: 9

    Est ce que ça peut venir de la version python, de l'OS ? (chez moi :python 2.62 sous windows XP)
    a priori, mon PC ne fait pas grand chose d'autre pendant l'exécution...

  10. #10
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Points : 1 384
    Points
    1 384
    Par défaut
    Bonsoir,

    Ce qui m'étonne le plus c'est qu'il "saute" souvent un tick, comme si la queue ne se remplissait pas assez vite... Chez moi j'obtiens des résultats corrects même avec des intervalles de 1ms:
    0.001235 frame sent: 0
    0.000902 frame sent: 1
    0.001005 frame sent: 2
    0.000993 frame sent: 3
    0.001021 frame sent: 4
    0.001005 frame sent: 5
    0.000998 frame sent: 6
    0.000976 frame sent: 7
    0.000999 frame sent: 8
    0.001069 frame sent: 9
    C'est peut-être lié à l'OS. Je suis sous Windows 7 avec Python 2.7.
    Essaie peut-être avec cette implémentation alternative de la classe Every:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    class Every(_Timer):
        def run(self):
            sleep(self.interval)
            while not self.finished.is_set():
                self.function(*self.args, **self.kwargs)
                sleep(self.interval)
    J'ai regardé le code Event.wait qui était utilisé dans mon code précédent et il est assez complexe; utiliser sleep directement pourrait améliorer les choses... mais j'y crois qu'à moitié.

    Vérifie aussi si ça ne se stabilise pas après qqes itérations supplémentaires (100 au lieu de 10, par exemple).

    J'ai chronométré la durée d'exécution de la fonction send à 7 ou 8 microsecondes (après les premières itérations qui sont plus lentes); même si ton PC est très lent cela m'étonnerais que cela ait un effet pour des périodes de 10 ms...

  11. #11
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    28
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 28
    Points : 25
    Points
    25
    Par défaut
    Bonjour à tous,
    tu as raison, dividee, j'ai remplacé Event.wait par un sleep dans Every et ça va beaucoup mieux :

    interval = .01
    0.010290 frame sent: 0
    0.010739 frame sent: 1
    0.010743 frame sent: 2
    0.010739 frame sent: 3
    0.010764 frame sent: 4
    0.010728 frame sent: 5
    0.010734 frame sent: 6
    0.010753 frame sent: 7
    0.010737 frame sent: 8
    0.010737 frame sent: 9
    interval = .001
    0.002061 frame sent: 0
    0.001948 frame sent: 1
    0.001952 frame sent: 2
    0.001954 frame sent: 3
    0.001953 frame sent: 4
    0.001958 frame sent: 5
    0.001948 frame sent: 6
    0.001958 frame sent: 7
    0.001950 frame sent: 8
    0.001952 frame sent: 9
    L'écart de temps est régulier, un peu plus fort que celui demandé.
    De 7 à 9 dix-millièmes ?

    Le nombre d'itérations ne change rien. Avec 10 ça suffit. Les deux premiers temps sont quelques fois mauvais mais à partir du 3ème, c'est stable.

    Merci pour le coup de main.

Discussions similaires

  1. Envoi d'une trame ethernet
    Par Sékiltoyai dans le forum Réseau
    Réponses: 4
    Dernier message: 22/03/2009, 16h51
  2. Réponses: 5
    Dernier message: 28/09/2007, 09h52
  3. [Réseau] Connexion et envoie d'une trame
    Par ivanoe25 dans le forum Langage
    Réponses: 10
    Dernier message: 29/09/2006, 00h04
  4. Problème avec l'envoi d'une trame TCP
    Par fredoBreton dans le forum API, COM et SDKs
    Réponses: 14
    Dernier message: 17/11/2005, 20h19

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