【问题标题】:Queue of dicts only仅字典队列
【发布时间】:2020-09-10 13:18:25
【问题描述】:

我正在编写一个套接字服务器,它在请求时将服务器状态传递给客户端。状态作为 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

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

这是怎么回事?

【问题讨论】:

    标签: python-3.x dictionary queue


    【解决方案1】:

    正如我看到的,您并没有创建新的 dict,而只是更改了现有 dict 变量的值。这可以通过下面的sn-p代码很容易理解,

    >>> 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())
    

    【讨论】:

    • 这就是答案,布维。没有意识到字典是通过引用复制的。在放入队列之前转换为 JSON 也可以。这就是我要做的。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2021-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-09
    • 2017-04-17
    • 1970-01-01
    相关资源
    最近更新 更多