python et les Threads

Comment utiliser simplement les Thread ?

import threading

def affiche(nb, nom = ''):
    for i in range(nb): print nom, i

a = threading.Thread(None, affiche, None, (200,), {'nom':'thread a'})
b = threading.Thread(None, affiche, None, (200,), {'nom':'thread b'})
a.start()
b.start()

Comment arrêter définitivement un Thread ?

import threading
import time

class Affiche(threading.Thread):
    def __init__(self, nom = ''):
        threading.Thread.__init__(self)
        self.nom = nom
        self.Terminated = False
    def run(self):
        i = 0
        while not self.Terminated:
            print self.nom, i
            i += 1
            time.sleep(2.0)
        print "le thread "+self.nom +" s'est termine proprement"
    def stop(self):
        self.Terminated = True

Le problème de la méthode précédente est donc le fait qu’il peut y avoir un laps de temps important entre le moment de la demande de l’arrêt du thread et celui où le thread est réèllement terminé dû à la durée du timer. En utilisant la classe Event, on peut ainsi accélérer l’arrêt du thread car la méthode monevent.wait(timeout) bloque le thread pendant la durée timeout où jusqu’au moment où la méthode monevent.set() est appelée. La classe Affiche2 présente un exemple sur ce principe.

class Affiche2(threading.Thread):
    def __init__(self, nom = ''):
        threading.Thread.__init__(self)
        self.nom = nom
        self._stopevent = threading.Event( )
    def run(self):
        i = 0
        while not self._stopevent.isSet():
            print self.nom, i
            i += 1
            self._stopevent.wait(2.0)
            print "le thread "+self.nom +" s'est termine proprement"
    def stop(self):
        self._stopevent.set( )

a = Affiche2('Thread A')
b = Affiche2('Thread B')
c = Affiche2('Thread C')

a.start()
b.start()
c.start()
time.sleep(6.5)
a._Thread__stop()
b.stop()
c.stop()

Arrêter un thread par un control-C

rien de plus simple il suffit d’intercepter le KeyBoardInterrupted

import sys

#global
THREAD = None

class Affiche2(threading.Thread):
    def __init__(self, nom = ''):
        threading.Thread.__init__(self)
        self.nom = nom
        self._stopevent = threading.Event( )
    def run(self):
        i = 0
        while not self._stopevent.isSet():
            print self.nom, i
            i += 1
            self._stopevent.wait(2.0)
            print "le thread "+self.nom +" s'est termine proprement"
    def stop(self):
        self._stopevent.set( )

def lanceprog():
    THREAD = Affiche2('Thread C')
    THREAD.start()

def exitprog():
    THREAD.stop()
    sys.exit(0)

try:
    print 'Utilisez Control-C pour finir'
    lanceprog()
except KeyboardInterrupt:
    exitprog()