Python: 打印全局对象列表时打印函数挂起

Python: print function hang when printing global list of objects

我目前正在编写一个 Python Telegram 机器人,用于监控 Raspi IOs 并向频道发送消息。所以基本上它有一个函数可以更新日志变量 llog.

这个函数 (logUpdate),正如它的名字一样,将删除超过 5 分钟的条目。在其中,我试图检查全局变量的内容。打印时,它只是挂起。

这似乎并没有阻止机器人的任何其他功能,因为我仍然可以调用其他机器人命令。

我不认为这是机器人。一定是某种数据访问问题。

我在下面附上一些代码片段:

#!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。我认为有人可能会建议使用 'class' 版本。觉得行得通吗?

toString函数中,我忘了把self放在应该成员sTypetimestamp前面:

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 ""

这就是返回值始终为空字符串的原因。

自我注意:检查你的变量!!!

就此而言,这解释了为什么它似乎没有阻塞线程。