Краткая версия:
Отправка сигналов в GUI внезапным образом приводит к тому, что данные, которые они несут, вставляются повсюду в текстовое поле, в которое они должны входить.
Длинная версия:
У меня есть графический интерфейс PyQt, который подключен к скрипту Python. Скрипт запускается в отдельном потоке и пишет в stdout
и stderr
. Скрипт может выполняться независимо, но я создал графический интерфейс, чтобы обеспечить более удобный интерфейс.
Чтобы захватить stdout
/stderr
и записать их вывод в графическом интерфейсе, я перезаписал sys.stdout
и sys.stderr
в потоке объектом, имеющим метод записи.
sys.stdout = StreamWrapper(sys.stdout, self, self.mutex)
sys.stderr = StreamWrapper(sys.stderr, self, self.mutex)
StreamWrapper:
class StreamWrapper:
def __init__(self, stream, thread, mutex):
self.stream = stream # reference to original stream (stdout or stderr)
self.thread = thread # thread in which this object is initialised.
self.mutex = mutex # mutex ensuring write is only called once at a time
def write(self, msg):
with QtCore.QMutexLocker(self.mutex):
self.thread.emit(QtCore.SIGNAL('update_console(QString)'), msg)
self.stream.write(msg)
time.sleep(0.5)
Этот метод записи выдает сигнал и сообщение графическому интерфейсу. Графический интерфейс (в основном потоке) подбирает его и соответственно обновляет обычное текстовое поле (называемое consoleOutput
):
self.connect(self.thread, QtCore.SIGNAL('update_console(QString)'), self.ui.consoleOutput.insertPlainText)
Я заметил, что когда происходит внезапный всплеск активности от stdout
, выходные данные будут записываться в графическом интерфейсе в беспорядке (буквально в любом порядке и смещая, но не перезаписывая предыдущий вывод). Я также пишу тот же вывод на консоль, и это в полном порядке.
Чтобы исправить это, я попытался ввести мьютекс, но безрезультатно. Затем я ввел задержку (путем вызова time.sleep(0.5)
), и это решило проблему, хотя и неуклюжим образом.
Посмотрев на испускание и порядок сигналов, похоже, что сигналы обрабатываются в том порядке, в котором они испускаются (я не отменяю какое-либо стандартное поведение), поэтому порядок может не быть проблемой.
Любые идеи?
ИЗМЕНИТЬ:
Я создал компилируемый пример, состоящий из трех файлов, которые должны находиться в одном каталоге:
Компилируемый пример выводит случайные данные на экран вместе со счетчиком для отслеживания порядка печати. На этом снимке экрана видно, что некоторые данные не синхронизированы с остальными.