PYTHON2 : pb de threads

Bonjour,

Je pense jamais à poster ici pour les problèmes de codage :frowning: Alors pour une fois je vais tenter :slightly_smiling:

J’ai un script python qui s’occupe de récupérer des températures et les enregistrer dans une base de donnée.
J’ai un peu allégé tout ça pour qu’on y voit plus clair.
Etant très pressé, mon script de départ ne gérait pas les erreurs, et ça fonctionnait très bien… La j’ai envie de le terminer…

J’ai donc ajouté ce qu’il fallait à mes threads pour que lorsqu’une erreur BT intervient, les threads s’arrêtent, et la fonction liée à l’erreur du BT relance le tout après reconnexion du BT.
Lorsque j’ai ajouté les lignes xxx = threading.Event(), en cas d’erreur il arrive quelque chose que j’ai jamais rencontré :
la fonction erreurBT() stope tout, et relance le init() La dernière ligne de celui-ci ne s’execute pas lorsque elle est appelée…

Donc au démarrage, aucun problème… init() est entièrement executée.
Si je coupe le module BT, l’erreur est bien détectée. Les threads sont bien coupés, ma fonction init() est relancée… mais à l’execution de la ligne self.startRecptBT(), PAF… ça s’arrête net, sans message d’erreur… donc je ne sais pas la cause du problème.

Voici le code allégé qui provoque la même erreur :

[code]#!/usr/bin/python2
#-- coding: utf-8 --

import sys
import os
import locale

import time
import datetime
from bluetooth import *
from serial import *

import threading
from subprocess import call
import subprocess

############################ Class gestion module d’arrosage BLUETOOTH ############################
PRINT_DEBUG = False
class Bt(Object) :
#------------- init -------------
def init(self, port=1, delaiReceptBT=0.1, delaiLect=60):

    self.debugTxt("Initialisation de l'application")
    self.listeDonnees = {
                        u"I": [u"Température Interne (°C)", 0 ],
                        u"E": [u"Température Externe (°C)", 0 ],
                        u"H": [u"Humidité du sol", 0 ],
                        u"L": [u"Luminosité", 0 ],
                        u"N": [u"Niveau d'eau", 0 ]
                        }

    self.infoDemandee = ""
    self.reponseEnTraitement = True

    self.ThreadRunedServ = False
    self.ThreadRunedLect = False


    self.delaiReceptBT = delaiReceptBT
    self.delaiLect = delaiLect


    self.debugTxt("Démarre les threads :")
    self.startRecptBT()

def debugTxt(self, message):
    print message
    f=open("/var/log/arrosage.log","a")
    f.write(message + "\n")
    f.close()

def afficheTout(self):
    for a in self.listeDonnees:
        self.debugTxt(self.listeDonnees[a][0].encode('utf-8') + " : " + self.listeDonnees[a][1])

def erreurBT(self, erreur):
    self.debugTxt("ERREUR BT (erreurBT%s" % erreur)

    self.debugTxt("Demande l'arrêt des threads : ")
    self.client_socket.close()

    self.stopRecptBT()
    self.stopInterroge()

    #self.debugTxt("Attend et force l'arrêt des threads : ")
    #self.serveurBtThread.join()
    #self.serveurBtInterroge.join()


    self.debugTxt("Relance le thread startRecptBT : ")
    self.__init__()


# ------------- thread de reception bluetooth -------------
def threadReceptBT(self):
    while True:
        try:
            self.client_socket=BluetoothSocket( RFCOMM )
            self.client_socket.connect(("20:13:08:19:04:51", 1))
            # démarrage des autres threads si connexion au module BT OK
            self.startInterroge()

            break
        except BluetoothError, err:
            print err
            self.client_socket.close()
            time.sleep(1.1)


    while self.ThreadRunedServ:
        self.heure = time.strftime("%A %d %B %Y %H:%M:%S",time.localtime())
        car = ""
        val = ""
        while True :
            try:
                car = self.client_socket.recv(1)
                if car == "!":
                    break
                val = val + car
                self._serveurBtThreadStopevent.wait(self.delaiReceptBT)
            except BluetoothError, err:
                self.erreurBT(err)
        if self.infoDemandee != '':
            self.listeDonnees[self.infoDemandee][1] = val
            if PRINT_DEBUG:
                print u"%s(%s) -> %s" % (self.listeDonnees[self.infoDemandee][0], self.infoDemandee, val)
        self.reponseEnTraitement = False

    self.client_socket.close()
    self.debugTxt("threadReceptBT : fin")
    return 0

def stopRecptBT(self):
    self.debugTxt("Arrêt du thread threadReceptBT")
    self.ThreadRunedServ = False
    self._serveurBtThreadStopevent.set()
    self.serveurBtThread._Thread__stop()

def startRecptBT(self):
    self.debugTxt("Démarrage du thread threadReceptBT")
    self.serveurBtThread = threading.Thread(None, self.threadReceptBT)
    self.ThreadRunedServ = True
    self._serveurBtThreadStopevent = threading.Event()
    self.serveurBtThread.start()

#------------- thread requette bluetooth -------------
def threadInterroge(self):
    time.sleep(1)
    while self.ThreadRunedLect:
        heure = time.strftime("%A %d %B %Y %H:%M:%S",time.localtime())
        self.debugTxt("--- nouvelle demande d'informations (%s)---" % heure)
        try:
            for a in self.listeDonnees:
                self.reponseEnTraitement = True
                self.infoDemandee = a
                self.client_socket.send(u"%s." % (self.infoDemandee))
                while self.reponseEnTraitement: # temporise le temps que l'info arrive au serveur !
                    time.sleep(1)
            self.afficheTout()
            self._serveurBtInterrogeStopevent.wait(self.delaiLect)
        except BluetoothError, err:
            self.erreurBT(err)

def stopInterroge(self):
    self.debugTxt("Arrêt du thread threadInterroge")
    self.ThreadRunedLect = False
    self._serveurBtInterrogeStopevent.set()
    self.serveurBtInterroge._Thread__stop()

def startInterroge(self):
    self.debugTxt("Démarrage du thread threadInterroge")
    self.serveurBtInterroge = threading.Thread(None, self.threadInterroge)
    #self.delaiLect = delaiLect
    self.ThreadRunedLect = True
    self._serveurBtInterrogeStopevent = threading.Event()
    self.serveurBtInterroge.start()

if name == ‘main’:
if not ‘DISPLAY’ in os.environ:
os.environ[‘DISPLAY’] = ‘:0.0’

locale.setlocale(locale.LC_ALL, 'fr_FR.utf-8')
srv = Bt()

[/code]

et voici la sortie de la console :

Initialisation de l'application Démarre les threads : Démarrage du thread threadReceptBT Démarrage du thread threadInterroge --- nouvelle demande d'informations (mardi 02 septembre 2014 08:55:34)--- Température Interne (°C) : 20 Humidité du sol : 921 Température Externe (°C) : 14 Luminosité : 954 Niveau d'eau : 0 (--------------------------------ICI JE COUPE LE MODULE BLUETOOTH-----------------------------------) ERREUR BT (erreurBT(110, "Connexion termin\xc3\xa9e par expiration du d\xc3\xa9lai d'attente") Demande l'arrêt des threads : Arrêt du thread threadReceptBT Arrêt du thread threadInterroge Relance le thread startRecptBT : $

Merci d’avance pour votre aide

Désolé je vais pas pouvoir répondre à ta question, ton script pique un peu les yeux niveau style.

Pêlemêle :

  • Les boucles [mono]while[/mono], un coup [mono]while True[/mono], un coup [mono]while(1)[/mono]
  • La classe Bt doit descendre de la classe object
  • [mono]init[/mono] devrait être en tête de la classe
  • Pour l’ouverture/écriture dans un fichier, pense au context manager avec [mono]with[/mono]
  • [mono]car, val = “”, “”[/mono]
  • [mono]if blabla[/mono] et pas [mono]if(blabla)[/mono] (c’est pas du C :wink:)

Après honnêtement j’ai beaucoup de mal à te lire, tu as beaucoup beaucoup imbriqué. Par exemple, [mono]init[/mono] qui lance [mono]startRecptBT()[/mono] qui lance [mono]serveurBtThread.start()[/mono], je suis paumé (note que je suis surement paumé assez facilement, un peu fatigué).

Désolé :slightly_smiling:

ok