Уведомления

Группа в Telegram: @pythonsu
  • Начало
  • » GUI
  • » PyQt4. Как прервать работу потока [RSS Feed]

#1 Май 13, 2009 11:31:23

voltron
От:
Зарегистрирован: 2009-04-23
Сообщения: 31
Репутация: +  2  -
Профиль   Отправить e-mail  

PyQt4. Как прервать работу потока

Есть приложение на PyQt 4.4.3 + Python 2.5, выполняющее анализ неких данных, Т.к. анализ процедура длительная, решил вынести его в отдельный поток и предоставить юзеру возможность прервать выполнение этой операции. До этого с потоками практически не сталкивался, посмотрел доки, примеры и похожую по функционалу программу. Научился создавать поток, получать информацию о процессе работы, а вот сделать так, чтобы по нажатию на кнопку поток останавливал работу не получается. Вот небольшой пример

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys

class dlgTest( QDialog ):
def __init__( self, parent = None ):
QDialog.__init__( self, parent )

self.mainLayout = QVBoxLayout()

self.btnStart = QPushButton()
self.btnStart.setText("Start")
QObject.connect( self.btnStart, SIGNAL( "clicked()" ), self.startCalculation )

self.btnStop = QPushButton()
self.btnStop.setText("Stop")
QObject.connect( self.btnStop, SIGNAL( "clicked()" ), self.stopCalculation )

self.lblProgress = QLabel()
self.lblProgress.setText("Progress: 0")

self.mainLayout.addWidget(self.btnStart)
self.mainLayout.addWidget(self.btnStop)
self.mainLayout.addWidget(self.lblProgress)
self.setLayout(self.mainLayout)

self.setWindowTitle( self.tr( "Thread" ) )
self.resize( 120, 100 )

# запуск "анализа" в отдельном потоке
def startCalculation( self ):
self.threadCalc = workThread()
QObject.connect( self.threadCalc, SIGNAL( "runStatus(PyQt_PyObject)" ), self.runStatusFromThread )
self.threadCalc.start()
# остановка "анализа" по нажатию на кнопку
def stopCalculation( self ):
self.threadCalc.stop()
# для отображения процесса выполнения
def runStatusFromThread( self, status ):
self.lblProgress.setText( "Progress: " + str( status ) )

class workThread( QThread ):
def __init__( self, parent = None ):
QThread.__init__( self, parent )
self.running = False
self.counter = 0

def run( self ):
self.running = True
while True:
self.counter += 1
self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), self.counter )
self.sleep(1)
# остановка потока
def stop( self ):
#self.counter = 0
self.running = False

if __name__ == "__main__":
app = QApplication( sys.argv )
frm = dlgTest()
frm.show()
sys.exit( app.exec_() )
При нажатии на кнопку Start поток запускается и начинает “анализ”, а вот нажатие на Stop ничего не дает. В чем моя ошибка? Может, что-то делаю не правильно? В примерах из комплекта PyQt ничего подходящего не нашел.

P.S.: Если ошибся топиком, прошу модераторов извинить и поправить.



Офлайн

#2 Май 13, 2009 12:19:44

PooH
От:
Зарегистрирован: 2006-12-05
Сообщения: 1948
Репутация: +  72  -
Профиль   Отправить e-mail  

PyQt4. Как прервать работу потока

Поток должен проверять, что self.running истинно, и завершаться в противном случае

class workThread( QThread ):
...

def run( self ):
self.running = True
while self.running:
self.counter += 1
self.emit( SIGNAL( "runStatus(PyQt_PyObject)" ), self.counter )
self.sleep(1)



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

Офлайн

#3 Май 13, 2009 17:40:33

voltron
От:
Зарегистрирован: 2009-04-23
Сообщения: 31
Репутация: +  2  -
Профиль   Отправить e-mail  

PyQt4. Как прервать работу потока

Т.е. все действия, которые выполняет поток, нужно просто завернуть в цикл while self.running?
Спасибо! Буду пробовать.



Офлайн

#4 Май 13, 2009 18:05:05

gmorgunov
От:
Зарегистрирован: 2008-10-15
Сообщения: 137
Репутация: +  0  -
Профиль   Отправить e-mail  

PyQt4. Как прервать работу потока

Поток можно завершить вот так, например:

# остановка потока
def stop( self ):
print 'stop'
self.terminate()
self.wait()
Тогда переменная self.running вообще-то и не нужна.:)



Отредактировано (Май 13, 2009 20:09:20)

Офлайн

#5 Май 14, 2009 01:22:37

ZZZ
От: Москва
Зарегистрирован: 2008-04-03
Сообщения: 2161
Репутация: +  26  -
Профиль   Адрес электронной почты  

PyQt4. Как прервать работу потока

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

И вообще, так, к размышлению, рекомендую всегда держать в уме выражение вида:
res = (yield curr)
Я, когда открыл это, оно было для меня как откровение и с тех пор я слежу за “What's new in Python X.X?” Это первое…

И второе.
У меня сейчас довольно специфическая задача и я организовал интерфейс через handler. Для остановки вызывает своё исключение. Для управдение самим алготитмом можно править хандлер.
Чтобы было понятно, вот немного кода:

class StopException(Exception): pass

class Handler(object):
'Типа хендлер'
def __init__(self, processor):
self.processor = processor

def start(self, id):
self.id = id

def work_start(self):
'Начало части алгоритма'
pass
def work_pass(self, curr):
self.processor.setProgress(curr)
def work_error(self, exc):
self.processor.process_stop()
raise StopException, exc
def work_end(self):
'Конец части алгоритма'
pass

def end(self):
pass
def stop(self):
pass


def work(work_data, handler):
'Какая-то абстрактная работа'
id = get_id()
handler.start(id)

try:
self.work_start()
for i in range(100):
try:
# Пашем...
handler.work_pass(i)
except Error, exc:
# Ууупс
handler.work_error(exc)
self.work_end()

except StopException, exc:
handler.stop(exc)
return

handler.end()

# Используется примерно так.
handler = Handler(processor)
work(data, handler)
Но стоит сказать, что у меня на один алгоритм работет несколько разных нендлеров… Всё зависит от того, какое поведение от этого алгоритма мне надо получить в данной ситуации.

И в третьих… Через неделю будет год, как я написал это. Рекомендовал бы разобрать.

P.S. gmorgunov, любишь Pink Floyd? Никогда не понимал, почему “The Division Bell” никому не нравится, а меня плющит…



Отредактировано (Май 14, 2009 01:24:28)

Офлайн

#6 Май 14, 2009 07:29:37

PooH
От:
Зарегистрирован: 2006-12-05
Сообщения: 1948
Репутация: +  72  -
Профиль   Отправить e-mail  

PyQt4. Как прервать работу потока

ZZZ
И вообще, так, к размышлению, рекомендую всегда держать в уме выражение вида:
res = (yield curr)
Что то я не понял смысл выражения :(
ZZZ
Никогда не понимал, почему “The Division Bell” никому не нравится, а меня плющит…
А там кроме заглавной песни почему-то ничего не запоминается. Хотя клип на нее хорош, хоооороош



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

Офлайн

#7 Май 14, 2009 15:19:47

ZZZ
От: Москва
Зарегистрирован: 2008-04-03
Сообщения: 2161
Репутация: +  26  -
Профиль   Адрес электронной почты  

PyQt4. Как прервать работу потока

PooH
Что то я не понял смысл выражения
5.2.8. Yield expressions
Да, PooH, yield, это не только ценный мех…

PooH
А там кроме заглавной песни почему-то ничего не запоминается. Хотя клип на нее хорош, хоооороош
Ну нет, не согласен… High Hopes вещь так вообще взрывает мозг! А Wearing The Inside Out разве плохо звучит? Suum сuique… Блин… А то я сейчас весь альбом перечислю… :-) Просто я люблю добротную профессиональную музыку и завидую этим дядям, потому что так я никогда не смогу играть, сколько бы я гитару не мучал…



Офлайн

#8 Май 14, 2009 16:01:01

PooH
От:
Зарегистрирован: 2006-12-05
Сообщения: 1948
Репутация: +  72  -
Профиль   Отправить e-mail  

PyQt4. Как прервать работу потока

ZZZ
5.2.8. Yield expressions
Да, PooH, yield, это не только ценный мех…
Аааа… это я просто выражения не понял. Ну генераторы я регулярно использую, особенно презенташка вдохновляет, где цепочка итераторов начинается на одной машине, а заканчивается уже на другой :)
ZZZ
PooH
А там кроме заглавной песни почему-то ничего не запоминается. Хотя клип на нее хорош, хоооороош
Ну нет, не согласен… High Hopes
Хм… оказывается именно ее я имел ввиду :) уж очень полотна на ветру запомнились
ZZZ
Просто я люблю добротную профессиональную музыку и завидую этим дядям, потому что так я никогда не смогу играть, сколько бы я гитару не мучал…
Я то барабаны терзал… Вообще последнее время Сантана доставляет :)



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

Отредактировано (Май 14, 2009 16:01:55)

Офлайн

#9 Май 14, 2009 18:19:53

ZZZ
От: Москва
Зарегистрирован: 2008-04-03
Сообщения: 2161
Репутация: +  26  -
Профиль   Адрес электронной почты  

PyQt4. Как прервать работу потока

PooH
Аааа… это я просто выражения не понял.
Ну я к тому, что генератор может не только давать, но и получать объект, а также райзить исключения.

PooH
Вообще последнее время Сантана доставляет
Очень давно его не слышал… Но когда-то он мне очень нравился и уж его гитару ни с чем не спутаешь!



Офлайн

#10 Май 14, 2009 18:32:18

gmorgunov
От:
Зарегистрирован: 2008-10-15
Сообщения: 137
Репутация: +  0  -
Профиль   Отправить e-mail  

PyQt4. Как прервать работу потока

Сейчас снова послушал. Раньше как-то больше впечатляло. Но Marooned и High Hopes… звучат по-прежнему.:)



Офлайн

  • Начало
  • » GUI
  • » PyQt4. Как прервать работу потока[RSS Feed]

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version