Форум сайта python.su
Есть приложение на 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_() )
Офлайн
Поток должен проверять, что 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)
Офлайн
Т.е. все действия, которые выполняет поток, нужно просто завернуть в цикл while self.running?
Спасибо! Буду пробовать.
Офлайн
Поток можно завершить вот так, например:
# остановка потока
def stop( self ):
print 'stop'
self.terminate()
self.wait()
Отредактировано (Май 13, 2009 20:09:20)
Офлайн
Это, вроде бы, и самый простой вариант, но я бы рекомендовал космотреть на микротридинг. Иногда правильный генератор будет лучше любой нити. А с 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)
Отредактировано (Май 14, 2009 01:24:28)
Офлайн
ZZZЧто то я не понял смысл выражения :(
И вообще, так, к размышлению, рекомендую всегда держать в уме выражение вида:
res = (yield curr)
ZZZА там кроме заглавной песни почему-то ничего не запоминается. Хотя клип на нее хорош, хоооороош
Никогда не понимал, почему “The Division Bell” никому не нравится, а меня плющит…
Офлайн
PooH5.2.8. Yield expressions
Что то я не понял смысл выражения
PooHНу нет, не согласен… High Hopes вещь так вообще взрывает мозг! А Wearing The Inside Out разве плохо звучит? Suum сuique… Блин… А то я сейчас весь альбом перечислю… :-) Просто я люблю добротную профессиональную музыку и завидую этим дядям, потому что так я никогда не смогу играть, сколько бы я гитару не мучал…
А там кроме заглавной песни почему-то ничего не запоминается. Хотя клип на нее хорош, хоооороош
Офлайн
ZZZАааа… это я просто выражения не понял. Ну генераторы я регулярно использую, особенно презенташка вдохновляет, где цепочка итераторов начинается на одной машине, а заканчивается уже на другой :)
5.2.8. Yield expressions
Да, PooH, yield, это не только ценный мех…
ZZZХм… оказывается именно ее я имел ввиду :) уж очень полотна на ветру запомнилисьPooHНу нет, не согласен… High Hopes
А там кроме заглавной песни почему-то ничего не запоминается. Хотя клип на нее хорош, хоооороош
ZZZЯ то барабаны терзал… Вообще последнее время Сантана доставляет :)
Просто я люблю добротную профессиональную музыку и завидую этим дядям, потому что так я никогда не смогу играть, сколько бы я гитару не мучал…
Отредактировано (Май 14, 2009 16:01:55)
Офлайн
PooHНу я к тому, что генератор может не только давать, но и получать объект, а также райзить исключения.
Аааа… это я просто выражения не понял.
PooHОчень давно его не слышал… Но когда-то он мне очень нравился и уж его гитару ни с чем не спутаешь!
Вообще последнее время Сантана доставляет
Офлайн
Сейчас снова послушал. Раньше как-то больше впечатляло. Но Marooned и High Hopes… звучат по-прежнему.:)
Офлайн