Стереть весь вывод программы
Когда закрывается приложение написанное при помощи библиотеки на подобии ncurses (vim, mc, htop) - его вывод (интерфейс) пропадает и курсор приглашения ввода переходит на следующую строку (будто вывода и не было). Как это можно реализовать на Python без ncurses или подобных библиотек типа termbox, npyscreen и подобных?
Ответы (3 шт):
Чуток нето, но можно затирать строку после каждого вывода.
import time
for i in range(30):
print(i, end='')
print('\r', end='')
time.sleep(0.1)
Весь вывод в 1 строчку.нет захламления консоли и нечего очищать.
ncurses делает это через создание нового терминала
root@route:~# ls /dev/pts/
0 1 2 3 4 5 6 ptmx
root@route:~# mc
root@route:~# ls /dev/pts/
0 1 2 3 4 5 6 7 8 ptmx
7 - окошко, 8 - командная строка снизу
Как он это делает точно не знаю, но мне кажется через подмену дескриптора управляющего терминала.
1.
Как это можно реализовать на Python без ncurses или подобных библиотек?
Можно сделать также как ncurses - с помощью альтернативного буфера экрана The Alternate Screen Buffer.
Не все терминалы обладают данной функциональностью - например, виртуальный терминал (tty). Если запустите top или less в tty терминале, то увидете, что предыдущее содержимое экрана уходит вверх после запуска подобных программ. Узнать тип терминала можно с помощью команды echo $TERM.
Код для xterm-256color терминала:
from time import sleep
print("\033[?1049h", end='') # Переключиться на альтернативные буфер экрана
print("\033[H", end='') # Установить курсор в левый верхний угол
print("Alternate_screen_string_1")
print("Alternate_screen_string_2")
print("Alternate_screen_string_3")
print("Alternate_screen_string_4")
print("Alternate_screen_string_5")
print("Alternate_screen_string_6")
sleep(3) # Пауза нужна, чтобы успеть увидеть содержимое альтернативного буфера
print("\033[?1049l", end='') # Переключиться на обычный буфер экрана
2.
Как работает ncurses программа можно посмотреть следующим образом:
2.1. Создаём минимальную программу c ncurses:
#include <ncurses.h>
int main()
{
napms(25000); /* Пауза нужна, чтобы было время поймать процесс с помощью strace */
initscr();
printw("Hello World !!!");
refresh();
endwin();
return 0;
}
2.2. Компилируем и запускаем:
gcc curses_hello_world.c -o curses_hello_world -lncurses
./curses_hello_world
2.3. Переходим в другой терминал и подключаемся к процессу curses_hello_world:
sudo strace -s 99 -p $(pgrep curses_hello_wo) 2>&1 | less
2.4. Ждём 25 секунд и получаем системные вызовы, которые делала наша программа во время работы. В данном случае нас интересует системные вызовы write:
write(1, "\33[?1049h\33[22;0;0t\33[1;39r\33(B\33[m\33[4l\33[?7h\33[H\33[2J", 46) = 46
write(1, "Hello World !!!", 15) = 15
write(1, "\33[39;1H\33[?1049l\33[23;0;0t\r\33[?1l\33>", 32) = 32
С расшифровкой этих эскейп последовательностей мне помогли здесь (на английском).