#python #rich
#python #богатый
Вопрос:
Я использую Live
дисплей для отображения содержимого Table
, которое растет со временем. В конечном итоге происходит вертикальное переполнение, и в этом случае я бы хотел, чтобы самые старые (т. Е. Самые верхние) Строки Исчезли, в то время как самые последние строки должны отображаться вместе с заголовком, т. Е. Содержимое должно прокручиваться. vertical_overflow
Параметр live display предоставляет "visible"
опцию, но при этом заголовок таблицы исчезает. Очевидно, что это Table
специфическая проблема, поскольку заголовок должен оставаться, но содержимое должно прокручиваться.
import time
from rich.live import Live
from rich.table import Table
table = Table()
table.add_column('Time')
table.add_column('Message')
with Live(table, refresh_per_second=5, vertical_overflow='visible'):
for i in range(100):
time.sleep(0.2)
table.add_row(time.asctime(), f'Event {i:03d}')
Левая часть показывает поведение с vertical_overflow='visible'
, а правая часть показывает желаемое поведение:
Пока я использую обходной путь с отдельной структурой данных для хранения строк, а затем создаю таблицу с нуля каждый раз, когда нужно добавить новую строку. Это не кажется очень эффективным, поэтому мне интересно, есть ли лучшее решение. Этот обходной путь также не работает для многострочных строк, поскольку он считает их как одну строку (следовательно, произойдет переполнение).
from collections import deque
import os
import time
from rich.live import Live
from rich.table import Table
def generate_table(rows):
table = Table()
table.add_column('Time')
table.add_column('Message')
for row in rows:
table.add_row(*row)
return table
width, height = os.get_terminal_size()
messages = deque(maxlen=height-4) # save space for header and footer
with Live(generate_table(messages), refresh_per_second=5) as live:
for i in range(100):
time.sleep(0.2)
messages.append((time.asctime(), f'Event {i:03d}'))
live.update(generate_table(messages))
Ответ №1:
Недавно я работал над тем же самым и тоже не смог найти встроенное решение. Поскольку вы отображаете отображение в реальном времени, в таблице не будет более ~ 100 строк, поэтому эффективность не должна вызывать беспокойства.
Вот мое решение. Он повторно удаляет строки сверху, пока таблица не будет соответствовать. Это измеряется путем помещения таблицы в a Layout
, которая обрезает таблицу внизу, если она не подходит.
from collections import deque
import os
import time
from rich.live import Live
from rich.table import Table
from rich.layout import Layout
from rich.console import Console
def generate_table(rows):
layout = Layout()
console = Console()
table = Table()
table.add_column('Time')
table.add_column('Message')
rows = list(rows)
# This would also get the height:
# render_map = layout.render(console, console.options)
# render_map[layout].region.height
n_rows = os.get_terminal_size()[1]
while n_rows >= 0:
table = Table()
table.add_column('Time')
table.add_column('Message')
for row in rows[-n_rows:]:
table.add_row(*row)
layout.update(table)
render_map = layout.render(console, console.options)
if len(render_map[layout].render[-1]) > 2:
# The table is overflowing
n_rows -= 1
else:
break
return table
width, height = os.get_terminal_size()
messages = deque(maxlen=height-4) # save space for header and footer
with Live(generate_table(messages), refresh_per_second=5) as live:
for i in range(100):
time.sleep(0.2)
messages.append((time.asctime(), f'Event {i:03d}'))
live.update(generate_table(messages))
Волшебная строка здесь if len(render_map[layout].render[-1]) > 2:
.
Это простой способ определить, печатается ли таблица полностью.
Если это так, последний элемент render_map[layout].render
будет выглядеть так
[
Segment('└──────────────────────────┘', Style()),
Segment(' ',)
]
или как
[
Segment(
'
',
)
]
но если оно усечено, оно будет выглядеть так
[
Segment('│', Style()),
Segment(' ', Style()),
Segment(
'37',
Style(color=Color('cyan', ColorType.STANDARD, number=6), bold=True, italic=False)
),
Segment(' ', Style()),
Segment(' ', Style()),
Segment('│', Style()),
Segment(' ',)
]
Комментарии:
1. Это умное решение. Это кажется несколько странным, но это определенно решает проблему. И поскольку он использует только общедоступный API rich, он также кажется надежным / стабильным.
2. Я согласен, что это халтурно — я думаю, основная проблема заключается в том, что Rich заранее не знает, насколько большой будет таблица. Я бы предположил, что существуют и более надежные решения, но основная идея по-прежнему будет «попробуйте сделать это и посмотреть».