gpt4 book ai didi

python - 为什么 input() 会导致 "QCoreApplication::exec: The event loop is already running"?

转载 作者:行者123 更新时间:2023-12-02 20:56:15 24 4
gpt4 key购买 nike

我遇到了这个 QCoreApplication 问题,其中 QObject 在 QThread 内完成执行后调用 input() 会导致无限循环打印到控制台“QCoreApplication::exec: 事件循环已在运行”。

在代码中,我创建了一个通用worker作为QObject,将其移动到QThread中(使用QThread的认可方式,而不是对其进行子类化),然后在通用worker内执行另一个QObject(主类)函数。只要我在执行 Master 后不调用 input() ,一切就可以正常工作。请注意,如果我直接在工作线程中执行函数(而不是 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()

最佳答案

您的示例中的输入没有真正的问题。在 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 装饰器 - 因为这样,何时建立信号连接就无关紧要了。 (有关此问题的更完整说明,请参阅 this answer)。

关于python - 为什么 input() 会导致 "QCoreApplication::exec: The event loop is already running"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40177743/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com