【问题标题】:is Queue empty method broken?队列空方法是否损坏?
【发布时间】:2020-08-14 21:45:58
【问题描述】:

如何检查队列是否为空?运行以下代码:

from multiprocessing import Queue

q = Queue()
print(q.empty())

q.put("a")
print(q.empty())

渲染:

True
True

在添加元素后,q.empty() 是否应该返回 False

【问题讨论】:

  • 我猜put 是异步的,所以你不能保证它会在下一行执行时完成。
  • 它是异步的,让它休眠2秒然后再次检查q.empty()
  • @MZ 是的,在添加元素后使用 time.sleep(1) 在空检查时返回 False。我会发布一个简短的答案还是你会?

标签: python python-multiprocessing


【解决方案1】:

两种可能的解决方案:

  1. 使用queue.Queue 而不是multiprocessing.Queue: 他们之间的一些differences in doc

它们的不同之处在于 Queue 缺少 Python 2.5 的 queue.Queue 类中引入的 task_done() 和 join() 方法。

from queue import Queue
q = Queue()
print(q.empty())
q.put("a")
print(q.empty())
  1. 或者就像@Hans Musgrave 在评论中所说的那样。time.sleep(1) 不能保证。您可以改用time.sleep(0)
from multiprocessing import Queue
import time
q = Queue()
print(q.empty())
time.sleep(0)
q.put("a")
print(q.empty())

他们都给我:

True
False

关于为什么sleep(0)零值会导致线程将其时间片的剩余部分交给任何其他准备运行的线程。如果没有其他线程准备运行,则函数立即返回,线程继续执行 cpu放弃资源,去执行q.emety()任务。我是这么想的。

稳定的方法是使用queue.Queuequeues.SimpleQueue

【讨论】:

【解决方案2】:

官方推荐的解决方案是使用Manager.Queue

引用Python docs

注意:
当一个对象被放入队列时,该对象被腌制并且后台线程稍后将腌制数据刷新到底层管道。这会产生一些令人惊讶的后果,但不会造成任何实际困难——如果它们真的困扰您,那么您可以改用由经理创建的队列。
1. 将对象放入空队列后,队列的 empty() 方法返回 False 和 get_nowait() 可以在不引发 Queue.Empty 的情况下返回。
2. 如果多个进程正在对对象进行排队,则对象可能在另一端被乱序接收。但是,由同一进程排队的对象将始终按照彼此的预期顺序排列。

【讨论】:

    【解决方案3】:

    put 方法是异步的,因此在检查元素时队列可能仍然是空的。在putempty() 之后添加time.sleep(1) 将返回False

    【讨论】:

    • 添加time.sleep(1) 可能为添加元素提供了足够的时间。这不能保证。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-13
    • 1970-01-01
    • 2012-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多