仅字典队列

Queue of dicts only

我正在编写一个套接字服务器,它在请求时将服务器状态传递给客户端。状态作为 JSON 传递,但在服务器中,数据存储在字典中。当客户端请求服务器状态时,socketserver 处理程序从队列中拉取服务器状态(服务器在线程中运行)。

我的问题是,当我从队列中取出时,我总是只得到最后一个队列条目。当我从队列中提取条目时,我可以看到队列大小在减少。这是一个非常简单的脚本来说明这个问题:

import queue

appState = {"console" : {"message" : "NA"}}

appStateQueue = queue.Queue()

print("Putting dict data on the queue:")
for i in range(10):
        appState["console"]["message"] = str(i)
        print(appState) 
        appStateQueue.put_nowait(appState)

print("Queue size:", appStateQueue.qsize())

print("Getting dict data from the queue:")
for i in range(10):
        print(appStateQueue.get(), appStateQueue.qsize())

print("Putting integer data on the queue:")
for i in range(10):
        appState = i
        print(appState)
        appStateQueue.put_nowait(appState)

print("Queue size:", appStateQueue.qsize())

print("Getting integer data from the queue:")
for i in range(10):
        print(appStateQueue.get(), appStateQueue.qsize())

输出结果如下:

Putting dict data on the queue:
{'console': {'message': '0'}}
{'console': {'message': '1'}}
{'console': {'message': '2'}}
{'console': {'message': '3'}}
{'console': {'message': '4'}}
{'console': {'message': '5'}}
{'console': {'message': '6'}}
{'console': {'message': '7'}}
{'console': {'message': '8'}}
{'console': {'message': '9'}}
Queue size: 10
Getting dict data from the queue:
{'console': {'message': '9'}} 9
{'console': {'message': '9'}} 8
{'console': {'message': '9'}} 7
{'console': {'message': '9'}} 6
{'console': {'message': '9'}} 5
{'console': {'message': '9'}} 4
{'console': {'message': '9'}} 3
{'console': {'message': '9'}} 2
{'console': {'message': '9'}} 1
{'console': {'message': '9'}} 0
Putting integer data on the queue:
0
1
2
3
4
5
6
7
8
9
Queue size: 10
Getting integer data from the queue:
0 9
1 8
2 7
3 6
4 5
5 4
6 3
7 2
8 1
9 0

请注意队列中的字典数据如何始终相同。它总是放在队列中的最后一个数据。整数数据的行为符合我的预期。字符串也可以,虽然我没有在这里显示。

这是怎么回事?

因为,我看到您没有创建新的字典,而只是更改现有字典变量的值。通过下面的代码片段可以很容易地理解这一点,

>>> appState = {"console" : {"message" : "NA"}}
>>> appState
{'console': {'message': 'NA'}}

>>> appState_copy = appState
>>> appState_copy["console"]["message"] = 23

>>> appState
{'console': {'message': 23}}
>>> appState_copy
{'console': {'message': 23}}

Python 仅在将 dict 分配给新变量时复制引用,因此当您在每次迭代中分配整数时,实际上是在更改同一个 dict 的值而不是创建新变量一.

由于您使用的是嵌套字典,因此您需要使用复制模块中的 deepcopy 方法来完成这项工作。

这是一个可行的解决方案:

import queue
import copy #added import statememt

appState = {"console" : {"message" : "NA"}}

appStateQueue = queue.Queue()

print("Putting dict data on the queue:")
for i in range(10):
        new_appState = copy.deepcopy(appState) #creating a copy of dict every iteration
        new_appState["console"]["message"] = str(i)
        print(new_appState) 
        appStateQueue.put_nowait(new_appState) #putting the created copy in the queue

print("Queue size:", appStateQueue.qsize())

print("Getting dict data from the queue:")
for i in range(10):
        print(appStateQueue.get(), appStateQueue.qsize())

print("Putting integer data on the queue:")
for i in range(10):
        appState = i
        print(appState)
        appStateQueue.put_nowait(appState)

print("Queue size:", appStateQueue.qsize())

print("Getting integer data from the queue:")
for i in range(10):
        print(appStateQueue.get(), appStateQueue.qsize())