2010-10-28 7 views
2

J'ai un seul processus Python qui utilise un port série (ressource unique) qui est géré en utilisant une instance d'une classe A. Il existe deux threads différents initialisés en utilisant des instances des classes B et C, qui utilisent constamment la ressource de port série via l'objet déjà créé.Python Comment partager un port série avec deux threads différents (Classe A, Classe B)

import threading 

Class A(threading.Thread): 
    #Zigbee serial port handler 
    def __init__(self,dev): 
     #something here that initialize serial port 
    def run(): 
     while True: 
      #listening serial interface 
    def pack(self): 
     #something 
    def checksum(self): 
     #something 
    def write(self): 
     #something 

Class B(threading.Thread): 
    def __init__(self,SerialPortHandler): 
     self.serialporthandler=SerialPortHandler 
    def run(self) 
     while True: 
      #something that uses self.serialporthandler 

Class C(threading.Thread): 
    def __init__(self,SerialPortHandler): 
     self.serialporthandler=SerialPortHandler 
    def run(self) 
     while True: 
      #something that uses self.serialporthandler 

def main(): 
    a=A('/dev/ttyUSB1') 
    b=B(a) 
    b.start() 
    c=C(a) 
    c.start() 

if __name__=='main': 
    while True: 
     main() 

Le problème est que les deux threads tentent d'accéder à la ressource série en même temps. Je pourrais utiliser plusieurs instances de la même classe A, en attachant Lock.acquire() et Lock.release() dans les parties sensibles.

Certains d'entre vous pourraient me pointer du bon côté?

Merci d'avance.

Répondre

11

Alors que vous pouvez partager le port série en utilisant le verrouillage approprié, je ne le recommanderais pas. J'ai écrit plusieurs applications multi-thread qui communiquent sur le port série en Python, et dans mon expérience l'approche suivante est meilleure:

  • Avoir une seule classe, dans un seul thread, gérer la communication de port série réel , par l'intermédiaire d'un objet Queue ou deux:
    • Stuff lire à partir de l'orifice est placé dans la file d'attente
    • commandes à envoyer au port sont placés dans la file d'attente et le « fil de série » les envoie
  • Avoir la D'autres threads implémentent la logique en plaçant des éléments dans la file d'attente et en les sortant

L'utilisation de Queue objets va grandement simplifier votre code et le rendre plus robuste.

Cette approche ouvre beaucoup de possibilités en termes de design. Vous pouvez, par exemple, enregistrer des événements (callbacks) avec le gestionnaire de threads en série et les appeler (de manière synchronisée) lorsque des événements intéressants se produisent, etc.

+0

Merci pour le conseil, j'ai beaucoup de sens pour moi. – Jaime

0

Ajouter un threading.Lock()-class A et en font l'acquisition de la serrure lors de son utilisation:

def __init__(self,dev): 
    self.lock = threading.Lock() 

def read(self): 
    self.lock.acquire() 
    data = ? #whatever you need to do here to read 
    self.lock.release() 
    return data 

def write(self, data): 
    self.lock.acquire() 
    #whatever you need to do to write 
    self.lock.release() 
+1

Les verrous sont bons, c'est juste que dans Python vous les utilisez comme 'avec self.lock: retourne quelque chose()' –

+0

En supposant que OP utilise 2.6 ou plus tard. – user470379

+1

Méfiez-vous des exceptions lancées pendant que vous tenez le verrou. Utiliser 'with' (Python 2.6+) ici ou' try/finally' serait prudent. –