Как одновременно вводить и выводить данные в консоль python
Я даже не знаю ка сформулировать вопрос, что бы он был ясен, но все таки постараюсь. В итоге я хочу сделать свой мини-чат - я могу получать новые сообщения во время ввода своего текста сообщения.
Мне нужен способ сделать одновременный ввод и вывод в консоли. Я пробовал делать так: с помощью ESC-последовательностей, двигать строку с вводом, затем перемещаться выше, выводить в освободившуюся строку текст, а потом возвращаться назад на строку вниз, где идет введенный мной текст и приглашение ввода. Это оказалось очень неэффективным и неудобным кодом, так как приглашение и текст пропадали, когда я пытаюсь вставить строку, когда окно консоли уже подошло к концу. Так же были проблемы, что если выводится несколько строк на экран, то сдвигалось все только на одну строку, и я писал ввод уже вдоль выведенного текста. Я пока что пользуюсь решением получать данные только по окончании ввода, но хотелось бы, что бы я мог получать нужную информация прямо во время ввода.
Возможно, как предложил @andreymal, стоит сделать 2 секции - внизу ввод, сверху вывод, но я не представляю как, я слышал что есть curses, но только на линукс. Есть ли какие то еще варианты с готовыми решениями, или стоит продолжить искать решение с ESC-последовательностями?
Ответы (1 шт):
Что ты имеешь в виду под консолью python? Если запущенный скрипт в командной строке windows, то можно так, с кареткой и самописным input'ом. Это довольно просто и работает. Из этого кода будет ясен принцип.
import msvcrt
import time
def input_wait(prompt='', timeout=1000, *, _delay=0.02):
inpute_line = str()
start = time.time()
while time.time() - start < timeout:
prompt_t = '\r{:.1f}| {}{}'.format(timeout - time.time() + start,
prompt, inpute_line)
print(prompt_t, end='')
if msvcrt.kbhit():
char = msvcrt.getwch()
if char == '\r':
msvcrt.putwch('\n')
break
elif char == '\000' or char == '\xe0':
msvcrt.getwch()
pass
elif ord(char) == 8: # backspace
print('\r{}'.format(' ' * len(prompt_t)), end='')
inpute_line = inpute_line[:-1]
else:
inpute_line += char
else:
time.sleep(_delay)
else:
inpute_line = None
return inpute_line
timeout = 10
prompt = 'Enter answer: '
print('Сколько будет 5 + 5?')
print('у вас есть 10 секунд')
while True:
answer = input_wait(prompt, timeout=timeout)
if answer is None:
print('\nTime is up')
else:
if answer == '10':
print("It's right answer!")
elif answer == 'q':
print('exit...')
break
else:
print("No! Try again.")
Насколько я понял, тебе нужно перерисовывать не одну строчку, а несколько. Вот код, который демонстрирует свободное перемещение курсора для перерисовки кареткой.
from __future__ import print_function
import colorama
from time import sleep
colorama.init()
# # ESC [ n A # move cursor n lines up
# # ESC [ n B # move cursor n lines down
cursor_up = lambda lines: '\x1b[{0}A'.format(lines)
cursor_down = lambda lines: '\x1b[{0}B'.format(lines)
print("meow :)")
print("meow-meow :)")
print("meow-meow-meow :)")
lines_up = 3
print(cursor_up(lines_up), end='')
sleep(1)
print("woof", " " * 10)
sleep(1)
lines_down = 1
sleep(1)
print(cursor_down(lines_down), end='')
sleep(1)
print("woof-woof-woof", " " * 10)
sleep(1)
lines_up = 2
sleep(1)
print(cursor_up(lines_up), end='')
print("woof-woof", " " * 10)
sleep(1)
С этим пониманием можно свободно выводить в командной строке какую угодно информацию на множестве строк, постоянно обновлять её и одновременно писать в свой input.