Итак, я пишу приложение, использующее PySide2, которое должно перенаправлять все с stdout
на промежуточный queue.Queue
. Этот Queue
испускает сигнал, который будет обработан QThread, добавляя все строки в очереди в QTextEdit.
Я немного осмотрелась, но, к сожалению, похоже, у меня ничего не получается.
Это код, который я имею в виду.
from PySide2 import QtWidgets, QtGui, QtCore
import sys
from queue import Queue
class WriteStream(object):
""" Redirects sys.stdout to a thread-safe Queue
Arguments:
object {object} -- base class
"""
def __init__(self, queue):
self.queue = queue
def write(self, msg):
self.queue.put(msg)
def flush(self):
""" Passing to create non-blocking stream (?!)
https://docs.python.org/3/library/io.html#io.IOBase.flush
"""
pass
class WriteStreamThread(QtCore.QThread):
queue_updated = QtCore.Signal(str)
def __init__(self, queue):
super(WriteStreamThread, self).__init__()
self.stop = False
self.queue = queue
def set_stop(self):
self.stop = True
self.wait() # waits till finished signal has been emitted
def run(self):
while not self.stop: # i guess this is blocking
msg = self.queue.get()
self.queue_updated.emit(msg)
self.sleep(1) # if commented out, app crashes
self.finished.emit()
class Verifyr(QtWidgets.QMainWindow):
def __init__(self, queue, parent=None):
super(Verifyr, self).__init__(parent)
self.centralwidget = QtWidgets.QWidget(self)
layout = QtWidgets.QVBoxLayout(self.centralwidget)
self.textedit = QtWidgets.QTextEdit(self)
layout.addWidget(self.textedit)
self.setLayout(layout)
self.setCentralWidget(self.centralwidget)
print("Verifyr initialised...")
self.listener_thread = WriteStreamThread(queue)
self.listener_thread.queue_updated.connect(self._log_to_qtextedit)
self.listener_thread.start()
@QtCore.Slot(str)
def _log_to_qtextedit(self, msg):
self.textedit.insertPlainText(msg)
if __name__ == '__main__':
# create Queue to be passed to WriteStream and WriteStreamListener
queue = Queue()
# redirect stdout to WriteStream()
sys.stdout = WriteStream(queue)
print("Redirected sys.stdout to WriteStream")
# launching the app
app = QtWidgets.QApplication(sys.argv)
window = Verifyr(queue)
app.aboutToQuit.connect(window.listener_thread.set_stop)
window.show()
sys.exit(app.exec_())
В WriteStreamThread
Я использую цикл while
, который продолжает излучать сигналы, перехваченные основным приложением для добавления к его QTextEdit. Когда я комментирую self.sleep(1)
, приложение может застрять в бесконечном цикле. Если нет, то нить выйдет просто отлично.
Может кто-нибудь, пожалуйста, объясните мне это?
UPDATE:
Как я уже упоминал в своем комментарии, я нашел ошибку ... вот обновленный run()
метод WriteStreamThread
:
def run(self):
while not self.stop:
try:
msg = self.queue.get(block=False) # nasty little kwarg
except:
msg = "No items in queue. Sleeping 1sec.."
self.sleep(1)
self.queue_updated.emit(msg)
self.finished.emit() # optional