2016-10-21 5 views
0

이 Q QCoreApplication 문제가 발생했습니다. QObject가 QThread 내에서 실행을 마친 후에 input()을 호출하면 "QCoreApplication :: exec : 이벤트 루프가 이미 실행 중입니다"라는 콘솔에 무한 루프가 인쇄됩니다.input()이 "QCoreApplication :: exec : 이벤트 루프가 이미 실행 중"인 이유는 무엇입니까?

코드에서 일반 작업자를 QObject로 생성하고이를 QThread (하위 클래스로 만드는 대신 QThread를 사용하는 보편적 인 방법)로 이동 한 다음 일반 작업자 내에서 다른 QObject (마스터 클래스) 함수를 실행합니다. 마스터가 실행 된 후에 input()을 호출하지 않는 한 모든 것이 잘 작동합니다. 마스터 인스턴스의 함수가 아닌 작업자에서 직접 함수를 실행하는 경우에도 문제가 발생합니다.

import sys 
from PyQt4.QtCore import QCoreApplication, QObject, QThread, pyqtSignal, pyqtSlot 


class Worker(QObject): 
    """ 
    Generic worker. 
    """ 
    start = pyqtSignal(str) 
    finished = pyqtSignal() 

    def __init__(self, function): 
     QObject.__init__(self) 
     self._function = function 
     self.start.connect(self.run) 

    def run(self): 
     self._function() 
     self.finished.emit() 


class Master(QObject): 
    """ 
    An object that will use the worker class. 
    """ 
    finished = pyqtSignal() 

    def __init__(self): 
     QObject.__init__(self) 

    @pyqtSlot() 
    def do(self): 
     print("Do what?") 
     self.finished.emit() 


def done(): 
    # FIXME This will cause an infinite loop printing to the console: 
    # "QCoreApplication::exec: The event loop is already running" 
    input("Enter your answer: ") 


def main(): 
    app = QCoreApplication(sys.argv) 

    master = Master() 
    worker = Worker(master.do) 
    master.finished.connect(done) 

    thread = QThread() 
    thread.started.connect(worker.run) 
    worker.moveToThread(thread) 

    # Terminating thread gracefully, or so. 
    worker.finished.connect(thread.quit) 
    worker.finished.connect(worker.deleteLater) 
    thread.finished.connect(thread.deleteLater) 

    thread.start() 

    sys.exit(app.exec_()) 


if __name__ == "__main__": 
    main() 

답변

2

귀하의 예제에서 input와 실제 문제가 없습니다 : 여기

문제를 재현하는 샘플 코드입니다. done()에 enter를 입력하면 컨트롤이 이벤트 루프로 돌아간 다음 추가 사용자 상호 작용을 기다립니다. 이는 정상적이고 예상되는 동작입니다.

그 이후에 발생할 것으로 예상되는 것을 분명히하지 마십시오. 당신이 종료 할 수있는 프로그램을 원한다면, 그냥 이렇게 :

def done(): 
    input("Enter your answer: ") 
    QCoreApplication.quit() 

Qt는 경고 메시지는 무해하지만 이런 식으로 제거 할 수 있습니다 :

def main(): 
    from PyQt4.QtCore import pyqtRemoveInputHook 
    pyqtRemoveInputHook() 

    app = QCoreApplication(sys.argv) 
    ... 

귀하의 예제에서 유일한 진짜 문제는 스레딩 구현 print(QThread.currentThread())Worker.run(), Master.do()main()에 추가하면 메인 스레드에서 3 개 모두가 실행되는 것을 확인할 수 있습니다. 이는 thread.start 신호를 에 연결 한 후 작업자를 다른 스레드로 이동했기 때문입니다. 스레드를 통해 연결된 모든 슬롯에 항상 @pyqtSlot 데코레이터를 사용하도록이 문제를 해결하는 가장 쉬운 방법 (즉, 유지 관리가 용이함)은 신호 연결이 언제 이루어 지든 상관 없기 때문입니다. 이 문제에 대한 자세한 설명은 this answer을 참조하십시오.

+0

우수! 나는 당신의 대답으로 2 가지 문제를 해결했습니다. 고마워. – R01k