简体   繁体   English

“QThread:当线程仍在运行时被破坏”从Windows cmd或IDLE运行但不是从PyCharm运行?

[英]“QThread: Destroyed while thread is still running” when run from the Windows cmd or IDLE but not from PyCharm?

This is a simplified version of the program implementing PyQt multi-threading with QObject.moveToThread. 这是使用QObject.moveToThread实现PyQt多线程的程序的简化版本。 Basically, I query a webpage on a separate thread and extract the HMTL content. 基本上,我在一个单独的线程上查询网页并提取HMTL内容。

I get this problem where running the code from IDLE or the Windows command line hangs python. 我遇到这个问题,从IDLE运行代码或Windows命令行挂起python。 The Windows cmd shows "QThread: Destroyed while thread is still running". Windows cmd显示“QThread:在线程仍在运行时被销毁”。 However, if I run it from Pycharm, everything works fine. 但是,如果我从Pycharm运行它,一切正常。

You can get the .ui file here 你可以在这里获得.ui文件

Any ideas? 有任何想法吗?

import requests
import sys
from PyQt4 import QtGui, uic
from PyQt4.QtCore import QObject, pyqtSlot, pyqtSignal, QThread


qtCreatorFile = "window.ui"
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)


class HttpClient(QObject):

    finished =  pyqtSignal(str)

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

    @pyqtSlot()
    def retrieve_page(self, url):
        response = requests.get(url)
        self.finished.emit(response.text)


class HtmlGetter(QtGui.QMainWindow, Ui_MainWindow):

    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        Ui_MainWindow.__init__(self)
        self.setupUi(self)       
        self.go_button.clicked.connect(self.query_page)

    def query_page(self):
        http_client = HttpClient()
        temp_thread = QThread()
        http_client.moveToThread(temp_thread)

        temp_thread.started.connect(
        lambda: http_client.retrieve_page("http://www.google.com/"))
        http_client.finished.connect(self.show_html)

        # Terminating thread gracefully.
        http_client.finished.connect(temp_thread.quit)
        http_client.finished.connect(http_client.deleteLater)
        temp_thread.finished.connect(temp_thread.deleteLater)

        temp_thread.start()

    def show_html(self, html_text):
        print(html_text)


def main():
    app = QtGui.QApplication(sys.argv)
    window = HtmlGetter()
    window.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

I figured it out: 我想到了:

Both http_client and temp_thread have to be attributes or the HtmlGetter class. http_client和temp_thread都必须是属性或HtmlGetter类。 I think it's because otherwise python discards them when exiting the function. 我认为这是因为否则python在退出函数时会丢弃它们。 This is the working code: 这是工作代码:

import requests
import sys
from PyQt4 import QtGui, uic
from PyQt4.QtCore import QObject, pyqtSlot, pyqtSignal, QThread


qtCreatorFile = "window.ui"
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)


class HttpClient(QObject):

    finished =  pyqtSignal()
    send_text = pyqtSignal(str)

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

    @pyqtSlot()
    def retrieve_page(self, url):
        response = requests.get(url)
        self.send_text.emit(response.text)
        self.finished.emit()


class HtmlGetter(QtGui.QMainWindow, Ui_MainWindow):

    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        Ui_MainWindow.__init__(self)
        self.setupUi(self)       
        self.go_button.clicked.connect(self.query_page)

    def query_page(self):
        self.http_client = HttpClient()
        self.temp_thread = QThread()
        self.http_client.moveToThread(self.temp_thread)

        self.temp_thread.started.connect(
        lambda: self.http_client.retrieve_page("http://www.google.com/"))
        self.http_client.send_text.connect(self.show_html)

        # Terminating thread gracefully.
        self.http_client.finished.connect(self.temp_thread.quit)
        self.http_client.finished.connect(self.http_client.deleteLater)
        self.temp_thread.finished.connect(self.temp_thread.deleteLater)

        self.temp_thread.start()

    def show_html(self, html_text):
        print(html_text)


def main():
    app = QtGui.QApplication(sys.argv)
    window = HtmlGetter()
    window.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM