任務量較少的情況,我會直接用 threading, 任務量大且需向其它gui 物件傳遞訊息的情況,我會用QThread
這篇是寫PyQt,所以這邊我也只寫 QThread部份
會想使用QThread,我所遇到的情況,是向網頁,抓取資料,又遇網路過慢,延遲過久造成Gui介面等待過久,介面會卡卡、頓頓的。
首先先寫介面,然後點擊 startBtn 可以測試 無線程情況下,圖形介面是不是卡卡的
# -*- coding: UTF8 -*-import sys import urllib2 from PyQt4.QtGui import * from PyQt4.QtCore import * class Window(QWidget): def __init__(self, parent=None): super(self.__class__, self).__init__(parent) layout = QVBoxLayout() hbox = QHBoxLayout() self.edit = QTextEdit() self.startBtn = QPushButton("Start") self.stopBtn = QPushButton("Stop") hbox.addStretch() hbox.addWidget(self.startBtn) hbox.addWidget(self.stopBtn) layout.addWidget(self.edit) layout.addLayout(hbox) self.setLayout(layout) # SIGNAL&SLOT self.startBtn.clicked.connect(self.test) def test(self): url = 'http://blog.sina.com.cn/' html = urllib2.urlopen(url).read() length = len(html) self.edit.append("Url:%s Content:%s" % (url, length)) if __name__ == "__main__": app = QApplication(sys.argv) window = Window() window.show() sys.exit(app.exec_())
加入線程
class Worker(QThread): def __init__(self, parent=None): super(self.__class__, self).__init__(parent) self.url = 'http://blog.sina.com.cn/' def run(self): html = br.urlopen(self.url).read() length = len(html) self.emit(SIGNAL("length"), self.url, str(length)) print 'success'self.emit(SIGNAL("length"), self.url, str(length))當線程完成任務時,我們請線程發送訊號"length",並傳遞url及所抓取網頁的資料大小
主程式添加
class Window(QWidget): def __init__(self, parent=None): super(self.__class__, self).__init__(parent).
.
.
self.work = Worker() # SIGNAL&SLOT self.startBtn.clicked.connect(self.start) self.connect(self.work, SIGNAL("length"), self.updateUI) def start(self): self.work.start() def updateUI(self, url, length): self.edit.append("Url:%s Content:%s" % (url, length))
self.connect(self.work, SIGNAL("length"), self.updateUI)主程式這邊接收剛線程傳遞出來的資料"length"
現在我們多添加一點任務給線程
import lxml.html as H
線程改寫成
class Worker(QThread): def __init__(self, parent=None): super(self.__class__, self).__init__(parent) self.url = 'http://blog.sina.com.cn/' def run(self): self.url = 'http://blog.sina.com.cn/' html = urllib2.urlopen(self.url).read() doc = H.document_fromstring(html) urlList = doc.xpath('//a/@href') for i in range(10): url = urlList[i] html = urllib2.urlopen(url).read() length = len(html) self.emit(SIGNAL("length"), url, str(length)) print 'success'
在任務一執行時,先關閉doc = H.document_fromstring(html) urlList = doc.xpath('//a/@href')這邊我們用 lxml.html xpath語法 取得了,所有文章連結
讓線程去跑十篇文章。
在跑文章時候,我們希望避免重複按下startBtn
應修改
def start(self): self.work.start() self.startBtn.setEnabled(False)
self.startBtn
任務完成時,再開啟 self.startBtn主程式添加以下代碼self.connect(self.work, SIGNAL("finished()"), self.finished) def finished(self): self.startBtn.setEnabled(True)
那如果我們希望執行當中,停止任務呢?
QMutex() 上鎖吧!最後整個程式代碼如下:# -*- coding: UTF8 -*- import sys import lxml.html as H import urllib2 from PyQt4.QtGui import * from PyQt4.QtCore import * class Window(QWidget): def __init__(self, parent=None): super(self.__class__, self).__init__(parent) layout = QVBoxLayout() hbox = QHBoxLayout() self.edit = QTextEdit() self.startBtn = QPushButton("Start") self.stopBtn = QPushButton("Stop") hbox.addStretch() hbox.addWidget(self.startBtn) hbox.addWidget(self.stopBtn) layout.addWidget(self.edit) layout.addLayout(hbox) self.setLayout(layout) # self.work = Worker() # SIGNAL&SLOT self.startBtn.clicked.connect(self.start) self.stopBtn.clicked.connect(self.stop) self.connect(self.work, SIGNAL("length"), self.updateUI) self.connect(self.work, SIGNAL("finished()"), self.finished) def start(self): self.work.start() self.startBtn.setEnabled(False) def updateUI(self, url, length): self.edit.append("Url:%s Content:%s" % (url, length)) def finished(self): self.startBtn.setEnabled(True) def stop(self): self.work.stop() self.startBtn.setEnabled(True) class Worker(QThread): def __init__(self, parent=None): super(self.__class__, self).__init__(parent) self.stoped = False self.mutex = QMutex() def run(self): with QMutexLocker(self.mutex): self.stoped = False self.url = 'http://blog.sina.com.cn/' html = urllib2.urlopen(self.url).read() doc = H.document_fromstring(html) urlList = doc.xpath('//a/@href') for i in range(10): url = urlList[i] if self.stoped: return html = urllib2.urlopen(url).read() length = len(html) self.emit(SIGNAL("length"), url, str(length)) print 'success' def stop(self): with QMutexLocker(self.mutex): self.stoped = True def isStop(self): with QMutexLocker(self.mutex): return self.stoped if __name__ == "__main__": app = QApplication(sys.argv) window = Window() window.show() sys.exit(app.exec_())
沒有留言:
張貼留言