Python:'thread._local 对象没有属性'todo' [英] Python: 'thread._local object has no attribute 'todo'

查看:61
本文介绍了Python:'thread._local 对象没有属性'todo'的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在使用线程和所有这些编程基于 python 的数据报服务器.

I am currently programming a python-based datagram-Server using threads and all of that.

我遇到了以下问题:我使用多个分配线程将传入的包分配给不同的处理线程.在处理线程中,我使用 threading.local() 来跟踪线程局部变量.

I encountered the following problem: I am using multiple Allocation Threads to allocate incoming packages to the different processing threads. Inside the Processing Threads, I am using threading.local() to keep track of thread-local variables.

我目前正在测试我的服务器在高负载(约 2 秒内 2000 个数据包)期间的反应,并且发现了 local()-Object 的奇怪行为.

I am currently testing how my server reacts during high load (2000 Packets in ~2 seconds), and have come upon a strange behaviour of the local()-Object.

它似乎可以正常工作一段时间,然后在某些时候抛出异常:

It seems like it works just fine for a while, and then, at some point, it throws an exception:

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)

完整输出,包括所有调试打印:

The full output, including all debug print's:

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",但在一段时间内似乎一切正常.

As you can see in the log, everything seems to work fine for a while, although it never reaches the print "processing in the main function of the processing thread.

我在网络和 StackOverflow 上搜索过类似的问题,但没有找到.在此先感谢您的任何帮助,请原谅我的编码风格,我现在只编写 Python 几天,仍在学习它的一些功能.

I have searched the web and StackOverflow for similar problems, but was unable to find any. Thanks in advance for any help, and excuse my coding style, I'm only programming Python for a few days now and still learning the ropes with some of its features.

当然,这个服务器还有更多的东西.有一个主线程正在接收数据包并将它们发送到分配线程,还有一堆其他的东西在后台.此外,服务器还远未完成,但我想在开始其他事情之前让接收工作.

Of course, there is more to this Server than this. There is a main thread that is receiving the packets and sending them to the allocation thread, and a bunch of other stuff in the background. Additionally, the Server is far from done, but I want to get the receiving working before I start on other things.

推荐答案

threading.local 是表示线程本地数据的类.线程本地数据是其值特定于线程的数据,因此仅可用于本地 线程(创建local() 对象的线程).换句话说,只有设置该值的线程才能看到该值.

threading.local is class that represents thread-local data. Thread-local data are data whose values are thread specific and thus available for local thread only (the thread that created local() object). In other words only the thread that set the value sees the value.

因为您在处理线程的 __init__ 方法中设置了 loc.parent 值,但在分配器线程内执行,因此处理线程的线程局部变量将仅可用在分配器线程中.所以它不会在处理线程的 run() 中工作,因为它将被不同的线程(而不是分配器)执行.

Because you set the loc.parent value in __init__ method of your processing thread, but executed inside the allocator thread, the thread locals of proccessing threads will be available only in the allocator thread. So it won't work in the run() of processing thread, as it will be executed by different thread (not the allocator).

这篇关于Python:'thread._local 对象没有属性'todo'的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆