Python多进程Queue的put()行为

9

我正在使用多进程做一些非常简单的事情:

data = {'a': 1}
queue.put(data, True)
data.clear()

当我在另一个进程(使用get()方法)中使用队列时,我获得一个空字典。如果我删除data.clear(),则会按预期获取键。是否有一种方法可以等待put()完成序列化?

2个回答

12

实际上,这被认为是一种特性而不是问题。队列立即返回,因此在序列化发生时您的进程将继续进行,以避免所谓的“队列争用"。

我建议你有两个选择:

  1. 你是否确信首先需要可变字典?为了避免创建防御性副本,你可以尝试创建一个新的字典而不是使用 dict.clear(),让垃圾回收器处理旧字典。

  2. 自己封装数据; 也就是说:a_queue.put(pickle.dumps(data))pickle.loads(a_queue.get())。现在,如果你在 put 后立即执行 data.clear() ,数据已经由你自己序列化了。

从并行编程的角度来看,第一种方法(将数据视为不可变)更加可行和干净,但我不确定你是否必须清除你的字典。


1
谢谢你的回答,选项1绝对是最优雅的选择,因为复制数据所需的时间远远大于创建新字典并让GC处理它的时间。 - Tarantula
这真的是 Python 中一个“这不是错误,而是特性!”时刻。 - Rares Dima
1
我谨虚心地不同意。如果我把数据交给你,而你之后需要访问它,那么复制数据就是你的责任。至少现在我知道了出了什么问题。 - Aaron D. Marasco

4

最好的方法可能是在发送数据之前先复制一份data。尝试使用以下代码:

data = {'a': 1}
dc = data.copy()
queue.put(dc)
data.clear()

基本上,您不能指望发送完成之前字典被清除,因此不应该尝试。当dc超出范围或代码再次执行时,它将被垃圾回收。

这是我现在的解决方法,但我不想要额外的副本来确保序列化会在正确的时刻发生。 - Tarantula

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接