【问题标题】:multiprocessinq.Queue as attribute of Queue.Queue childmultiprocessinq.Queue 作为 Queue.Queue 子项的属性
【发布时间】:2014-10-02 19:05:48
【问题描述】:

我试图弄清楚下面的模块在做什么。

import Queue
import multiprocessing
import threading

class BufferedReadQueue(Queue.Queue):
    def __init__(self, lim=None):
        self.raw = multiprocessing.Queue(lim)
        self.__listener = threading.Thread(target=self.listen)
        self.__listener.setDaemon(True)
        self.__listener.start()
        Queue.Queue.__init__(self, lim)

    def listen(self):
        try:
            while True:
                self.put(self.raw.get())
        except:
            pass

    @property
    def buffered(self):
        return self.qsize()

它只在调用代码中实例化一次,.raw 属性 multiprocessing.Queue 被发送到另一个类,该类似乎继承自 multiprocessing.Process

正如我所见,BufferedReadQueue 的一个属性被用作队列,而不是类(也不是它的实例)本身。

BufferedReadQueue 继承自 Queue.Queue 而不仅仅是 object 的原因是什么,如果它实际上没有被用作队列?

【问题讨论】:

    标签: python multithreading queue multiprocessing


    【解决方案1】:

    看起来BufferedReadQueue 旨在用作将multiprocessing.Queue 的读取端转换为普通Queue.Queue 的一种方式。请注意__init__

        self.__listener = threading.Thread(target=self.listen)
        self.__listener.setDaemon(True)
        self.__listener.start()
    

    这会启动一个侦听器线程,它会不断尝试从内部multiprocessing.Queue 获取get 项目,然后将puts 所有这些项目传递给self。看起来用例是这样的:

    def func(queue):
       queue.put('stuff')
       ...
    
    buf_queue = BufferedReadQueue()
    proc = multiprocessing.Process(target=func, args=(buf_queue.raw,))
    proc.start()
    out = buf_queue.get()  # Only get calls in the parent
    

    现在,您为什么要这样做而不是直接使用multiprocessing.Queue?可能是因为multiprocessing.Queue 有一些Queue.Queue 没有的缺点。例如qsize(),这个BufferedReadQueue使用,is not reliable with multiprocessing.Queue

    返回队列的大致大小。由于多线程/多处理语义,这个数字并不可靠。

    请注意,这可能会在未实现 sem_getvalue() 的 Unix 平台(如 Mac OS X)上引发 NotImplementedError

    还可以对Queue.Queue 进行内省,并在不弹出它们的情况下查看其内容。 multiprocessing.Queue 无法做到这一点。

    【讨论】:

    • 我看到.buffered 在某一时刻被调用。我仍然对属性装饰器感到困惑。在这种情况下,.buffered 是否类似于说 self.buffered=self.qsize(),但将其设为只读属性?
    • @MikeiLL 无论出于何种原因,作者决定他们想使用buf_queue.buffered 而不是buf_queue.qsize()。可能是因为对象是对象缓冲区的抽象,而不是对象队列,而buffered 应该理解为“缓冲了多少对象”。或者,他们可能希望将来能够更改 BufferedReadQueue 的内部实现,这可能意味着 buffered 的值不再是 qsize()
    • Queue.Queue.__init__(self, lim) 发生了什么?这是否实质上将Queue.Queue(lim) 的实例分配给BufferedReadQueue 的实例?
    • @MikeiLL 它只是调用父类的构造函数。 BufferedReaderQueueQueue.Queue 的子代,所以它需要从自己的__init__ 中调用Queue.Queue__init__,这样才能正确初始化。它只是标准的面向对象编程。你可能更习惯看到super(BufferedReaderQueue, self).__init__(limt),但我认为Queue.Queue是Python 2.x中的一个老式类,所以你不能使用super
    • 嗯,我不会说我已经习惯了看到这些,但我隐约记得在“Python In a Nutshell”中读过。我今天早些时候(在同一本书中)确实读过 Queue.Queue 是旧式类。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-28
    • 2017-10-17
    • 2018-07-25
    • 2012-01-02
    • 1970-01-01
    • 2018-04-13
    • 1970-01-01
    相关资源
    最近更新 更多