Как отображать динамические данные в табличном виде?

Рейтинг: 1Ответов: 2Опубликовано: 04.07.2023

Скрипт в цикле обрабатывает много файлов. Сейчас вывожу информацию о статусе построчно, отображаю много параметров. Хочу перейти на вывод только одного параметра для каждого файла : ОК и !ОК, при этом ограничить строку скажем на 20 значений. Следующие 20 значений отображать в новой строке. Но так как длина ОК и !ОК разная, то на экране не слишком красиво выходит. Пробовал Tabulate, но там вроде как только статика, т.е. сразу нужно написать в команду 20 значений, а хочется видеть постепенное появление ОК. "ОК" я взял для примера, скорее всего будут отображаться номера файлов, а они разной длины. Приводить к одной длине типа 0001,2001 пока не хочется. Какие есть варианты отображения значений в строку с фиксированным размером "ячейки" ?

Ответы

▲ 1Принят

Определяете максимальный размер данных после используете center - для выравнивания по центру ljust - выравнивания по правому краю или rjust - выравнивания по левому краю:

import random
import time

data = [(i, random.random() < 0.5) for i in range(1000)]

num_length = 5
data_length = len('!OK') + 1

for i in range(0, len(data), 20):
    for j in range(i, i + 20):
        time.sleep(0.05)
        row = (f"{str(data[j][0]).center(num_length)}"
               f"{(['OK', '!OK'][data[j][1]]).center(data_length)}|")
        print(row, end='')
    print()

Для того чтобы выводить во время работы, вы можете использовать curses (В pycharm нужно включить эмуляцию терминала):

import random
import time
import curses


def print_at(x_, y_, string):
    stdscr.addstr(y_, x_, string)
    stdscr.refresh()


stdscr = curses.initscr()

data = [(i, random.random() < 0.5) for i in range(50)]

num_length = 5
data_length = len('!OK') + 1
summary_length = (num_length + data_length + 1)

in_line = stdscr.getmaxyx()[1] // summary_length - 1
# Т.к. после перехода в обычный режим
# консоль очищается мы должны сохранить таблицу
result = ''

for i in range(0, len(data), in_line):
    for j in range(i, i + in_line):
        if j >= len(data):
            break
        x, y = (j - i) * summary_length, i // in_line + 1
        print_at(x, y, "Working...".center(summary_length))
        time.sleep(0.25)
        row = (f"{str(data[j][0]).center(num_length)}"
               f"{(['OK', '!OK'][data[j][1]]).center(data_length)}|")
        result += row
        print_at(x, y, row)
    result += '\n'

curses.endwin()

print(result)
# Продолжение кода
▲ 0

Вариант с +/- и номерами файлов

from random import random

for i in range(100):
    print(f"{i:5}{'+' if random() > 0.5 else '-'}", end='\n' if (i + 1) % 20 == 0 else '')
    0+    1+    2-    3-    4-    5-    6-    7-    8-    9+   10-   11+   12-   13-   14+   15+   16-   17+   18-   19+
   20-   21-   22-   23-   24-   25+   26+   27-   28-   29+   30-   31-   32+   33+   34+   35+   36+   37+   38-   39-
   40+   41-   42-   43-   44-   45-   46-   47+   48-   49-   50+   51+   52+   53+   54-   55-   56-   57+   58+   59-
   60+   61+   62+   63-   64+   65+   66-   67-   68-   69+   70+   71-   72+   73+   74+   75+   76+   77+   78-   79-
   80+   81+   82-   83-   84-   85+   86+   87+   88+   89+   90-   91-   92+   93-   94+   95-   96+   97-   98+   99+