2011-12-26 2 views
2

У меня есть сценарий, который я пишу для загрузки изображений с графического экрана через JSON/XML api. Раньше это был просто CLI, но в последнее время я пытался создать пользовательский интерфейс в PyQt с большим успехом, но для одной проблемы: проблемы с блокировкой потоков, невосприимчивый графический интерфейс при вызове рабочих потоков внутри моего скрипта. Итак, я пытаюсь переключиться с threading.Thread на QThread, чтобы упростить управление (выпуская threadFinished SIGNAL для обновления моего графического интерфейса), но я не могу настроить его правильно. Всякий раз, когда я запускаю сценарий, нити умирают преждевременно. Я запускаю Windows, с PyQt4 на Python 2.7.2.QObject :: killTimers error QThread PyQt

После немного большего количества исследований я считаю, что проблема заключается в выходе потока и создании нового потока с новым кортежем, который передается из очереди. Все результаты, которые я могу найти в Интернете, указывают на то, что приложение не выходит из игры чисто.

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

это выход я принимаю.

Прямого код в вопросе:

md5_queue является очередью пустой Dict из md5sum/файла, чтобы быть заполненной Url_Download() очереди очереди кортеж имен файлов/URLs

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

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

и от GUI.py, слот подключения:

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

Гит (тестирование филиал) для кода: https://github.com/CirnoIsTheStrongest/BiriCrawler/tree/testing

Пожалуйста, обратите внимание, что это моя первая попытка на что-либо кодирования. Если это проблема, просто дайте мне знать

+1

Я не могу обернуть мою голову вокруг проблемы вы столкнулись, но что 'connect' линия является неправильной. Вы подключаете сигнал 'fileFinished'' QMainWindow', которого не существует. – Avaris

ответ

0

Спасибо Аварис за вашу помощь, я установил соединение, чтобы указать на экземпляр Url_Download(). Возникшая проблема, по-видимому, была очень неадекватно отображена на окнах. На моем 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 

Так что вопрос все еще вызвал (я считаю) мой GUI, не дожидаясь темы, чтобы закончить свои задачи, прежде чем они были прекращены. После ссылки на объект моих потоков в GUI.py ошибка больше не возникает. Я также, наконец, смог отправить сигнал в графический интерфейс из моего потока. Полные изменения кода можно найти здесь для тех, кто хочет видеть другие изменения участвуют: Github page, testing branch

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

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

в функции.р


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() 
Смежные вопросы