【问题标题】:Python Thread class variable is blankPython Thread 类变量为空
【发布时间】:2014-07-28 12:48:59
【问题描述】:

过去几个小时我一直在尝试解决这个问题,但我就是不知道我做错了什么!

我有一个 python 文件:

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)

这个想法是 user_manager 类有一个名为 users 的类变量,它在运行时填充 - 这非常有效。

然后我有一个名为 user_timer 的线程函数,它从 user_manager 启动,它管理这些用户并在 X 时间后使它们过期。由于不相关,因此已从本文的上下文中删除。

目前,每次调用 user_timer 时,user_manager.users 的结果都是一个空字典 {},但从该文件外部其他模块可以看到已填充类变量。

我到底做错了什么,为什么会这样?

詹姆斯。

编辑:

调用类的构造函数:

    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

从上面的类调用函数:

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

【问题讨论】:

  • 任何问题,包括“这已从本文的上下文中删除,因为它不相关”。通常意味着相关代码已被删除。我的猜测是您正在使用 multiprocessing 模块,并且对 user_timer 的每次调用都发生在一个新进程中。
  • 好的,我会将代码添加到帖子中 - 但我正在对多处理模块进行 0 次调用...@Duncan 编辑完成。
  • @James 你必须为我们提供足够的代码来重现问题。现在看起来不像你有。
  • @dano 你想看什么?程序的结构有点复杂,需要发布更多的代码。但是,如果有帮助,我可以描述架构吗?我有三个使用队列进行通信的进程。提供的代码是在一个管理网络通信的进程中,user_manager模块是在这个进程中创建的,线程也是在这个进程中创建的。这样可以吗?
  • @James,理想情况下,您会给我们提供在我们自己的机器上重现问题所需的最少代码量。

标签: python multithreading class class-variables


【解决方案1】:

当我在您的代码周围添加足够多的代码以使其运行时,它至少对我有用,因为您已将 datetime 模块与该模块中的 datetime 类混合在一起。

我知道的帮助不多,但我怀疑问题一定出在您发布的代码之外。 user_timer 看到更新到 user_manager.users 就好了:

import threading
import datetime

REFRESH_RATE=10.0
MAX_SECONDS=30

class user:
    def __init__(self, properties):
        self.properties = properties

    def get_first_seen(self):
        return 42

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)


u = user_manager(None, None)
u.add_user("1234", "Properties")
raw_input()

给我这个输出:

C:\temp>c:\python27\python t.py
Test
{'1234': <__main__.user instance at 0x02583A80>}
Exception in thread Thread-1:
Traceback (most recent call last):
  File "c:\python27\lib\threading.py", line 810, in __bootstrap_inner
    self.run()
  File "c:\python27\lib\threading.py", line 763, in run
    self.__target(*self.__args, **self.__kwargs)
  File "t.py", line 55, in user_timer
    difference=datetime.strptime(current_time, format) - datetime.strptime(first_seen[1], format)
AttributeError: 'module' object has no attribute 'strptime'

Traceback (most recent call last):
  File "t.py", line 65, in <module>
    raw_input()
KeyboardInterrupt

【讨论】:

  • 是的,我确定那段代码有错误!由于这个线程错误,我没有机会对其进行测试。但是,在进行了更多测试之后,我可以看到您所看到的。这几乎就像 user_timer 看到的user_manager.users,与其他模块正在读取的完全不同。有什么想法吗?
【解决方案2】:

我通过将其生成为 Process 并使用 manager.Dict() 的共享状态变量来解决此问题!

我认为线程是在生成时复制变量,并且因为它在几乎“独立”的环境中运行,所以类变量没有改变!

谢谢大家。

詹姆斯。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-24
    • 1970-01-01
    • 2011-07-01
    相关资源
    最近更新 更多