[英]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的队列元组
num_conn = int(max_threads)
threads = []
for download in range(num_conn):
t = Url_Download(queue, md5_queue)
t.start()
threads.append(t)
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()
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页面,测试分支
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()
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)
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.