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 :

threading et �couteur d'�v�nements


Sujet :

Python

  1. #1
    Membre �clair�
    Profil pro
    Expert technique
    Inscrit en
    Septembre 2003
    Messages
    328
    D�tails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes C�te d'Azur)

    Informations professionnelles :
    Activit� : Expert technique

    Informations forums :
    Inscription : Septembre 2003
    Messages : 328
    Par d�faut threading et �couteur d'�v�nements
    Bonjour,

    Je suis en train de tester le threading sur python, et je rencontre quelque difficult�s. Mon test est simple:

    Je voudrai qu'un thread fasse des insertions dans une base pendant que mon programme principal affiche ce qui a �t� introduit.

    Voil� en gros le code que je teste (j'ai vir� toute la partie bdd car �a fonctionne bien sur cette partie).

    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
    #!/usr/bin/env python
     
    import sys
    import os
    import subprocess
    import re
    import signal
    import MySQLdb
    import threading
    import multiprocessing
    import time
     
    class Affiche2(threading.Thread):
            def __init__(self, nom = ''):
                    threading.Thread.__init__(self)
                    self.nom = nom
                    self._stopevent = threading.Event( )
            def run(self):
                    ''' FAIS DES INSERTIONS EN BASE '''
            def stop(self):
                    self._stopevent.set( )
     
    ''' main '''
    ''' appelle la fonction de connexion '''
    conn = connectDB()
     
    print "Daemon ready to work"
     
    c = Affiche2('Thread C')
    c.start()
    time.sleep(6.5)
    c.stop()
     
    while (1):
         ''' FAIS DES SELECT ET AFFICHE LE RESULTAT '''
    Voil� ce que �a donne en gros. Le prob est que quand le thread d�marre, il ne rend pas la main tant que les insertions ne sont pas termin�s. or je voudrai le faire tourner en parall�le du programme principal.

    Auriez-vous une piste � me filer ?

  2. #2
    Expert confirm�

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 307
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 307
    Par d�faut
    Salut,

    C'est fait pour tourner conjointement avec ton code principal, justement.

    Et ton code fonctionne tr�s bien d'ailleurs:
    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
     
    import threading
    import time
     
    class Affiche2(threading.Thread):
        def __init__(self, nom=''):
            threading.Thread.__init__(self)
            self.nom = nom
            self.is_alive = True
     
        def run(self):
            while self.is_alive:
                time.sleep(1)
                print 'Et pourtant je tourne'
     
     
    print "Daemon ready to work"
     
    c = Affiche2('Thread C')
    c.start()
    count = 5
    while count:
        print count
        time.sleep(1)
        count -= 1
     
    c.is_alive = False
    time.sleep(2)
    O� est le probl�me ?

  3. #3
    Expert �minent
    Homme Profil pro
    Architecte technique retrait�
    Inscrit en
    Juin 2008
    Messages
    21 770
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activit� : Architecte technique retrait�
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 770
    Par d�faut
    Salut,
    Le partage d'une m�me connexion � la BDD entre plusieurs threads est sp�cifique � l'API (MySQLDB) tant c�t� support que mise en �uvre.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  4. #4
    Membre �clair�
    Profil pro
    Expert technique
    Inscrit en
    Septembre 2003
    Messages
    328
    D�tails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes C�te d'Azur)

    Informations professionnelles :
    Activit� : Expert technique

    Informations forums :
    Inscription : Septembre 2003
    Messages : 328
    Par d�faut
    En fait, pour la partie bdd, je ne m'en fais pas. � la limite, je re-cr�e une nouvelle connexion dans le thread, et zou ...

    Ce que je ne comprends pas, c'est qu'au d�but du programme, il me dit bien que les threads ont �t� d�marr�s. Mais le reste du programme n'est pas ex�cut� tant que les threads ne sont pas termin�s.

    Par exemple, si dans mon __main__ j'ai 2 start() pour d�marrer 2 threads et que juste apr�s je fais un print, le print ne s'affiche pas tant que les threads ne sont pas termin�s.

    Par contre, c'est vrai que les 2 threads s'ex�cutent simultan�ment. Si je comprends bien, il faut donc que mon thread qui ins�re et celui qui fait les select tournent en parall�le et non, juste un thread pour l'insert et le select dans le __main__ apr�s le start() du thread d'insertion ?

    Sinon, il va falloir que je buche sur le partage de ressource entre 2 threads car les 2 threads, � un moment donn�, devront utiliser le m�me port s�rie. Ne pouvant pas ouvrir 2 fois le port, je serai oblig� de l'ouvrir dans le programme principal, et de partager mon objet sur les 2 threads. C'est possible �a ?

  5. #5
    Expert confirm�

    Homme Profil pro
    Inscrit en
    Octobre 2008
    Messages
    4 307
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2008
    Messages : 4 307
    Par d�faut
    Dans la question de d�part il s'agit d'un seul thread.

    Ce thread ne fonctionne pas comme attendu parce qu'il est mal utilis�.

    1. Un thread doit �tre con�u comme une t�che unique.
    2. Le code principal ne doit rien en attendre.
    3. Il devrait (je ne dis pas il doit) disposer de toutes ses resources avant d'�tre lanc�.
    4. il faut le laisser mourir de sa mort naturelle.

    Le code exemple de mon post pr�c�dent remplit exactement la t�che d�crite dans la question initiale.

    J'invite zerros � relire sa question.

  6. #6
    Membre �clair�
    Profil pro
    Expert technique
    Inscrit en
    Septembre 2003
    Messages
    328
    D�tails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes C�te d'Azur)

    Informations professionnelles :
    Activit� : Expert technique

    Informations forums :
    Inscription : Septembre 2003
    Messages : 328
    Par d�faut
    ok, apr�s avoir fait quelques tests avec le code de VincsS (merci), le fonctionnement me convient, sauf que mes 2 threads doivent tourner en boucle. Du coup voici le code que j'ai fait, mais je suis encore confront� � plusieurs soucis:

    1 - Le CPU monte d'un coup d�s que je lance le d�mon
    2 - Impossible d'arr�ter les threads sans killer le process python

    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
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    #!/usr/bin/env python2.7
     
    import sys
    import os
    import subprocess
    import re
    import signal
    import MySQLdb
    import threading
    import time
     
    ##########################################################################
    # class
    ##########################################################################
     
    class watchSerial(threading.Thread):
    	''' thread init '''
    	def __init__(self, name = ''):
    		threading.Thread.__init__(self)
    		self.name = name
    		self._stopevent = threading.Event()
     
    	''' main process of the thread '''
    	def run(self):
    		while not self._stopevent.isSet():
    			conn = connectDB()
    			results = execSQL(conn,'SELECT * FROM evt WHERE type="Receive" ORDER BY tstamp')
    			for row in results:
    				idEvt = row["idEvt"]
    				action = row["action"]
    				hardName = row["hardName"]
    				idHard = row["idHard"]
    				hardKey = row["hardKey"]
    				serial = row["serial"]
    				cmd = row["cmd"]
     
    				print "[" + str(serial) + "] found evt " + action
    				print "[" + str(serial) + "] Deleting evt " + str(idEvt)
    				execSQL(conn,'DELETE FROM evt WHERE idEvt=' + str(idEvt))
     
    			closeDB(conn)
     
    	''' stop the thread '''
    	def stop(self):
    		self._stopevent.set()
     
    class watchEvt(threading.Thread):
    	''' thread init '''
    	def __init__(self, name = ''):
    		threading.Thread.__init__(self)
    		self.name = name
    		self._stopevent = threading.Event()
     
    	''' main process of the thread '''
    	def run(self):
    		while not self._stopevent.isSet():
    			conn = connectDB()
     
    			results = execSQL(conn,'SELECT * FROM evt WHERE type="Send" OR type="Ring" OR type="Sys" ORDER BY tstamp')
    			for row in results:
    				idEvt = row["idEvt"]
    				action = row["action"]
    				hardName = row["hardName"]
    				idHard = row["idHard"]
    				hardKey = row["hardKey"]
    				serial = row["serial"]
    				cmd = row["cmd"]
     
    				if (action == "ring"):
    					print "[" + str(serial) + "] found evt " + action
    					res = execSQL(conn,'SELECT * FROM conf WHERE idConf=1')
    					for conf in res:
    						appPath = conf['appPath']
    						ringFile = conf['ringFile']
     
    					ring(appPath,ringFile,serial)
     
    				if (action == "sys"):
    					print "[" + str(serial) + "] found evt " + action
    					execSys(cmd,serial)
     
    				print "[" + str(serial) + "] Deleting evt " + str(idEvt)
    				execSQL(conn,'DELETE FROM evt WHERE idEvt=' + str(idEvt))
     
    			closeDB(conn)
    			''' self._stopevent.wait(1.0) '''
     
    	''' stop the thread '''
    	def stop(self):
    		self._stopevent.set()
     
    ##########################################################################
    # functions
    ##########################################################################
     
    ''' execute a system command on host '''
    def execSys(sysCmd,serial):
    	print "[" + str(serial) + "] Executing sys cmd:  " + str(sysCmd)
    	os.system(sysCmd)
     
    ''' execute ring bell  '''
    def ring(appPath,ringFile,serial):
    	conf = appPath + "/config/mplayer.conf"
    	file = appPath + "/ringtones/" + ringFile;
    	ret = subprocess.Popen("ps -aef | grep mplayer | grep -v grep | awk '{print $2}'", shell=True, stdout=subprocess.PIPE)
    	ps = ret.stdout.read() . rstrip('\n')
    	ret.stdout.close()
    	val = re.search(r"(\d+)", ps)
    	if val:
    		print "[" + str(serial) + "] Already ringing ..."
    	else:
    		os.system("mplayer -include " + conf + " " + file + " &")
    		print "[" + str(serial) + "] Ringing"
     
    ''' connect to DB '''
    def connectDB():
    	try:
    		conn = MySQLdb.connect(
    			host = "127.0.0.1",
    			user = "xxxx",
    			passwd = "xxxx",
    			db = "xxxx"
    		)
    		return conn
    	except MySQLdb.Error, e:
    		print "Error %d: %s" % (e.args[0], e.args[1])
    		sys.exit(1)
     
    ''' execute sql queries '''
    def execSQL(conn,query):
    	try:
    		cursor = conn.cursor(MySQLdb.cursors.DictCursor)
    		cursor.execute(query)
    		rows = cursor.fetchall()
    		cursor.close()
    		return rows
    	except MySQLdb.Error, e:
    		print "Error %d: %s" % (e.args[0], e.args[1])
    		sys.exit(1)
     
    ''' disconnect from DB '''
    def closeDB(conn):
    	conn.close()
     
    ##########################################################################
    # main program
    ##########################################################################
     
    if __name__=='__main__':
    	try:
    		watchEvtT = watchEvt('watchEvt')
    		watchSerialT = watchSerial('watchSerial')
    		watchEvtT.start()
    		watchSerialT.start()
    	except KeyboardInterrupt:
    		print "Ctrl-C pressed, exiting"
    		watchEvtT.stop()
    		watchSerialT.stop()
    		sys.exit()
    Le watchEvt r�cup�re des �v�nements de type 'Sys', 'Ring' et 'Serial' et les ex�cute (pour le moment je n'ai fait que le ring et sys) et le watchSerial devra au final v�rifier ce qui arrive sur une liaison serial et faire des insertions de type "Receive" dans la table des �v�nements. N'ayant pas encore pr�parer la partie serial, je fais juste un insert de type "Receive" dans watchEvt et un select puis un drop dans watchSerial.

    Pourquoi est-ce que lorsque je fais CTR-C le programme ne s'arr�te pas ? Pourquoi est-ce que le programme prend autant de ressources lorsqu'il tourne ? Il tourne aux alentours de 60% et monte m�me parfois � 99% de load cpu.

    Ce d�mon python tourne sur une raspberry pi dot� d'un CPU arm.

    J'esp�re que vous pourrez m'aiguiller sur ce que je fais de mal ...

  7. #7
    Expert �minent
    Homme Profil pro
    Architecte technique retrait�
    Inscrit en
    Juin 2008
    Messages
    21 770
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activit� : Architecte technique retrait�
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 770
    Par d�faut
    Citation Envoy� par zerros Voir le message
    Pourquoi est-ce que lorsque je fais CTR-C le programme ne s'arr�te pas ? Pourquoi est-ce que le programme prend autant de ressources lorsqu'il tourne ? Il tourne aux alentours de 60% et monte m�me parfois � 99% de load cpu.
    Tel que vous avez �crit cela les "control-C" sont pris en compte jusqu'au retour des thread.start... apr�s, le programme attend que les threads se termine mais il n'y a rien pour attraper "control-C".

    Exemple:

    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
    import threading
    import time
    import sys
     
    def waitforever():
        while True:
            print "waitforever"
            time.sleep(1)
     
    if __name__ == '__main__':
        th = threading.Thread(target=waitforever)
        th.daemon = True  
        th.start()
     
        while True:
            try:
                time.sleep(0.5)
            except KeyboardInterrupt:
                print 'KeyboardInterrupt'
                break
     
        print ('done')
    Le programme principal attend un eventuel control-C.
    th.daemon = True permet de sortir du programme: il n'y a pas de m�canique pour arr�ter la thread.

    Sans pause entre les diff�rents passages, �� bouffe du CPU inutilement: on cherche dans la base de donn�e sans rien trouver et on boucle.

    Le vrai sujet est pourquoi utiliser des threads:
    - �� ne sert � rien dans votre cas: les activit�s sont synchrones(*),
    - comme vous ne savez pas les utiliser vous accumulez les d�pendances entre des difficult�s: interroger le SGDB, lancer des taches, mettre cela en threads,...

    (*) watchSerial n'est qu'un cas particulier de watchEvt: plut�t que lancer une commande on d�truit les event de type "Receive".

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  8. #8
    Membre �clair�
    Profil pro
    Expert technique
    Inscrit en
    Septembre 2003
    Messages
    328
    D�tails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes C�te d'Azur)

    Informations professionnelles :
    Activit� : Expert technique

    Informations forums :
    Inscription : Septembre 2003
    Messages : 328
    Par d�faut
    En fait le d�mon sera asynchrone au final. Actuellement, pour faire les tests j'envoi un insert depuis le watchEvt pour que le select de watchSerial puisse le "poper" et le d�truire. Je fais �a car je n'ai pas encore fait la partie serial.

    Au final, quand un �v�nement sera r�cup�rer dans watchEvt, notamment si c'est un �v�nement de type serial, une donn�e sera �crite dans un serial (/dev/ttyUSB0). L'appareil connect� sur ce serial va ex�cuter une action, puis renvoyer un status qui sera "traper" par le watchSerial et ins�r� en base avec le type Receive. Mais le mat�riel peut recevoir des ordres d'une autre source �galement, et le status de ces ordres doivent �tre ins�r�s en base �galement.

    Les threads doivent tourner en boucle pour traiter les �v�nements aussit�t qu'ils arrivent. Dans ce cas l�, existe t il un autre moyen d'arriver � mes fins qu'utiliser les threads ?

  9. #9
    Membre �clair�
    Profil pro
    Expert technique
    Inscrit en
    Septembre 2003
    Messages
    328
    D�tails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes C�te d'Azur)

    Informations professionnelles :
    Activit� : Expert technique

    Informations forums :
    Inscription : Septembre 2003
    Messages : 328
    Par d�faut
    j'ai ajout� une tempo de 0.5s et le cpu tombe � 3. oufff. 0.5, �a ira tr�s bien pour commencer.

    Il me reste plus qu'� trouver une solution pour la partie arr�t des threads, et/ou carr�ment changer la mani�re de tout g�rer en utilisant autre chose que les threads. Mais quoi ?

  10. #10
    Expert �minent
    Homme Profil pro
    Architecte technique retrait�
    Inscrit en
    Juin 2008
    Messages
    21 770
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activit� : Architecte technique retrait�
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 770
    Par d�faut
    Citation Envoy� par zerros Voir le message
    Les threads doivent tourner en boucle pour traiter les �v�nements aussit�t qu'ils arrivent. Dans ce cas l�, existe t il un autre moyen d'arriver � mes fins qu'utiliser les threads ?
    Votre "Aussitot" passe par:
    1. mise en base,
    2. attente de la fin du traitement des taches lanc�es par watchEvt (ce qui a �t� lu 'avant'),
    3. la lecture de ce qui est nouveau,

    Le d�lai entre un �v�nement et son traitement est difficile � borner => ce n'est pas du temps r�el. Vu que �� passe par des acc�s disques le temps de r�ponse (d�lai) sera toujours sup�rieur � quelques millisecondes.

    Si votre "fin" est de bouffer du temps CPU pour rien, vous y arriverez s�rement avec des threads. Si vous voulez que les d�lais de traitements soient born�s et inf�rieurs � 1/10 de milliseconde, il faut revoir le design.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  11. #11
    Expert �minent
    Homme Profil pro
    Architecte technique retrait�
    Inscrit en
    Juin 2008
    Messages
    21 770
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activit� : Architecte technique retrait�
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 770
    Par d�faut
    Citation Envoy� par zerros Voir le message
    Il me reste plus qu'� trouver une solution pour la partie arr�t des threads, et/ou carr�ment changer la mani�re de tout g�rer en utilisant autre chose que les threads.
    La m�canique que vous avez d�j� fonctionne.
    Mais vous ne savez pas l'utiliser.
    Relisez ce que je vous ai d�j� indiqu� plus haut.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  12. #12
    Expert confirm�
    Avatar de tyrtamos
    Homme Profil pro
    Retrait�
    Inscrit en
    D�cembre 2007
    Messages
    4 486
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes C�te d'Azur)

    Informations professionnelles :
    Activit� : Retrait�

    Informations forums :
    Inscription : D�cembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par d�faut
    Bonjour,

    Avec les threads, on fait � peu pr�s ce qu'on veut, sauf � les arr�ter "sauvagement". Mais la solution propos�e ici (avec le while et le stop) fonctionne tr�s bien.

    Il y a plusieurs choses qui me g�nent dans le dernier code de zerros.

    - chaque thread cherche des donn�es (select) et en efface (delete). Il n'est donc pas impossible qu'un thread essaie d'effacer des donn�es qui viennent d'�tre effac�es par un autre thread. Ce n'est pas logique. M�me si le serveur accepte les acc�s concurrents, il faudrait que chaque thread commence et finisse son travail sans qu'un autre thread s'interpose sur les m�mes donn�es: on fait �a avec un verrou!

    - les threads peuvent effectivement avoir un fonctionnement permanent au sein d'un programme, mais le fait que la seule fa�on de les arr�ter est un Ctrl-C me choque un peu. Il faudrait, par exemple, que lorsqu'un thread ne trouve plus de donn�es dans son "select", il g�n�re lui-m�me son arr�t (fin de sa m�thode "run").

    - dernier point mineur, il ne devrait pas y avoir de "print" dans les threads, parce qu'il n'y a qu'un seul canal d'affichage (sys.stdout) que les threads et le "thread pricipal" doivent se partager. On devrait donc utiliser un verrou.

    Voil� un petit programme de test qui prend en compte le 1er point (le verrou sur la base de donn�es):

    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
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    from __future__ import division
    # Python 2.7
     
    import sys, os, threading, time
     
    ##########################################################################
    class Monthread(threading.Thread):
     
        def __init__(self, name = ''):
            threading.Thread.__init__(self)
            self.name = name
            self.encore = True
     
        def run(self):
            global verroudb
     
            while self.encore:
                verroudb.acquire() # bloque jusqu'à ce que le verrou soit libéré
                #conn = connectDB()
                print
                print "thead %s instruction SELECT" % (self.name,)
                time.sleep(0.1) # simul temps d'execution
                print "thead %s instruction DELETE" % (self.name,)
                #closeDB(conn)
                verroudb.release() # libère le verrou
                time.sleep(0.1) # pour que while ne consomme pas trop de ressources
     
        def stop(self):
            self.encore = False
     
    ##########################################################################
    if __name__=='__main__':
     
        # création d'un verrou pour que chaque thread intervienne seul sur la base
        verroudb = threading.Lock()
     
        # ouverture des threads
        thread1 = Monthread("1")
        thread2 = Monthread("2")
        thread3 = Monthread("3")
        thread4 = Monthread("4")
        thread5 = Monthread("5")
        thread1.start()
        thread2.start()
        thread3.start()
        thread4.start()
        thread5.start()
     
        # boucle d'attente interruptible par Ctrl-C
        try:
            while True:
                time.sleep(0.1)
        except KeyboardInterrupt:
            pass
     
        # fermeture des threads
        thread1.stop()
        thread2.stop()
        thread3.stop()
        thread4.stop()
        thread5.stop()
     
        # on attend que tous les threads soient effectivement arrêtés
        while thread1.isAlive() or thread2.isAlive() or thread3.isAlive() or thread4.isAlive() or thread5.isAlive():
            time.sleep(0.1)
     
        print
        print "fin du programme!"
    A l'ex�cution, il est affich�:

    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
    ...
     
    thead 1 instruction SELECT
    thead 1 instruction DELETE
     
    thead 2 instruction SELECT
    thead 2 instruction DELETE
     
    thead 3 instruction SELECT
    thead 3 instruction DELETE
     
    thead 4 instruction SELECT
    thead 4 instruction DELETE
     
    thead 5 instruction SELECT
    thead 5 instruction DELETE
     
    thead 1 instruction SELECT
    thead 1 instruction DELETE
     
    thead 2 instruction SELECT
    thead 2 instruction DELETE
     
    ...
    On voit bien que lorsqu'un thread commence par un select, il termine bien par le delete sans qu'un autre thread n'intervienne entre les 2.

    L'ordre d'intervention des thread d�pend du caract�re al�atoire des t�ches de la boucle while qui ne se trouverait pas soumis au verrou sur la base de donn�es. Si par contre il n'y a aucune t�che hors du bloc "acquire() ...release()", les threads interviendont toujours dans le m�me ordre. Dans ce cas, on se demande si les threads sont bien utilies ici...

    Et avec un Ctrl-C, le programme arr�te proprement les 5 threads, et affiche � la fin que le programme est termin�.

  13. #13
    Expert �minent
    Homme Profil pro
    Architecte technique retrait�
    Inscrit en
    Juin 2008
    Messages
    21 770
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activit� : Architecte technique retrait�
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 770
    Par d�faut
    Salut,

    Citation Envoy� par tyrtamos Voir le message
    M�me si le serveur accepte les acc�s concurrents, il faudrait que chaque thread commence et finisse son travail sans qu'un autre thread s'interpose sur les m�mes donn�es: on fait �a avec un verrou!
    Comment fait-on lorsque il s'agit de process ind�pendants qui tournent sur des machines diff�rentes? Avec les SGDB, on passe par des transactions.

    Ceci dit le code du thread watchSerial r�cup�re les entr�es de la table evt de type "Receive" alors que watchEvt s'occupe des types "Send", "Ring", "Sys": ce ne sont pas les m�mes donn�es.

    Le traitement de watchSerial pourrait �tre int�gr� dans watchEvt qui s'occuperait en plus de ce type l�.

    In fine, on a un thread qui fait tout de fa�on s�quentielle et le programme principal qui attend qu'on tape "control-C".

    - les threads peuvent effectivement avoir un fonctionnement permanent au sein d'un programme, mais le fait que la seule fa�on de les arr�ter est un Ctrl-C me choque un peu. Il faudrait, par exemple, que lorsqu'un thread ne trouve plus de donn�es dans son "select", il g�n�re lui-m�me son arr�t (fin de sa m�thode "run").
    Le code de zerros arr�te les threads proprement: il a associ� un Event � chaque thread qu'il teste dans le run avant d'ex�cuter l'it�ration suivante de ses traitements.
    Ce qui est en d�faut, c'est le traitement des "control-C".
    J'esp�re que votre exemple lui permettra d'y voir plus clair.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  14. #14
    Membre �clair�
    Profil pro
    Expert technique
    Inscrit en
    Septembre 2003
    Messages
    328
    D�tails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes C�te d'Azur)

    Informations professionnelles :
    Activit� : Expert technique

    Informations forums :
    Inscription : Septembre 2003
    Messages : 328
    Par d�faut
    mouarff. je suis en train de d�cortiquer avec le manuel python lol.

    Je reviens vous dire quand j'aurai compris et appliquer vos conseils

    merciii en tout cas. a tr�s vite

  15. #15
    Membre �clair�
    Profil pro
    Expert technique
    Inscrit en
    Septembre 2003
    Messages
    328
    D�tails du profil
    Informations personnelles :
    Localisation : France, Var (Provence Alpes C�te d'Azur)

    Informations professionnelles :
    Activit� : Expert technique

    Informations forums :
    Inscription : Septembre 2003
    Messages : 328
    Par d�faut
    merci � vous !!! C'est impeccable. � marche au poil. J'ai mis 0.5 pour lib�rer encore un peu plus de ressource, et j'ai utilis� les Event en lisant le tuto de developpez: http://python.developpez.com/faq/?page=Thread

    Je reviendrai surement poser des questions sur le partage de ressources entre les threads.

    Merccciiiiiii

+ R�pondre � la discussion
Cette discussion est r�solue.

Discussions similaires

  1. R�ponses: 2
    Dernier message: 04/08/2012, 19h22
  2. R�ponses: 2
    Dernier message: 22/06/2011, 15h21
  3. Prototypage et �couteur d'�v�nement
    Par xess91 dans le forum G�n�ral JavaScript
    R�ponses: 18
    Dernier message: 29/12/2010, 19h57
  4. Passage d'arguments � un �couteur d'�v�nements
    Par JockdiL dans le forum ActionScript 3
    R�ponses: 3
    Dernier message: 14/08/2009, 13h35
  5. [POO]O� placer les �couteurs d'�v�nement utilisateur?
    Par ChriGoLioNaDor dans le forum Langages de programmation
    R�ponses: 4
    Dernier message: 03/09/2008, 07h28

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