简体   繁体   English

QObject :: killTimers错误QThread PyQt

[英]QObject::killTimers error QThread PyQt

I have a script I'm writing to batch download images from an imageboard via JSON/XML api. 我有一个正在编写的脚本,用于通过JSON / XML API从图像板批量下载图像。 Previously, it had been purely CLI, but recently I've been trying to build a UI in PyQt, with great success but for one problem: thread blocking issues, nonresponsive GUI when actually calling the worker threads within my script. 以前,它纯粹是CLI,但最近我一直试图在PyQt中构建UI,但取得了很大的成功,但有一个问题:线程阻塞问题,在脚本中实际调用工作线程时GUI不响应。 So, I'm trying to switch from threading.Thread to QThread, to make it easier to manage (by emitting a threadFinished SIGNAL to update my GUI), but I can't seem to get it set up properly. 因此,我试图从threading.Thread切换到QThread,以使其易于管理(通过发出threadFinished SIGNAL更新我的GUI),但是我似乎无法正确设置它。 Whenever I run the script, The threads die prematurely. 每当我运行脚本时,线程就会过早死亡。 I am running on windows, with PyQt4 on Python 2.7.2. 我在Windows上运行,在Python 2.7.2上使用PyQt4。

After a bit more research, I believe the problem lies in a thread exiting, and creating a new thread with a new tuple being passed from the queue. 经过更多研究,我认为问题出在线程退出,并使用从队列中传递的新元组创建新线程。 All results I can find online point to it being about the application not exiting cleanly. 我在网上可以找到的所有结果都表明它与应用程序未完全退出有关。

Exception KeyError: KeyError(1188,) in <module 'threading' from 'C:\Python27\lib\threading.pyc'> ignored
QObject::killTimers: timers cannot be stopped from another thread

this is the output I receive. 这是我收到的输出。

Direct code in question: 有问题的直接代码:

md5_queue is queue of an empty dict of md5sum/filename to be filled by Url_Download() queue is a queue tuple of filenames/urls md5_queue是要由Url_Download()填充的md5sum / filename空字典的队列,是文件名/ url的队列元组

in crawler.py: 在crawler.py中:

num_conn = int(max_threads)
threads = []
for download in range(num_conn):
    t = Url_Download(queue, md5_queue)
    t.start()
    threads.append(t)

from functions.py (poorly named, I know) the Url_Download() class: 从functions.py(我知道这个名字很差)的Url_Download()类:

class Url_Download(QThread):

    file_finished = pyqtSignal(QString, int, name="fileFinished")

    def __init__(self, dl_queue, md5_queue):
        self.dl_queue = dl_queue
        self.md5_queue = md5_queue
        QThread.__init__(self)
    def run(self):
        while 1:
            try:
                count = 0
                file_url, file_path, md5 = self.dl_queue.get_nowait()
                file_extension = str(file_url)[-4:]
                file_name = md5 + file_extension
                while count < 3:
                    count +=1
                    fetch_url(file_url, file_path, md5)
                    if md5 == hash_sum(file_path):
                       self.md5_queue.put_nowait((md5, file_name))
                       self.file_finished.emit("Test!", 10)
                       break

                if count > 3:
                    print 'File failed to download, {} might be corrupt.'.format(file_name)       
                qsize = self.dl_queue.qsize()
                if qsize > 0:
                    print 'Count Remaining: ', qsize
            except Queue.Empty:
                raise SystemExit 
            except:
                traceback.print_exc(file=sys.stderr)
                sys.stderr.flush()

and from GUI.py, the slot connect: 并从GUI.py中,插槽连接:

self.connect(self, SIGNAL("fileFinished(QString, int)"), self.handle_test, Qt.QueuedConnection)

Git (testing branch) for the code: https://github.com/CirnoIsTheStrongest/BiriCrawler/tree/testing 代码的Git(测试分支): https : //github.com/CirnoIsTheStrongest/BiriCrawler/tree/testing

Please note, this is my first ever attempt at coding anything. 请注意,这是我第一次尝试编码任何东西。 If that is a problem, just let me know 如果有问题,请告诉我

Thanks Avaris for your help, I fixed the connect to point towards my Url_Download() instance. 感谢Avaris的帮助,我修复了连接问题,使其指向我的Url_Download()实例。 The issue occurring apparently was very inadequately displayed on windows. 发生的问题显然没有在窗口上充分显示。 On my linux VM I was given this error instead: 在我的linux VM上,我得到了这个错误:

QThread: Destroyed while thread is still running
QThread: Destroyed while thread is still running
QThread: Destroyed while thread is still running
QThread: Destroyed while thread is still running
Segmentation fault

So the issue was still caused (I believe) by my GUI not waiting for threads to finish their tasks before they were terminated. 因此,问题仍然是由我的GUI引起的(我相信),因为我不等待线程在终止之前完成任务。 After referencing my threads object in GUI.py, the error no longer occurs. 在GUI.py中引用我的线程对象后,该错误不再发生。 I'm also finally able to send a signal to the GUI from within my threaded class. 我最终也可以从线程类中向GUI发送信号。 Full code changes can be found here for those who want to see the other changes involved: Github page, testing branch 对于那些希望查看涉及的其他更改的人,可以在此处找到完整的代码更改: Github页面,测试分支

In Crawler.py 在Crawler.py中


    threads = []
    for download in range(self.num_of_threads):
        t = Url_Download(self.dl_queue, self.md5_queue, is_cli=True)
        t.start()
        threads.append(t)

    for thread in threads:
        thread.wait()

in GUI.py 在GUI.py中


   main = Crawler(gui_tags, gui_limit, gui_page, gui_booru, gui_savepath, gui_partype, gui_rating, max_threads)
    self.threads = main.start_threads()
    for thread in self.threads:
        self.connect(thread, SIGNAL("fileFinished(QString, int)"), self.onFileFinished, Qt.QueuedConnection)
        self.connect(thread, SIGNAL("allFinished()"), self.onAllFilesFinished, Qt.QueuedConnection)

in functions.py 在functions.py中


class Url_Download(QThread):

    file_finished = pyqtSignal(QString, int, name="fileFinished")        

    def __init__(self, dl_queue, md5_queue, is_cli=False, parent=None):
        QThread.__init__(self, parent)
        self.exiting = False
        self.dl_queue = dl_queue
        self.md5_queue = md5_queue
        self.is_cli = is_cli

    def __del__(self):
        self.exiting = True

     def run(self):
        while not self.exiting:
            try:
                count = 0
                file_url, file_path, md5 = self.dl_queue.get_nowait()
                file_extension = str(file_url)[-4:]
                file_name = md5 + file_extension
                while count < 3:
                    count +=1
                    fetch_url(file_url, file_path, md5)
                    if md5 == hash_sum(file_path):
                       self.md5_queue.put_nowait((md5, file_name))
                       self.file_finished.emit("Test!", 10)
                       break

                if self.is_cli:       
                    if count >= 3:
                        print 'File failed to download, {} might be corrupt.'.format(file_name)       
                    qsize = self.dl_queue.qsize()
                    if qsize > 0:
                        print 'Count Remaining: ', qsize
            except Queue.Empty:
                self.__del__()
            except:
                traceback.print_exc(file=sys.stderr)
                sys.stderr.flush()

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

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