Search code examples
pythonmultithreadingclassclass-variables

Python Thread class variable is blank


I've been trying to fix this issue for the past few hours, and i just can't figure out what i'm doing wrong!

I have a single python file:

REFRESH_RATE=10.0
MAX_SECONDS=30

class user_manager:
  users={}
  def __init__(self,queue,sign_properties):

    self.properties=sign_properties
    self.queue=queue
    self.lock=threading.Lock()
    t=threading.Thread(target=user_timer,args=(self.lock,))
    t.daemon=True
    t.start()

  def add_user(self,macaddr,user_properties):
    self.lock.acquire()
    user_manager.users[macaddr]=user(user_properties)
    self.lock.release()

  def user_exists(self, macaddr):
    if macaddr in user_manager.users:
      return True
    return False

  def update_rssi_for_user(self, macaddr,rssi):
    self.lock.acquire()
    user_manager.users[macaddr].update_rssi(rssi)
    self.lock.release()

  def get_users(self):
    return user_manager.users



def user_timer(lock):
  while True:
    print 'Test'
    lock.acquire()
    print user_manager.users
    lock.release()
    format = '%H:%M:%S'
    for user in user_manager.users:
      first_seen=user_manager.users[user].get_first_seen()
      current_time=str(datetime.datetime.now().time())
      difference=datetime.strptime(current_time, format) - datetime.strptime(first_seen[1], format)
      print 'difference'+str(difference.seconds)
      if difference.seconds >30:
        user.expire()
        del user_manager.users[user]
    time.sleep(REFRESH_RATE)

The idea is that the user_manager class has a class variable called users, that is populated during runtime - this works perfectly.

Then I have a threaded function called user_timer that is started from the user_manager, which manages these users and expires them after X amount of time. This is removed from the context of this post as it's not relevant.

Currently, every time user_timer is called the result of user_manager.users is an empty dictionary {} but from outside of this file other modules can see the class variable as being populated.

What exactly am i doing wrong, and why does it work in this fashion?

James.

EDIT:

Calling class' constructor:

    class api_wrapper(object):
  def __init__(self,queue,display_queue,macaddr):
    self.properties={}
    self.queue=queue
    self.register_sign(macaddr)
    self.user_manager=user_manager(self.queue,self.properties)
    self.nearby_devices={}
    self.display_queue=display_queue

Calling function from the above class:

def handle_address(self,address,postcode):
if self.user_manager is None:
  return
if self.user_manager.user_exists(address):
  #print user_manager.users
  self.user_manager.update_address_for_user(address,postcode)
  #self.display_queue.put(self.user_manager.get_users())
elif macaddr not in self.nearby_devices:
  if self.check_address(address) is False:
    self.nearby_devices[address]=postcode

Solution

  • I resolved this by spawning it as a Process instead and using the shared state variable of manager.Dict()!

    The thread i believe was copy the variables at the time of spawn, and because it was running in an almost 'separate' environment, the class variables weren't changing!

    Thanks all.

    James.