如何在不使用队列的情况下将字典传递给可以在外部更改的Python线程
我想在我的多个线程之间共享一个字典,但不想使用队列。我之前是通过创建一个包含对象的线程来实现的,但现在我想只用对象中的一个函数来创建线程,而不是使用整个对象。我的简化代码如下:
#!/usr/bin/python
import threading
import time
class WebSocket(threading.Thread):
def __init__(self, server=1, sock=1, address=1):
self.s1=server
self.s2=sock
self.s3=address
print "salam"
def CheckThread(self):
self.a={'1':1, '2':2}
s=threading.Thread(target=self.SockFun, kwargs=self.a)
s.deamon=True
s.start()
while(1):
self.a['1']=self.a['1']+1
time.sleep(1)
def SockFun(self,**kwargs):
pass
class SimpleEcho(WebSocket):
def SockFun(self,**kwargs):
while(1):
print kwargs
time.sleep(1)
def handleMessage(self):
self.CheckThread()
s=SimpleEcho()
s.handleMessage()
我在线程中打印的字典元素 '1' 的值并没有像我预期的那样增加:
3 个回答
1
使用 kwargs
这个机制会把字典里的元素复制到 SimpleEcho
里面。一旦复制过去了,原来的内容再怎么改也不会影响到打印出来的结果。想要快速验证这一点,可以把 print kwargs
改成 print self.a
来看看。
另外,你可以把 kwargs=self.a
改成 kwargs={"argh":self.a}
。这样做的话,kwargs
还是会被复制,但这个复制的内容会包含对原始 self.a
的引用。
还有,你是不是应该使用某种锁定机制呢?
1
当你使用 **
这种写法时,字典会被复制,这就是为什么你不能那样做的原因。
>>> foo = {'bar': 'baz'}
>>> def spam(**kwargs):
... print(kwargs is foo)
...
>>> spam(**foo)
False
你需要使用一个可变类型,比如列表,作为字典中的一个项(你可以这样做,因为复制的是浅拷贝:它只复制字典本身,而不复制里面的内容)。
>>> import time
>>> import threading
>>> def spam(**kwargs):
... while True:
... time.sleep(10)
... print(kwargs['bar'][0])
...
>>> foo = {'bar': ['baz']}
>>> threading.Thread(target=spam, kwargs=foo).start()
>>> baz
>>> foo['bar'][0] = 'qux'
>>> qux
qux
qux
1
这不是线程问题。当你通过关键字参数(kwargs)传递self.a这个字典时,它并不是通过引用传递的,而是被复制了一份。
>>> mydict = {'foo': 'bar'}
>>> def func(**kwargs):
... kwargs['hi'] = 'mom'
...
>>> func(**mydict)
>>> print mydict
{'foo': 'bar'}