2016-05-06 6 views
0

Ich schreibe gerade einen Python Telegram Bot, der verwendet wird, um Raspi IOs zu überwachen und Nachrichten an einen Kanal zu senden. Im Grunde hat es eine Funktion, die eine Protokollierungsvariable llog aktualisiert.Python: Druckfunktion hängt beim Drucken der globalen Liste von Objekten

Diese Funktion (logUpdate), wie sie genannt wird, wird Einträge entfernen, die mehr als 5 Minuten alt sind. Ich habe versucht, den Inhalt der globalen Variable zu überprüfen. Beim Drucken hängt es einfach.

Dies scheint keine anderen Funktionen des Bot zu blockieren, da ich immer noch andere Bot-Befehle aufrufen kann.

Ich glaube nicht, dass es der Bot ist. Es muss sich um eine Art von Datenzugriffsproblemen handeln.

lege ich einige Code-Snippet:

#!usr/bin/python 

## 
### RF Security bot start script 
## 

## 
### Imports 
## 
import telegram  as tg 
import telegram.ext as tgExt 
import RPi.GPIO  as gpio 
import time 
from datetime import datetime as dt 

## 
### Common variables 
## 
NULLSENSOR = 0 
PRESSENSOR = 1 
MAGSENSOR = 2 

sensDict = {NULLSENSOR:"No sensor", 
      PRESSENSOR:"Pressure sensor", 
      MAGSENSOR:"Magnetic sensor"} 

# Event class 
class ev(object): 

     timestamp = 0 
     sType  = NULLSENSOR 

     def __init__(self, ts=0, st=NULLSENSOR): 
       self.timestamp = ts 
       self.sType  = st 


     def toString(self): 

       if(sType == PRESSENSOR): 
         return str("-> @"+timestamp.strftime('%c')+ 
            ": Pressure sensor triggered\n") 
       elif(sType == MAGSENSOR): 
         return str("-> @"+timestamp.strftime('%c')+ 
            ": Magnetic sensor triggered\n") 
       else: 
         return "" 


# Report log 
llog = []  # Data log 
lmutex = True # Log mutex for writing 

## 
### Hardware configuration 
## 

# GPIO callbacks 
def pressureCallback(channel): 
     global llog 
     global lmutex 
     global trigCntGlobal 
     global trigCntPress 

     ep = ev(ts=dt.now(), st=PRESSENSOR) 

     print("---> Pressure sensor triggered at "+ 
       ep.timestamp.strftime("%c")) 

     rfSecuBot.sendMessage('@channel', "Pressure sensor "+ 
         "triggered.") 

     while(not lmutex): 
       pass 

     lmutex = False 

     llog.insert(0, ep) 
     trigCntGlobal = trigCntGlobal + 1 
     trigCntPress = trigCntPress + 1 

     lmutex = True 


def magneticCallback(channel): 
     global llog 
     global lmutex 
     global trigCntGlobal 
     global trigCntMag 
     global rfSecuBot 

     em = ev(ts=dt.now(), st=PRESSENSOR) 

     print("---> Magnetic sensor triggered at "+ 
       em.timestamp.strftime("%c")) 

     rfSecuBot.sendMessage('@channel', "Magnetic sensor "+ 
         "triggered.") 

     while(not lmutex): 
       pass 

     lmutex = False 

     llog.insert(0, em) 
     trigCntGlobal = trigCntGlobal + 1 
     trigCntMag = trigCntMag + 1 

     lmutex = True 


# Periodic logging function 
def logUpdate(): 
     global llog 
     global lmutex 

     updTime = dt.now() 
     print("---> Updating log\n") 
     while(not lmutex): 
       pass 

     lmutex = False 

     for i in llog:       ########### STUCK HERE 
       print(i.toString())    ########### 

     # Check log timestamps 
     for i in llog: 
       if((updTime - i.timestamp).total_seconds() > 300): 
         llog.remove(i) 

     for i in llog:       ########### WAS STUCK HERE 
       print(i.toString())    ########### TOO 

     lmutex = True 

     print("---> Log updated\n") 


# Formatting function 
def logFormat(): 
     global llog 
     global lmutex 

     logUpdate() # Asynchronous call to logUpdate to make sure 
        # that the log has been updated at the time 
        # of formatting 

     while(not lmutex): 
       pass 

     lmutex = False 

     flog = [] 
     cnt = 0 

     for i in llog: 
       if(cnt < 10): 
         flog.append(i.toString()) 
         cnt = cnt + 1 
       else: 
         break 

     lmutex = True 

     print("----> Formatted string:") 
     print(flog+"\n") 
     return flog 


def listFormat(): 
     global llog 
     global lmutex 

     logUpdate() # Asynchronous call to logUpdate to make sure 
        # that the log has been updated at the time 
        # of formatting 

     while(not lmutex): 
       pass 

     lmutex = False 

     flog = [] 
     flog.append("  Sensors  \n") 

     dLen = len(sensDict.keys()) 

     if(dLen <= 1): 
       flog.append(sensDict.get(NULLSENSOR)) 
     else: 
       sdItr = sensDict.iterkeys() 
       st = sdItr.next() # Had to add extra var 
       while(dLen > 1): 
         st = sdItr.next() 
         trigCnt = 0 

         for i in llog: 
           if(i.sType == st): 
             trigCnt = trigCnt + 1 

         if(trigCnt < 1): 
           pass 
         else: 
           flog.append("-> "+st+"\n") 
           flog.append(" No. of times tripped: "+ 
              trigCnt+"\n") 

     lmutex = True 

     print("----> Formatted string:") 
     print(flog+"\n") 
     return flog 


## 
### Software configuration 
## 

def blist(bot, update): 
     print("--> List command received\n") 

     listString = "List of sensor trips in the last 5 minutes:\n" 
     listString = listString+listFormat() 

     print("> "+listString+"\n") 
    bot.sendMessage('@channel', listString) 


def log(bot, update): 
     print("--> Log command received\n") 

     logString = "Log of last 10 occurrences:\n" 
     logString = logString+logFormat() 

     print("> "+logString+"\n") 
    bot.sendMessage('@channel', logString) 


rfSecuBotUpd.start_polling(poll_interval=1.0,clean=True) 

while True: 
     try: 
       time.sleep(1.1) 
     except KeyboardInterrupt: 
       print("\n--> Ctrl+C key hit\n") 
       gpio.cleanup() 
       rfSecuBotUpd.stop() 
       rfSecuBot = 0 
       quit() 
       break 

## Callback registration and handlers are inserted afterwards 

# Just in case... 
print("--> Bot exiting\n") 
gpio.cleanup() 
rfSecuBotUpd.stop() 
rfsecuBot = 0 
print("\n\n\t *** EOF[] *** \t\n\n") 
quit() 

# EOF [] 

P. S. Ich denke, jemand könnte eine "Klassenversion" vorschlagen. Denke es funktioniert?

+0

Der einzige Ort in dem "logUpdate", in dem ein Hang möglich ist, ist 'while (not lmutex): pass'. Hast du es überprüft? (Fügen Sie einfach 'print (" ---> lmutex \ n ")' direkt nach der 'while'-Schleife hinzu. – Ilya

+0

"Beim Drucken hängt es einfach": was meinst du genau? Es druckt, stoppt dann oder es druckt gar nichts? Die erste Option wäre keine Überraschung, denn 'while (not lmutex): pass 'wird für immer endlos. Dieser Prozess hat keine Bedeutung, den Wert von "lmutex" zu ändern. – zezollo

+0

Die Verwendung globaler Variablen kann schwierig sein. Sie sollten einen Weg finden, um den Wert im Laufe der Zeit zu überprüfen. Zum Beispiel, wenn es irgendwo geändert wird, könnten Sie es vielleicht in stderr schreiben. So können Sie sehen, ob 'logUpdate' den aktualisierten Wert von' lmutex' erhält oder nicht. – zezollo

Antwort

1

In der toString Funktion, ich vergaß self vor den sollte-sein-Mitglieder sType und timestamp zu setzen:

def toString(self): 

      if(sType == PRESSENSOR): 
        return str("-> @"+timestamp.strftime('%c')+ 
           ": Pressure sensor triggered\n") 
      elif(sType == MAGSENSOR): 
        return str("-> @"+timestamp.strftime('%c')+ 
           ": Magnetic sensor triggered\n") 
      else: 
        return "" 

, weshalb der Wert zurückgegeben wird, war immer eine leere Zeichenfolge.

Hinweis für sich selbst: Überprüfen Sie Ihre Variablen !!!

In diesem Sinne, erklärte diese Art, warum es den Thread nicht zu blockieren schien.

+1

Bitte markieren Sie diese Antwort als Antwort auf Ihre Frage. Vielen Dank! – Oleiade