1

궁극적 인 목표는 stdout을 여러 서브 프로세스에서 일부 대기열로 리디렉션하고 어딘가에 (어쩌면 작은 GUI로) 인쇄하는 것입니다.파이썬 3.5에서 멀티 프로세싱 대기열을 서브 클래스화할 수 없다

첫 번째 단계는 Queuestdout과 매우 유사한 개체로 하위 클래스 화하는 것입니다. 그러나 그것이 내가 붙어있는 곳이다. 다중 처리 Queue을 서브 클래 싱하는 것은 파이썬 v3.5에서는 불가능한 것처럼 보입니다. 멀티 프로세싱 Queue 클래스를 서브 클래스 때 Python multiprocessing redirect stdout of a child process to a Tkinter Text

파이썬 V3.5에서 당신이 이상한 오류 메시지에 우연히 발견 :

# 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() 

나는 (아직 그 순간에 존재하지 않았다 아마 파이썬 3.5) 다음 게시물이 조각을 발견 . - 이전 버전에가는

  1. 은 가정하자 내가 파이썬 V3.5에 충실하려는 : 나는이 개 질문이

    https://bugs.python.org/issue21367

    https://bugs.python.org/issue19895

    : 나는이 문제를 설명하는 두 개의 버그 리포트를 발견 정말 옵션이 아닙니다. 다중 처리 대기열을 어떻게 든 서브 클래 싱하는 데 사용할 수있는 해결 방법은 무엇입니까?

  2. 파이썬 v3.6으로 업그레이드해도 여전히 버그가 있습니까?

편집 :

from multiprocessing import Queue # <- known issue: you cannot subclass 
            # this Queue class, because it is 
            # not a genuine python class. 

그러나 다음과 같은 작동합니다 : 당신이 여기에있는 Queue 클래스를 서브 클래 싱 할 때

알려진 문제가

from multiprocessing.queues import Queue # <- from this Queue class, you 
              # should be able to make a 
              # subclass. But Python 3.5 
              # refuses :-(

슬프게도 파이썬 v3.5에서는 작동하지 않습니다. 다음과 같은 오류가 발생합니다 :

C:\Users\..\myFolder > python myTest.py 

     Traceback (most recent call last): 
      File "myTest.py", line 49, in <module> 
       q = StdoutQueue() 
      File "myTest.py", line 22, in __init__ 
       super(StdoutQueue,self).__init__(*args,**kwargs) 
     TypeError: __init__() missing 1 required keyword-only argument: 'ctx' 

편집 :

문제를 해결하기 위해 당신에게 다스 Kotik 감사합니다! 그의 솔루션으로 업데이트 된 완전한 코드가 있습니다. 이제 작동합니다.

import sys 
import time 
import multiprocessing as mp 
import multiprocessing.queues as mpq 
from threading import Thread 
from tkinter import * 

'''-------------------------------------------------------------------''' 
'''    SUBCLASSING THE MULTIPROCESSING QUEUE    ''' 
'''                 ''' 
'''   ..and make it behave as a general stdout io    ''' 
'''-------------------------------------------------------------------''' 
# The StdoutQueue is a Queue that behaves like stdout. 
# We will subclass the Queue class from the multiprocessing package 
# and give it the typical stdout functions. 
# 
# (1) First issue 
# Subclassing multiprocessing.Queue or multiprocessing.SimpleQueue 
# will not work, because these classes are not genuine 
# python classes. 
# Therefore, you need to subclass multiprocessing.queues.Queue or 
# multiprocessing.queues.SimpleQueue . This issue is known, and is not 
# the reason for asking this question. But I mention it here, for 
# completeness. 
# 
# (2) Second issue 
# There is another problem that arises only in Python V5 (and beyond). 
# When subclassing multiprocessing.queues.Queue, you have to provide 
# a 'multiprocessing context'. Not doing that, leads to an obscure error 
# message, which is in fact the main topic of this question. Darth Kotik 
# solved it. 
# His solution is visible in this code: 
class StdoutQueue(mpq.Queue): 

    def __init__(self,*args,**kwargs): 
     ctx = mp.get_context() 
     super(StdoutQueue, self).__init__(*args, **kwargs, ctx=ctx) 

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

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


'''-------------------------------------------------------------------''' 
'''       TEST SETUP        ''' 
'''-------------------------------------------------------------------''' 

# This function takes the text widget and a queue as inputs. 
# It functions by waiting on new data entering the queue, when it 
# finds new data it will insert it into the text widget. 
def text_catcher(text_widget,queue): 
    while True: 
     text_widget.insert(END, queue.get()) 

def test_child(q): 
    # This line only redirects stdout inside the current process 
    sys.stdout = q 
    # or sys.stdout = sys.__stdout__ if you want to print the child to the terminal 
    print('child running') 

def test_parent(q): 
    # Again this only redirects inside the current (main) process 
    # commenting this like out will cause only the child to write to the widget 
    sys.stdout = q 
    print('parent running') 
    time.sleep(0.5) 
    mp.Process(target=test_child,args=(q,)).start() 

if __name__ == '__main__': 
    gui_root = Tk() 
    gui_txt = Text(gui_root) 
    gui_txt.pack() 
    q = StdoutQueue() 
    gui_btn = Button(gui_root, text='Test', command=lambda:test_parent(q),) 
    gui_btn.pack() 

    # Instantiate and start the text monitor 
    monitor = Thread(target=text_catcher,args=(gui_txt,q)) 
    monitor.daemon = True 
    monitor.start() 

    gui_root.mainloop() 
+0

동일한 문제가있는 것 같습니다. http://stackoverflow.com/questions/24941359/ctx-parameter-in-multiprocessingqueue –

+0

안녕하세요 @BiRico, 정말 고마워요. 불행히도, 그것은 같은 문제가 아닙니다. 이 게시물에서 설명한 문제는 Queue 객체를 인스턴스화하는 것에 관한 것입니다. Queue를 서브 클래 싱하는 문제는 언급되거나 설명되지 않습니다. –

+0

파이썬 3.5.2에서 하위 클래스를 만들 수 있었지만 큐를 아직 종료 할 수 없습니다. –

답변

3
>>> 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 클래스 만 생성자 방법이다. 좋아요 :이 방법 here

편집의 소스를 볼 수 있습니다 당신은 자식 클래스를 확인하려면 단지 class MyQueue(multiprocessing.queues.Queue)

를 않습니다. 이제 문제가 생겼어. 위의 링크에서 볼 수 있듯이 multiprocessing.Queuectx 인수를 대기열에 전달합니다.그래서 나는 그것을 __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) 

EDIT2 : 밖으로 켜지고 문서는 상황 here에 대한 몇 가지 정보가 있습니다. 그래서 대신 수동으로 내가 그랬던 것처럼 당신이

import multiprocessing 
ctx = multiprocessing.get_context() 

그것은 (특정 경우에 '포크'에) _name 세트로 적절한 컨텍스트를 만듭니다 할 수있는 그것을 만들고 당신은 당신의 큐에 전달할 수 있습니다.

+0

두 방법 (multiprocessing.Queue 및 multiprocessing.queue.Queue)을 시도했지만 아무 것도 작동하지 않습니다. –

+0

안녕하세요 @Darth Kotik, 내 질문에 편집을 추가했습니다. 전체 예제와 자세한 오류 메시지가 표시됩니다. Python 3.5에서 작업합니까? 오류를 재현 할 수 있다면 좋을 것입니다 :-) –

+0

고마워요! 나는 그것을 시험해보고 효과가 있다면 알려주지 : –

관련 문제