我的最终目标是将
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
我有两个问题:
>>> 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”)创建正确的上下文,您可以将其传递到您的队列。