Потоки и строки Python

#python #multithreading #python-3.x #buffering

#python #многопоточность #python-3.x #буферизация

Вопрос:

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

 wating....
  

Код похож на приведенный ниже:

импорт потоков время импорта

 class ThreadExample(object):

    def __init__(self):
        self.pause = True
        threading.Thread(target=self.second_thread).start()
        #  Some other processes
        print("Waiting", end="")
        while self.pause:
            time.sleep(1)
            print(".", end="")
        print("Hooray!")

    def second_thread(self):
        print("timer started")
        time.sleep(3)
        self.pause = False
        print("timer finished")

if __name__ == "__main__":
    ThreadExample()
  

Когда я запускаю приведенный выше код, я получаю выходные данные:

 timer started
Do something else..timer finished
.
Hooray!
  

не большой сюрприз, за исключением того, что в начале появляется только «таймер запущен», а остальная часть текста мгновенно появляется в конце.

Если я изменю строку print(«.», end=»») на print(«.»), я получу следующий вывод:

 timer started
Do something else.
.
timer finished
.
Hooray
  

где точки появляются с шагом в 1 секунду, что и было моим намерением.

Есть ли способ получить «Ожидание …» в одной строке без end =»»?

И, во-вторых, я предполагаю, что это как-то связано с внутренними компонентами функции print(), а если нет, должен ли я выполнять потоковую обработку другим способом? Я не думаю, что проблема в GIL, поскольку я пробовал многопроцессорность.Обработал и получил тот же результат.

Ответ №1:

Вероятно, это связано с print буферизацией. Он сбрасывается n и в некоторых других случаях (например, переполнение буфера или выход из программы). Вместо print того, чтобы попробовать это:

 import sys

def unbuffered_print(msg):
    sys.stdout.write(msg)
    sys.stdout.flush()

...
unbuffered_print('.')
  

везде.

Комментарии:

1. Примечание: На современном Python (3.3 и выше) print может быть передан flush=True , чтобы сделать его сброшенным после печати , сохраняя при этом полную мощность / гибкость print функции. Так print(end='.', flush=True) что или print('.', end='', flush=True) также сделает свое дело.

2. Спасибо, это очень полезно.