Search code examples
pythoninheritancepolymorphismclass-variables

Python timer thread as class variable call timer.start() and timer.cancel() from different class instances


I am somewhat new to python and very new to threading. I am trying to write a client for a client-webserver interface and I am using the State design pattern. I am stuck on using a timer object inside my class as a class variable. I am implementing the object using the threading.Timer class, but I run into trouble when passing set_time method as an argument to the constructor. If I use threading.Timer(5.0, self.set_time) I get a "NameError: name 'self' is not defined" error . If I use threading.Timer(5.0, set_time) I get a "NameError: name 'set_time' is not defined" errror. Below is my code:

import time
import threading
import sys

from packet import Packet
from check import ip_checksum


class State():

    timer = threading.Timer(5.0, self.set_time)
    timeout = False

    def __init__(self):        
    time = False

    def time_out(self):
        return time

    def set_time(self):
        global timeout 
        timeout = True

    def start_timer(self):
        timer.start()

    def stop_timer(self):
        global timeout         
        timer.cancel()
        timeout = False

    def send_packet(self, data):
        print("Parent state send: " + data)
        self.start_timer()
        return True

    def receive_packet(self, packet):
        print("Parent state receive packet")
        self.stop_timer()
        return True

I googled and have looked at Python class instance vs. class variables and Python threading.timer - repeat function every 'n' seconds. These have have helped, but still I have two questions. One is in general , the other more specific to my issue.

One: how should I instantiate a class variable that uses a constructor that refers to a method in the class.

Two: how can I use a thread as a class variable to be used by classes that inherit from my State class? For example, say I have a class Wait_For_Call that inherits from State. I instantiate an object wait_for_call = Wait_For_Call(). Could I just do wait_for_call.start_timer() or wait_for_call.stop_timer()?


Solution

  • One: This is discussed in this question. You can use a module variable (see below).

    Two: Use @classmethod decorator to declare a class method. The first parameter of the method (usually named 'cls') gives you access to the class variables.

    Since, in the answer to your first question, I suggested using a module variable (as described in answers to the question I referenced), you do not need a class method or class variables to access it. You may still need them to access timeout, if you keep it as a class variable.

    Here you can see how to access a class variable from within a class method:

    class Base :
        my_number = 1
    
        @classmethod
        def class_method(cls):
            print (cls.my_number)
            cls.my_number = cls.my_number + 3