Как перенаправить вывод нескольких скриптов в QTextBrowser, используя PyQt4
Я использовал QtDesigner
сделать волшебника и преобразовать .ui
использованиефайла pyuic4
,
Этот мастер имеет несколько страниц. На одной из страниц есть флажки. Флажки используются для выбора определенных скриптов Python для запуска.
Мой вопрос заключается в том, как я должен вызывать выбранные сценарии один за другим, а затем перенаправлять вывод в режиме реального времени на QTextBrowser
виджет на любой из последующих страниц мастера.
Наконец, во время работы сценариев есть возможность временно отключить кнопки "Далее" и "Назад".
1 ответ
Использование QThread
чтобы избежать зависания пользовательского интерфейса; запускать скрипты в ветке, используя 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()
Однако обратите внимание, что из-за буферизации выходные данные сценариев могут приходить большими кусками, что затрудняет достижение гладкости в реальном времени, как в терминале. С питоном вы можете обойти это, передав -u
переключиться на переводчика (не на сценарий).