Python:如何启用和禁用函数?

0 投票
3 回答
7159 浏览
提问于 2025-04-18 01:10

我有一个树莓派,上面装了一个红外传感器。在我的Python脚本里,有一个线程类可以监听一个imap服务器(接收像START或STOP这样的指令)。我现在的想法是通过电子邮件发送命令,一旦脚本收到命令,就应该禁用一些功能,直到收到新的命令为止。但我现在最大的问题是,我不知道该怎么实现这个功能。

def take_picture():
   ...

def take_video():
   ...

class EmailThread(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        while True:
         ....
                if get_mail == 1:
                    if var_subject == 'STOP':
                        #TODO: stop take_picture(), take_video()
                        pass

                    elif var_subject == 'START':
                  #TODO: start take_picture(), take_video()
                        pass
                    else:
                        print u'Wrong command'

         time.sleep(600) #google doesn't like many connections within 10min

def main():
    # Start eMail Thread
    email = EmailThread()
    email.start()
    try:
        print "Waiting for PIR to settle ..."
        # Loop until PIR output is 0
        while GPIO.input(GPIO_PIR) == 1:
            Current_State = 0
        print "Ready"
        # Loop until threadingusers quits with CTRL-C
        while True :
            # Read PIR state
            Current_State = GPIO.input(GPIO_PIR)
            if Current_State == 1 and Previous_State == 0:
                counter = counter + 1
                # PIR is triggered
                start_time = time.time()

                log_to_file('Motion  Nr. %s detected!' % counter)
                take_picture()

                # Record previous state
                Previous_State = 1

            elif Current_State == 0 and Previous_State == 1:
                # PIR has returned to ready state
                stop_time=time.time()
                print "  Ready ",
                elapsed_time=int(stop_time-start_time)
                print " (Elapsed time : " + str(elapsed_time) + " secs)"
                Previous_State = 0

    except KeyboardInterrupt:
        print "Quit "
        # Reset GPIO settings
        GPIO.cleanup()

if __name__ == '__main__':
    main()

3 个回答

0

我觉得在这种情况下,self.enabled应该可以用吧?

def __init__(self):
    self.enabled=True        
    threading.Thread.__init__(self)

然后把启用状态切换为真或假?

2

在初始化的时候,你可以添加一个函数和布尔值(真或假)之间的映射,像这样:

class ClassWithTheFunctions:
    def __init__(self):
        import types
        #...
        self.funcMap = {}
        for o in self.__dict__:
            if type(self.__dict__[o]) == types.FunctionType or type(self.__dict__[o]) == types.MethodType:
                self.funcMap[self.__dict__[o]] = True

当你想调用一个函数时,先检查一下它的状态。

 if instanceOfTheClassWithTheFunctions.funcMap[funcIWantToCall] :
     funcIWantToCall()

如果你想禁用一个函数:

  instanceOfTheClassWithTheFunctions.funcMap[funcIWantToCall] = False

或者想启用它:

  instanceOfTheClassWithTheFunctions.funcMap[funcIWantToCall] = True
2

我觉得你的问题标题起得不太好。你想做的应该是启动和停止正在运行某些功能的线程。启动一个线程比较简单,但停止它就稍微复杂一些,这取决于这个功能内部是怎么运作的。

你需要了解一下线程之间的通信方法,特别是条件变量。一般来说,线程只有在允许你停止的时候才能优雅地停止,比如说它在等待某个条件变量的时候。

如果你其实不想用线程,而是想定期运行当前活跃的功能,那你就需要实现一个调度器——在最简单的情况下,调度器会不断循环遍历活跃功能的列表,并调用它们。

我建议你使用后者,因为线程通常会带来不必要的复杂性和错误源,但从你的问题来看,你似乎很想尝试前者。

撰写回答