0

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()?

Program0
  • 37
  • 1
  • 7
  • You want them all to use one timer for all instances? – Basya Nov 06 '18 at 19:24
  • To clarify, when you say "refers to a method in the class", do you mean a static or non-static method (one that refers to instance variables would be a bit problematic to use when instantiating a class variable :-) ) – Basya Nov 06 '18 at 19:33
  • Yes, to use one timer for all instances. It would be a static method. – Program0 Nov 06 '18 at 22:16

1 Answers1

1

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
Basya
  • 1,477
  • 1
  • 12
  • 22
  • This answers question 1 for me. But I'm still not sure how to use one thread for the class. – Program0 Nov 08 '18 at 14:46
  • The suggestion in the linked question is to make it a module variable. Then there will be only one instance of it. I would think that there would be a way to make it a class variable, but if there is I have not found it. – Basya Nov 08 '18 at 17:58
  • That makes sense. The classmethod solved the more immediate of my problems. Thank you for your answer. – Program0 Nov 08 '18 at 19:51