Python 是否可以手动锁定/解锁队列?

Python 是否可以手动锁定/解锁队列?,python,multiprocessing,Python,Multiprocessing,我很好奇是否有办法手动锁定多处理.Queue对象 我建立了一个非常标准的生产者/消费者模式,在这个模式中,我的主线程不断地生成一系列值,并且有一个多处理池。进程工作者根据生成的值进行操作 它都是通过一个单独的多处理.Queue()控制的 但是,由于该程序的古怪特性,我想将队列中的所有内容转储到一个文件中,以供以后处理。但是如果不能临时锁定队列,工人就无法消费队列中的所有内容,因为制作人不断地用垃圾填充队列——不管从概念上讲是这样。经过多次测试后,似乎有一个锁在某个点上获胜(但通常是添加到队列中的

我很好奇是否有办法手动锁定
多处理.Queue
对象

我建立了一个非常标准的生产者/消费者模式,在这个模式中,我的主线程不断地生成一系列值,并且有一个
多处理池。进程
工作者根据生成的值进行操作

它都是通过一个单独的
多处理.Queue()
控制的

但是,由于该程序的古怪特性,我想将队列中的所有内容转储到一个文件中,以供以后处理。但是如果不能临时锁定队列,工人就无法消费队列中的所有内容,因为制作人不断地用垃圾填充队列——不管从概念上讲是这样。经过多次测试后,似乎有一个锁在某个点上获胜(但通常是添加到队列中的锁)

编辑:而且,我意识到可以简单地停止制作人并从该线程消费它。。。但这让我心中的单一责任者感到悲伤,因为制作人是制作人,而不是消费者

编辑: 在查看了
队列的源代码之后,我得出了以下结论:

def dump_queue(q):
    q._rlock.acquire()
    try:
        res = []
        while not q.empty():
            res.append(q._recv())
            q._sem.release()
        return res
    finally:
        q._rlock.release()    
然而,我太害怕了,不敢使用它!我不知道这是否“正确”。我没有足够的把握,不知道在不炸毁任何
Queue
s内部结构的情况下,这是否能维持下去


有人知道这会不会破裂吗?:)

根据评论中所说的,队列对于您的问题来说只是一个错误的数据结构,但可能是可用解决方案的一部分

听起来你只有一个制片人。创建一个新的生产者本地(不是跨流程共享)类,实现您真正需要的语义。比如说,

class FlushingQueue:
    def __init__(self, mpqueue, path_to_spill_file, maxsize=1000, dumpsize=1000000):
        from collections import deque
        self.q = mpqueue  # a shared `multiprocessing.Queue`
        self.dump_path = path_to_spill_file
        self.maxsize = maxsize
        self.dumpsize = dumpsize
        self.d = deque()  # buffer for overflowing values

    def put(self, item):
        if self.q.qsize() < self.maxsize:
            self.q.put(item)
            # in case consumers have made real progress
            while self.d and self.q.qsize() < self.maxsize:
                self.q.put(self.d.popleft())
        else:
            self.d.append(item)
            if len(self.d) >= self.dumpsize:
                self.dump()

    def dump(self):
        # code to flush self.d to the spill file; no
        # need to look at self.q at all
class FlushingQueue:
def uuu init uuuu(self,mpqueue,路径到溢出文件,maxsize=1000,dumpsize=1000000):
从集合导入deque
self.q=mpqueue#一个共享的`多处理.Queue`
self.dump\u path=指向溢出文件的路径
self.maxsize=maxsize
self.dumpsize=dumpsize
self.d=deque()#溢出值缓冲区
def放置(自身,项目):
如果self.q.qsize()=self.dumpsize:
self.dump()
def转储(自):
#将self.d刷新到溢出文件的代码;不
#需要看看self.q

我打赌你能做到这一点:-)

你能用
多处理.Queue
的maxsize参数限制一次队列中可以有多少个项目吗?@AustinPhillips不幸的是,不能。这并不能完全解决问题。因为生产者正在从流中读取数据以生成其值,所以我希望尽可能长时间地保持它的“运行”。如果消费者在处理过程中落后,我宁愿快速地将队列转储到光盘上,然后再进行处理,而不是阻止制作者读取其输入源。也许你真的不需要这样锁定队列。只需添加另一个消费者,其工作就是将队列保持在合理水平。它可以轮询
queue.qsize()
,如果它变得太大,则使用队列中的项目并将其存储到文件中。没有记录在案的方法来锁定
mp.queue
——但即使有,它又有什么用呢?当它被锁定时,任何进程都无法从中取出项目。
def dump_queue(q):
    q._rlock.acquire()
    try:
        res = []
        while not q.empty():
            res.append(q._recv())
            q._sem.release()
        return res
    finally:
        q._rlock.release()    
class FlushingQueue:
    def __init__(self, mpqueue, path_to_spill_file, maxsize=1000, dumpsize=1000000):
        from collections import deque
        self.q = mpqueue  # a shared `multiprocessing.Queue`
        self.dump_path = path_to_spill_file
        self.maxsize = maxsize
        self.dumpsize = dumpsize
        self.d = deque()  # buffer for overflowing values

    def put(self, item):
        if self.q.qsize() < self.maxsize:
            self.q.put(item)
            # in case consumers have made real progress
            while self.d and self.q.qsize() < self.maxsize:
                self.q.put(self.d.popleft())
        else:
            self.d.append(item)
            if len(self.d) >= self.dumpsize:
                self.dump()

    def dump(self):
        # code to flush self.d to the spill file; no
        # need to look at self.q at all