簡體   English   中英

為什么input()導致“ QCoreApplication :: exec:事件循環已在運行”?

[英]Why does input() cause “QCoreApplication::exec: The event loop is already running”?

我遇到了這個QCoreApplication問題,其中在QObject在QThread中執行完后調用input()會導致無限循環打印到控制台“ QCoreApplication :: exec:事件循環已在運行”。

在代碼中,我創建了一個通用工作器作為QObject,將其移動到QThread(批准使用的方法來使用QThread,而不是對其進行子類化),然后在通用工作器內執行另一個QObject的(Master類)函數。 只要在執行完Master之后我不調用input(),一切都會正常。 請注意,如果我直接在worker中執行一個函數(而不是Master實例的函數),也會發生此問題。

這是重現該問題的示例代碼:

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

您的示例中的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() ,您將看到這三個都在主線程中執行。 這是因為您將工作進程移動到另一個線程之前連接了thread.start信號。 解決此問題的最佳方法(即最容易維護的方法)是始終在跨線程連接的任何插槽上使用@pyqtSlot裝飾器-因為那樣建立信號連接時就沒有關系了。 (有關此問題的更完整說明,請參見此答案 )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM