Захват вывода печати из нескольких потоков в Python

1

У меня есть функция, которая внутри lauches несколько потоков работает параллельно. Нити печатают что-то, и я хочу захватить этот вывод из внешней функции. Я попытался использовать следующий код для вывода результатов:

import sys, io
stdout = sys.stdout
sys.stdout = io.StringIO()
threads_conn(connect, devices) #- here many threads starts with many print inside
output = sys.stdout.getvalue()
sys.stdout = stdout

print(output)

Этот код работает. Но проблема в том, что вывод печатается только тогда, когда все ад заполняются. Поэтому у меня есть заморозка. Как только все потоки будут выполнены, будет напечатан весь вывод. То, что я хотел бы иметь, - иметь выход, когда он генерируется внутри - другими словами, в режиме реального времени. Теперь у меня есть весь выходной буфер, напечатанный сразу. Как получить все потоки для вывода в режиме реального времени?

  • 1
    Вы спрашиваете, как записать весь вывод в строку, а также распечатать его в режиме реального времени?
  • 0
    Я думаю, вам все равно, что выходные данные из разных потоков смешиваются вместе. Или вы бы предпочли, если есть способ определить выход каждого потока?
Показать ещё 1 комментарий
Теги:
multithreading
output
capture

1 ответ

0
Лучший ответ

То, что вы хотите сделать, это написать собственный класс TextIOBase (или, если вам нужны двоичные данные, напишите свой собственный RawIOBase а затем оберните вокруг него TextIOWrapper), где вы можете поместить любое поведение, которое вы хотите.

Как вы можете видеть из документов. все, что вам нужно реализовать для TextIOBase является detach, read, readline, и write. И первые три не имеют отношения к тому, что вы делаете.


Итак, что должно выглядеть ваша write? Ну, это зависит от того, что вы хотите сделать.

это звучит так, как ваша цель состоит в том, чтобы доработать все как на реальном уровне, так и на StringIO. Если это так, это довольно тривиально.

Единственный вопрос - это то, что вы хотите сделать, если одна из целей вызывает исключение или записывает меньшее количество байтов, чем другое, и т.д. Поскольку IOString никогда не будет делать ничего из этого, мы можем написать что-то действительно немое, что просто предполагает, что независимо от того, что было в действительности, это было правильным решением.

class TeeTextIO(io.TextIOBase):
    def __init__(self, target):
        self.target = target
        self.stringio = io.StringIO()
    def write(self, s):
        writecount = self.target.write(s)
        self.stringio.write(s[:writecount])
        return writecount

И сейчас:

stdout = sys.stdout
sys.stdout = TeeTextIO(sys.stdout)
threads_conn(connect, devices) #- here many threads starts with many print inside
output = sys.stdout.stringio.getvalue()
sys.stdout = stdout

Теперь выход StringIO на реальный stdout когда он вошел, но он также был сохранен в StringIO для того, что вы хотите сделать с ним позже.

(Обратите внимание, что этот класс будет работать с любым TextIOBase, как с open файлом, а не только с stdout. Это не стоило нам ничего, чтобы сделать его общим, так почему бы и нет?)


Что делать, если вы хотите сделать что-то совершенно другое, например, распространять каждую write случайно среди 10 разных файлов? Это должно быть очевидно:

class SpreadTextWriter(io.TextIOBase):
    def __init__(self, *files):
        self.files = files
    def write(self, s):
        return random.choice(self.files).write(s)
  • 0
    Я подозреваю, что печать на терминал в режиме реального времени - это красная сельдь, и ОП действительно хочет, чтобы перенаправленный стандартный вывод появлялся в его графическом интерфейсе в реальном времени.
  • 1
    @ PM2Ring Я не мог понять, чего хочет ОП, поэтому я написал две разные вещи, чтобы показать, как легко написать то, что он действительно хочет. Конечно, если он просто копирует и вставляет один из них, ничего не читая, вероятность того, что он сделает то, что он хочет, составляет миллион к одному, но я не слишком обеспокоен этим.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню