我目前正在编程一个基于python的数据报服务器使用线程和所有这些。Python:'thread._local对象没有属性'todo'
我遇到了以下问题:我正在使用多个分配线程将传入的包分配给不同的处理线程。在处理线程中,我使用threading.local()跟踪线程局部变量。
我目前正在测试我的服务器在高负载(大约2秒内2000个数据包)期间的反应,并且出现了local() - Object的奇怪行为。
好像它工作得很好了一会儿,然后,在某些时候,它抛出一个异常:
Exception in thread 192.168.1.102: # <-- This is the Processing Thread
Traceback (most recent call last):
File "/opt/lib/python2.7/threading.py", line 552, in __bootstrap_inner
self.run()
File "/volume1/home/Max/Python/MyThread/pyProcThread.py", line 37, in run
print self.loc.father
AttributeError: 'thread._local' object has no attribute 'father'
# The following three lines are debug
# This is the Allocation thread that has called the Processing thread
<Thread(192.168.1.102, started 1106023568)>
# This confirms that the queue it tries to access exists
<Queue.Queue instance at 0x40662b48>
# This is the Processing thread, which has stopped executing on exception
<Thread(192.168.1.102, stopped 1106023568)>
Exception in thread pyAlloc-0: # <-- This is the Allocation thread
Traceback (most recent call last):
File "/opt/lib/python2.7/threading.py", line 552, in __bootstrap_inner
self.run()
File "/volume1/home/Max/Python/MyThread/pyAllocThread.py", line 60, in run
foundThread.addTask(str(data))
File "/volume1/home/Max/Python/MyThread/pyProcThread.py", line 58, in addTask
print self.loc.todo
AttributeError: 'thread._local' object has no attribute 'todo'
处理线程
# Imports
import threading
import time
import Queue
class Thread(threading.Thread):
def __init__(self,pThread):
threading.Thread.__init__(self)
self.loc = threading.local()
self.loc.todo = Queue.Queue()
self.loc.father = pThread
print "Konstruktor ausgefuehrt"
print self.loc.todo
def run(self):
self.loc.run = True;
print self.loc.father
while (self.loc.run):
try:
task = self.loc.todo.get(True, 1)
print "processing..."
if(task == self):
self.loc.run=False
else:
print task
except Queue.Empty:
pass
self.loc.father.threadTerminated(self)
print self.name, "terminating..."
def addTask(self, pTask):
print self
print self.loc.todo
self.loc.todo.put(pTask)
而分配的一部分线程:
import threading
import pyProcThread # My processing Thread
import Queue
import time
class Thread(threading.Thread):
# Lock-Objects
threadListLock = threading.Lock()
waitListLock = threading.Lock()
alive = True;
taskQueue = Queue.Queue()
# Lists
# List of all running threads
threads = []
def threadExists(self,pIP):
"""Checks if there is already a thread with the given Name"""
for x in self.threads:
if x.name == pIP:
return x
return None
def threadTerminated(self,pThread):
"""Called when a Processing Thread terminates"""
with self.threadListLock:
self.threads.remove(pThread)
print "Thread removed"
def threadRegistered(self,pThread):
"""Registers a new Thread"""
self.threads.append(pThread)
def killThread(self):
self.alive = False
def run(self):
while(self.alive):
# print "Verarbeite Nachricht ", self.Message
# print "Von ", self.IP
try:
data, addtemp = self.taskQueue.get(True, 1)
addr, _junk = addtemp
with self.threadListLock:
foundThread=self.threadExists(str(addr))
# print "Thread " + self.name + " verarbeitet " + data
if (foundThread!=None):
#print "recycling thread"
foundThread.addTask(str(data))
else:
print "running new Thread"
t = pyProcThread.Thread(self)
t.name = str(addr)
t.addTask(str(data))
t.start()
self.threadRegistered(t)
self.taskQueue.task_done()
except Queue.Empty:
pass
print self.name, "terminating..."
with self.threadListLock:
for thread in self.threads:
thread.addTask(thread)
全输出,包括所有调试打印的:
running new Thread
Konstruktor ausgefuehrt
<Queue.Queue instance at 0x40662b48>
<Thread(192.168.1.102, initial)>
<Queue.Queue instance at 0x40662b48>
<Thread(192.168.1.102, started 1106023568)>
<Queue.Queue instance at 0x40662b48>
<Thread(192.168.1.102, started 1106023568)>
<Queue.Queue instance at 0x40662b48>
<Thread(192.168.1.102, started 1106023568)>
<Queue.Queue instance at 0x40662b48>
<Thread(192.168.1.102, started 1106023568)>
<Queue.Queue instance at 0x40662b48>
<Thread(192.168.1.102, started 1106023568)>
<Queue.Queue instance at 0x40662b48>
<Thread(192.168.1.102, started 1106023568)>
<Queue.Queue instance at 0x40662b48>
<Thread(192.168.1.102, started 1106023568)>
<Queue.Queue instance at 0x40662b48>
Exception in thread 192.168.1.102:
Traceback (most recent call last):
File "/opt/lib/python2.7/threading.py", line 552, in __bootstrap_inner
self.run()
File "/volume1/home/Max/Python/MyThread/pyProcThread.py", line 37, in run
print self.loc.father
AttributeError: 'thread._local' object has no attribute 'father'
<Thread(192.168.1.102, started 1106023568)>
<Queue.Queue instance at 0x40662b48>
<Thread(192.168.1.102, stopped 1106023568)>
Exception in thread pyAlloc-0:
Traceback (most recent call last):
File "/opt/lib/python2.7/threading.py", line 552, in __bootstrap_inner
self.run()
File "/volume1/home/Max/Python/MyThread/pyAllocThread.py", line 60, in run
foundThread.addTask(str(data))
File "/volume1/home/Max/Python/MyThread/pyProcThread.py", line 58, in addTask
print self.loc.todo
AttributeError: 'thread._local' object has no attribute 'todo'
Terminating main
192.168.1.102
DEINEMUDDA sent to 192.168.1.102 : 8082
pyAlloc-1 terminating...
<Thread(192.168.1.102, stopped 1106023568)>
<Queue.Queue instance at 0x40662b48>
正如你可以在日志中看到,一切似乎都很好地工作了一段时间,但它从来没有达到在加工螺纹的主要功能print "processing
。
我已经搜索了网络和StackOverflow的类似问题,但无法找到任何。预先感谢任何帮助,并且原谅我的编码风格,我现在只编程Python几天,仍然学习它的一些功能。
编辑:当然,这个服务器比这更多。有一个主线程正在接收数据包并将它们发送到分配线程以及后台的其他一些东西。另外,服务器远没有完成,但我想在开始其他事情之前让接收工作。
这很有趣,谢谢。如果我删除'print self.loc.parent',他也有'self.loc.todo'问题。我想这有同样的道理。我怎样才能做到这一点(将'parent'和'todo'属性放入'loc'中,这两个属性都可以在处理线程中访问)?是否有一个python帮助页面详细解释了这个整个机制?再次感谢。 – malexmave 2012-02-25 18:37:48
您可以将值设置为'Thread'对象的常规属性,所以'self.father = pThread'。我相信父不是执行线程特定的,而是线程实例特定的。 – 2012-02-25 18:40:18
呃,那实际上是我的工作解决方案,我试图用本地对象“正确”。但是因为它看起来像是“自我”。属性'似乎是正确的方式,我可以继续使用它(它感觉像是一个肮脏的解决方法,因为我第一次尝试时无法让本地对象工作)。再次感谢。 – malexmave 2012-02-25 18:43:42