使用QThread
來避免UI凍結; 在線程中運行腳本使用subprocess.Popen
與stdout=PIPE
, 逐行讀取它們的輸出,emit
的行,並得到他們在任何slot
你想要的。
from PyQt4.QtGui import QTextBrowser, QApplication
from PyQt4.QtCore import pyqtSignal, QThread
from subprocess import Popen, PIPE
from Queue import Queue
from threading import Event
class ScriptRunner(QThread):
# fired whenever a line from subprocess.stdout arrived
got_line = pyqtSignal(unicode)
def __init__(self):
QThread.__init__(self)
self.queue = Queue()
self.put = self.queue.put
self.stop_event = Event()
self.start()
def run(self):
"""thread function"""
while 1:
script = self.queue.get()
if script is None: # no more scripts
break
# run the script
proc = Popen(script, bufsize=1, stdout=PIPE, shell=True,
universal_newlines=True)
# read its output line by line
while not self.stop_event.is_set():
line = proc.stdout.readline()
if not line:
break
self.got_line.emit(line)
def join(self):
self.stop_event.set()
self.put(None)
self.wait()
if __name__ == '__main__':
app = QApplication([])
text_browser = QTextBrowser()
text_browser.show()
runner = ScriptRunner()
# connect to got_line signal
runner.got_line.connect(text_browser.insertPlainText)
# schedule a script
runner.put('''python -c "for i in range(25): print 'dada'; import time; time.sleep(.25)"''')
# now force python to flush its stdout; note -u switch
runner.put('''python -uc "for i in range(25): print 'haha'; import time; time.sleep(.25)"''')
app.exec_()
runner.join()
不過請注意,由於緩衝腳本的輸出可能會在大塊, 使其難以實現實時平滑像終端。 使用python,你可以通過將-u
切換到解釋器(而不是腳本)來規避這種情況。