无法在 Python 3.5 中子类化多处理队列

问题描述 投票:0回答:1

我的最终目标是将

stdout
从几个子进程重定向到一些队列,并将它们打印在某个地方(也许在一个小 GUI 中)。

第一步是将

Queue
子类化为一个行为与
stdout
非常相似的对象。但这就是我陷入困境的地方。在 Python v3.5 中子类化多处理
Queue
似乎是不可能的。

# This is a Queue that behaves like stdout
# Unfortunately, doesn't work in Python 3.5   :-(
class StdoutQueue(Queue):
    def __init__(self,*args,**kwargs):
        Queue.__init__(self,*args,**kwargs, ctx='')

    def write(self,msg):
        self.put(msg)

    def flush(self):
        sys.__stdout__.flush()

我在下面的帖子中找到了这个片段(可能当时 Python 3.5 还不存在):Python multiprocessing 将子进程的 stdout 重定向到 Tkinter Text

在 Python v3.5 中,当对 multiprocessing

Queue
类进行子类化时,您会偶然发现奇怪的错误消息。我发现了两个描述该问题的错误报告:

https://bugs.python.org/issue21367

https://bugs.python.org/issue19895

我有两个问题:

  1. 假设我想坚持使用 Python v3.5 - 转到以前的版本并不是一个真正的选择。我可以使用什么解决方法来以某种方式子类化多处理队列?
  2. 如果我升级到Python v3.6,这个bug还存在吗?
python python-3.x multiprocessing python-multiprocessing
1个回答
12
投票
>>> import multiprocessing
>>> type(multiprocessing.Queue)
<class 'method'>
AttributeError: module 'multiprocessing' has no attribute 'queues'
>>> import multiprocessing.queues
>>> type(multiprocessing.queues.Queue)
<class 'type'>

所以正如你所看到的

multiprocessing.Queue
只是
multiprocessing.queues.Queue
类的构造函数方法。如果你想开设儿童班,就做
class MyQueue(multiprocessing.queues.Queue)

您可以在此处查看此方法的来源

正如您在上面的链接中看到的,

multiprocessing.Queue
ctx
参数传递给队列。所以我自己用
__init__
方法让它工作起来。我不完全理解
BaseContext
对象应该在哪里获得
_name
属性,所以我手动传递了它。

def __init__(self,*args,**kwargs):
    from multiprocessing.context import BaseContext
    ctx = BaseContext()
    ctx._name = "Name"
    super(StdoutQueue,self).__init__(*args,**kwargs, ctx=ctx)

事实证明文档有一些有关上下文的信息这里。因此,您可以这样做,而不是像我一样手动创建它

import multiprocessing
ctx = multiprocessing.get_context()

它将使用

_name
设置(在您的特定情况下为“fork”)创建正确的上下文,您可以将其传递到您的队列。

© www.soinside.com 2019 - 2024. All rights reserved.