E
E
Egor Moiseev2021-11-27 13:30:49
Python
Egor Moiseev, 2021-11-27 13:30:49

How to display a table in Python as in the example?

Yes, I know about PrettyTable. He is good.
But nowhere can I find an example of how to implement the following:

61a2078ef412b956718135.png

Moreover, the borders of the table are not really needed.
It is necessary that the line is a line, but with several substrings.
Each ip address has several parameters and I want them to be printed on a new line,
but in the same place where the same parameter is already printed on the main line.

Thanks in advance!

PS I read a ton of information about PrettyTable and analogues - it does not contain an example corresponding to my request.
Or tell me, please - how to get the coordinates of the place where the first element of the list / dictionary value was printed?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
V
Vindicar, 2021-11-27
@lesnoy88

Output to console?
Well, this is how I would approach it.
1. Convert all output data to strings and split them by line breaks.
2. Determine the maximum width of each column, taking into account line breaks. For each cell, we calculate the maximum width of the row, then we look for the maximum in the column. You can add 1-2 characters as "fields" if needed.
3. When outputting a string, output the cell strings together using itertools.zip_longest() . Those. first the first line in each cell, then the second, and so on. If we received None instead of one of the lines, then the lines in this cell have already ended - we output spaces.
We know the output width of each cell from point 2, it is trivial to align the value with spaces.

# -*- coding: utf-8 -*-
import typing as t
import itertools

def print_table(headers: t.Dict[str, str], data: t.Iterable[t.Dict[str, str]]) -> None:
    keys: t.List[str] = list(headers.keys()) #список ключей в таблице - чтобы сохранять порядок столбцов
    split_data: t.List[t.Dict[str, t.List[str]]] = [] #ячейки, разбитые на строки
    max_widths: t.Dict[str, int] = { key:len(value) for key,value in headers.items() } #ширина каждого столбца в таблице
    for line in data:
        #разбиваем ячейки строки на текстовые строки по \n
        split_line: t.Dict[str, t.List[str]] = { key:value.splitlines() for key,value in line.items() }
        #обновляем ширину столбцов, если надо
        for key in keys:
            new_width = max(map(len, split_line.get(key, [''])))
            if new_width > max_widths[key]:
                max_widths[key] = new_width
        split_data.append(split_line)
    #выводим заголовки
    for key in keys:
        print(f'{{0:<{max_widths[key]}}}'.format(headers[key]), end='|') #можно вместо | поставить пробел
    print()
    print( '+'.join('-'*v for v in max_widths.values()) + '|') #разделитель заголовка и тела таблицы
    #выводим строки таблицы
    for row in split_data:
        for parts in itertools.zip_longest(*(row[key] for key in keys)):
            #parts - кортеж, где каждый элемент либо строка в очередной ячейке, либо None
            for key,part in zip(keys, parts):
                #None означает, что в этой ячейке строки текста уже кончились
                print(f'{{0:<{max_widths[key]}}}'.format(part if part is not None else ''), end='|')
            print()
        print( '+'.join('-'*v for v in max_widths.values())  + '|') #разделитель строк, если надо

data = [
    {'ip':'192.168.0.2', 'model':'DES-3200-26', 'uptime': '3d 12:03:05', 'uplink state': '25: up\n26:up', 'uplink err': '0\n11', 'uplink mcast': '24560\n113'},
    {'ip':'192.168.0.2', 'model':'DES-3200-52', 'uptime': '1d 04:00:15', 'uplink state': '49: up\n50:up\n51:down\n52:down', 'uplink err': '10\n1133\n0\n0', 'uplink mcast': '5497812\n3145\n0\n0'},
]
headers = {'ip': 'IP address', 'model': 'Model', 'uptime': 'Uptime', 'uplink state': 'Uplink state', 'uplink err': 'Uplink errors', 'uplink mcast': 'Uplink M-cast'}
print_table(headers, data)

IP address |Model      |Uptime     |Uplink state|Uplink errors|Uplink M-cast|
-----------+-----------+-----------+------------+-------------+-------------|
192.168.0.2|DES-3200-26|3d 12:03:05|25: up      |0            |24560        |
           |           |           |26:up       |11           |113          |
-----------+-----------+-----------+------------+-------------+-------------|
192.168.0.2|DES-3200-52|1d 04:00:15|49: up      |10           |5497812      |
           |           |           |50:up       |1133         |3145         |
           |           |           |51:down     |0            |0            |
           |           |           |52:down     |0            |0            |
-----------+-----------+-----------+------------+-------------+-------------|

D
Drill, 2021-11-29
@Drill

Actually, Prettytable understands multirow

data = [
    {'ip':'192.168.0.2', 'model':'DES-3200-26', 'uptime': '3d 12:03:05', 'uplink state': '25: up\n26: up', 'uplink err': '0\n11', 'uplink mcast': '24560\n113'},
    {'ip':'192.168.0.3', 'model':'DES-3200-52', 'uptime': '1d 04:00:15', 'uplink state': '49: up\n50: up\n51: down\n52: down', 'uplink err': '10\n1133\n0\n0', 'uplink mcast': '5497812\n3145\n0\n0'},
]

def set_data_for_PrettyTable(data):
    field_names = data[0].keys()
    rows = []
    for row in data:
        rows.append(row.values())
    return field_names, rows

field_names, rows = set_data_for_PrettyTable(data)

table = PrettyTable()
table.hrules = 1
table.field_names = field_names
table.add_rows(rows)
table.align["uplink state"] = "l"
print(table)

+-------------+-------------+-------------+--------------+------------+--------------+
|      ip     |    model    |    uptime   | uplink state | uplink err | uplink mcast |
+-------------+-------------+-------------+--------------+------------+--------------+
| 192.168.0.2 | DES-3200-26 | 3d 12:03:05 | 25: up       |     0      |    24560     |
|             |             |             | 26: up       |     11     |     113      |
+-------------+-------------+-------------+--------------+------------+--------------+
| 192.168.0.3 | DES-3200-52 | 1d 04:00:15 | 49: up       |     10     |   5497812    |
|             |             |             | 50: up       |    1133    |     3145     |
|             |             |             | 51: down     |     0      |      0       |
|             |             |             | 52: down     |     0      |      0       |
+-------------+-------------+-------------+--------------+------------+--------------+

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question