utilizar imprimir codigo python ascii tabular

codigo - ¿Cómo puedo imprimir bastante las tablas ASCII con Python?



imprimir codigo ascii en python (13)

Estoy buscando una biblioteca de Python para imprimir tablas como esta:

======================= | column 1 | column 2 | ======================= | value1 | value2 | | value3 | value4 | =======================

Me pareció asciitable pero no hace los bordes, etc. No necesito ningún formato complejo de elementos de datos, solo son cadenas. Lo necesito para auto-tamaño de columnas.

¿Existe tal cosa o necesito dedicar unos minutos a escribir la mía?


Acabo de lanzar asciiplotlib , y también tiene bonitas tablas. Por ejemplo, esto

import asciiplotlib as apl data = [ [["a", "bb", "ccc"]], [[1, 2, 3], [613.23236243236, 613.23236243236, 613.23236243236]], ] fig = apl.figure() fig.table(data, border_style="thin", ascii_mode=True, padding=(0, 1), alignment="lcr") fig.show()

te lleva

+-----------------+-----------------+-----------------+ | a | bb | ccc | +=================+=================+=================+ | 1 | 2 | 3 | +-----------------+-----------------+-----------------+ | 613.23236243236 | 613.23236243236 | 613.23236243236 | +-----------------+-----------------+-----------------+

De forma predeterminada, la tabla se representa con caracteres de dibujo de cuadro Unicode,

┌─────────────────┬─────────────────┬─────────────────┐ │ a │ bb │ ccc │ ╞═════════════════╪═════════════════╪═════════════════╡ │ 1 │ 2 │ 3 │ ├─────────────────┼─────────────────┼─────────────────┤ │ 613.23236243236 │ 613.23236243236 │ 613.23236243236 │ └─────────────────┴─────────────────┴─────────────────┘

las tablas de apl son muy configurables; echa un vistazo a las pruebas para ver más ejemplos.


Aquí está mi solución:

def make_table(columns, data): """Create an ASCII table and return it as a string. Pass a list of strings to use as columns in the table and a list of dicts. The strings in ''columns'' will be used as the keys to the dicts in ''data.'' Not all column values have to be present in each data dict. >>> print(make_table(["a", "b"], [{"a": "1", "b": "test"}])) | a | b | |----------| | 1 | test | """ # Calculate how wide each cell needs to be cell_widths = {} for c in columns: values = [str(d.get(c, "")) for d in data] cell_widths[c] = len(max(values + [c])) # Used for formatting rows of data row_template = "|" + " {} |" * len(columns) # CONSTRUCT THE TABLE # The top row with the column titles justified_column_heads = [c.ljust(cell_widths[c]) for c in columns] header = row_template.format(*justified_column_heads) # The second row contains separators sep = "|" + "-" * (len(header) - 2) + "|" # Rows of data rows = [] for d in data: fields = [str(d.get(c, "")).ljust(cell_widths[c]) for c in columns] row = row_template.format(*fields) rows.append(row) return "/n".join([header, sep] + rows)


Aquí hay una pequeña función rápida y sucia que escribí para mostrar los resultados de las consultas SQL que solo puedo hacer sobre una API SOAP. Espera una entrada de una secuencia de una o más namedtuples como filas de la tabla. Si solo hay un registro, lo imprime de manera diferente.

Es útil para mí y podría ser un punto de partida para ti:

def pprinttable(rows): if len(rows) > 1: headers = rows[0]._fields lens = [] for i in range(len(rows[0])): lens.append(len(max([x[i] for x in rows] + [headers[i]],key=lambda x:len(str(x))))) formats = [] hformats = [] for i in range(len(rows[0])): if isinstance(rows[0][i], int): formats.append("%%%dd" % lens[i]) else: formats.append("%%-%ds" % lens[i]) hformats.append("%%-%ds" % lens[i]) pattern = " | ".join(formats) hpattern = " | ".join(hformats) separator = "-+-".join([''-'' * n for n in lens]) print hpattern % tuple(headers) print separator _u = lambda t: t.decode(''UTF-8'', ''replace'') if isinstance(t, str) else t for line in rows: print pattern % tuple(_u(t) for t in line) elif len(rows) == 1: row = rows[0] hwidth = len(max(row._fields,key=lambda x: len(x))) for i in range(len(row)): print "%*s = %s" % (hwidth,row._fields[i],row[i])

Muestra de salida:

pkid | fkn | npi -------------------------------------+--------------------------------------+---- 405fd665-0a2f-4f69-7320-be01201752ec | 8c9949b9-552e-e448-64e2-74292834c73e | 0 5b517507-2a42-ad2e-98dc-8c9ac6152afa | f972bee7-f5a4-8532-c4e5-2e82897b10f6 | 0 2f960dfc-b67a-26be-d1b3-9b105535e0a8 | ec3e1058-8840-c9f2-3b25-2488f8b3a8af | 1 c71b28a3-5299-7f4d-f27a-7ad8aeadafe0 | 72d25703-4735-310b-2e06-ff76af1e45ed | 0 3b0a5021-a52b-9ba0-1439-d5aafcf348e7 | d81bb78a-d984-e957-034d-87434acb4e97 | 1 96c36bb7-c4f4-2787-ada8-4aadc17d1123 | c171fe85-33e2-6481-0791-2922267e8777 | 1 95d0f85f-71da-bb9a-2d80-fe27f7c02fe2 | 226f964c-028d-d6de-bf6c-688d2908c5ae | 1 132aa774-42e5-3d3f-498b-50b44a89d401 | 44e31f89-d089-8afc-f4b1-ada051c01474 | 1 ff91641a-5802-be02-bece-79bca993fdbc | 33d8294a-053d-6ab4-94d4-890b47fcf70d | 1 f3196e15-5b61-e92d-e717-f00ed93fe8ae | 62fa4566-5ca2-4a36-f872-4d00f7abadcf | 1

Ejemplo

>>> from collections import namedtuple >>> Row = namedtuple(''Row'',[''first'',''second'',''third'']) >>> data = Row(1,2,3) >>> data Row(first=1, second=2, third=3) >>> pprinttable([data]) first = 1 second = 2 third = 3 >>> pprinttable([data,data]) first | second | third ------+--------+------ 1 | 2 | 3 1 | 2 | 3


Esto puede hacerse solo con módulos integrados de forma bastante compacta utilizando listas y comprensiones de cadenas. Acepta una lista de diccionarios con el mismo formato ...

def tableit(dictlist): lengths = [ max(map(lambda x:len(x.get(k)), dictlist) + [len(k)]) for k in dictlist[0].keys() ] lenstr = " | ".join("{:<%s}" % m for m in lengths) lenstr += "/n" outmsg = lenstr.format(*dictlist[0].keys()) outmsg += "-" * (sum(lengths) + 3*len(lengths)) outmsg += "/n" outmsg += "".join( lenstr.format(*v) for v in [ item.values() for item in dictlist ] ) return outmsg


Hace mucho tiempo que leí esta pregunta y terminé de escribir mi propia bonita impresora para tablas: tabulate .

Mi caso de uso es:

  • Quiero un one-liner la mayor parte del tiempo
  • que es lo suficientemente inteligente como para encontrar el mejor formato para mí
  • y puede dar salida a diferentes formatos de texto sin formato

Dado su ejemplo, la grid es probablemente el formato de salida más similar:

from tabulate import tabulate print tabulate([["value1", "value2"], ["value3", "value4"]], ["column 1", "column 2"], tablefmt="grid") +------------+------------+ | column 1 | column 2 | +============+============+ | value1 | value2 | +------------+------------+ | value3 | value4 | +------------+------------+

Otros formatos compatibles son plain (sin líneas), simple (tablas simples de Pandoc), pipe (como tablas en PHP Markdown Extra), orgtbl (como tablas en el modo orgtbl de Emacs), rst (como tablas simples en reStructuredText). grid y orgtbl son fácilmente editables en Emacs.

En cuanto al rendimiento, tabulate es ligeramente más lento que asciitable , pero mucho más rápido que PrettyTable y texttable .

PD. También soy un gran fan de alinear números por una columna decimal . Así que esta es la alineación predeterminada para los números si hay alguno (overridable).


Por alguna razón, cuando incluí ''docutils'' en mis búsquedas de google me tropecé con texttable , que parece ser lo que estoy buscando.


Puedes probar BeautifulTable . Hace lo que quieres hacer. Aquí hay un ejemplo de su documentation

>>> from beautifultable import BeautifulTable >>> table = BeautifulTable() >>> table.column_headers = ["name", "rank", "gender"] >>> table.append_row(["Jacob", 1, "boy"]) >>> table.append_row(["Isabella", 1, "girl"]) >>> table.append_row(["Ethan", 2, "boy"]) >>> table.append_row(["Sophia", 2, "girl"]) >>> table.append_row(["Michael", 3, "boy"]) >>> print(table) +----------+------+--------+ | name | rank | gender | +----------+------+--------+ | Jacob | 1 | boy | +----------+------+--------+ | Isabella | 1 | girl | +----------+------+--------+ | Ethan | 2 | boy | +----------+------+--------+ | Sophia | 2 | girl | +----------+------+--------+ | Michael | 3 | boy | +----------+------+--------+


Sé que la pregunta es un poco vieja, pero aquí está mi intento de esto:

https://gist.github.com/lonetwin/4721748

Es un poco más fácil de leer en mi humilde opinión (aunque no distingue entre filas simples / múltiples como las soluciones de @ MattH, ni usa NamedTuples).


Si quieres una tabla con tramos de columna y fila, prueba la dashtable biblioteca

from dashtable import data2rst table = [ ["Header 1", "Header 2", "Header3", "Header 4"], ["row 1", "column 2", "column 3", "column 4"], ["row 2", "Cells span columns.", "", ""], ["row 3", "Cells/nspan rows.", "- Cells/n- contain/n- blocks", ""], ["row 4", "", "", ""] ] # [Row, Column] pairs of merged cells span0 = ([2, 1], [2, 2], [2, 3]) span1 = ([3, 1], [4, 1]) span2 = ([3, 3], [3, 2], [4, 2], [4, 3]) my_spans = [span0, span1, span2] print(data2rst(table, spans=my_spans, use_headers=True))

Qué salidas:

+----------+------------+----------+----------+ | Header 1 | Header 2 | Header3 | Header 4 | +==========+============+==========+==========+ | row 1 | column 2 | column 3 | column 4 | +----------+------------+----------+----------+ | row 2 | Cells span columns. | +----------+----------------------------------+ | row 3 | Cells | - Cells | +----------+ span rows. | - contain | | row 4 | | - blocks | +----------+------------+---------------------+


Versión que usa w3m diseñada para manejar los tipos que acepta la versión de MattH:

import subprocess import tempfile import html def pprinttable(rows): esc = lambda x: html.escape(str(x)) sour = "<table border=1>" if len(rows) == 1: for i in range(len(rows[0]._fields)): sour += "<tr><th>%s<td>%s" % (esc(rows[0]._fields[i]), esc(rows[0][i])) else: sour += "<tr>" + "".join(["<th>%s" % esc(x) for x in rows[0]._fields]) sour += "".join(["<tr>%s" % "".join(["<td>%s" % esc(y) for y in x]) for x in rows]) with tempfile.NamedTemporaryFile(suffix=".html") as f: f.write(sour.encode("utf-8")) f.flush() print( subprocess .Popen(["w3m","-dump",f.name], stdout=subprocess.PIPE) .communicate()[0].decode("utf-8").strip() ) from collections import namedtuple Row = namedtuple(''Row'',[''first'',''second'',''third'']) data1 = Row(1,2,3) data2 = Row(4,5,6) pprinttable([data1]) pprinttable([data1,data2])

resultados en:

┌───────┬─┐ │ first │1│ ├───────┼─┤ │second │2│ ├───────┼─┤ │ third │3│ └───────┴─┘ ┌─────┬───────┬─────┐ │first│second │third│ ├─────┼───────┼─────┤ │1 │2 │3 │ ├─────┼───────┼─────┤ │4 │5 │6 │ └─────┴───────┴─────┘


Yo también escribí mi propia solución a esto. Traté de mantenerlo simple.

https://github.com/Robpol86/terminaltables

from terminaltables import AsciiTable table_data = [ [''Heading1'', ''Heading2''], [''row1 column1'', ''row1 column2''], [''row2 column1'', ''row2 column2''] ] table = AsciiTable(table_data) print table.table +--------------+--------------+ | Heading1 | Heading2 | +--------------+--------------+ | row1 column1 | row1 column2 | | row2 column1 | row2 column2 | +--------------+--------------+ table.inner_heading_row_border = False print table.table +--------------+--------------+ | Heading1 | Heading2 | | row1 column1 | row1 column2 | | row2 column1 | row2 column2 | +--------------+--------------+ table.inner_row_border = True table.justify_columns[1] = ''right'' table.table_data[1][1] += ''/nnewline'' print table.table +--------------+--------------+ | Heading1 | Heading2 | +--------------+--------------+ | row1 column1 | row1 column2 | | | newline | +--------------+--------------+ | row2 column1 | row2 column2 | +--------------+--------------+


Yo uso esta pequeña función de utilidad.

def get_pretty_table(iterable, header): max_len = [len(x) for x in header] for row in iterable: row = [row] if type(row) not in (list, tuple) else row for index, col in enumerate(row): if max_len[index] < len(str(col)): max_len[index] = len(str(col)) output = ''-'' * (sum(max_len) + 1) + ''/n'' output += ''|'' + ''''.join([h + '' '' * (l - len(h)) + ''|'' for h, l in zip(header, max_len)]) + ''/n'' output += ''-'' * (sum(max_len) + 1) + ''/n'' for row in iterable: row = [row] if type(row) not in (list, tuple) else row output += ''|'' + ''''.join([str(c) + '' '' * (l - len(str(c))) + ''|'' for c, l in zip(row, max_len)]) + ''/n'' output += ''-'' * (sum(max_len) + 1) + ''/n'' return output print get_pretty_table([[1, 2], [3, 4]], [''header 1'', ''header 2''])

salida

----------------- |header 1|header 2| ----------------- |1 |2 | |3 |4 | -----------------


from sys import stderr, stdout def create_table(table: dict, full_row: bool = False) -> None: min_len = len(min((v for v in table.values()), key=lambda q: len(q))) max_len = len(max((v for v in table.values()), key=lambda q: len(q))) if min_len < max_len: stderr.write("Table is out of shape, please make sure all columns have the same length.") stderr.flush() return additional_spacing = 1 heading_separator = ''| '' horizontal_split = ''| '' rc_separator = '''' key_list = list(table.keys()) rc_len_values = [] for key in key_list: rc_len = len(max((v for v in table[key]), key=lambda q: len(str(q)))) rc_len_values += ([rc_len, [key]] for n in range(len(table[key]))) heading_line = (key + (" " * (rc_len + (additional_spacing + 1)))) + heading_separator stdout.write(heading_line) rc_separator += ("-" * (len(key) + (rc_len + (additional_spacing + 1)))) + ''+-'' if key is key_list[-1]: stdout.flush() stdout.write(''/n'' + rc_separator + ''/n'') value_list = [v for vl in table.values() for v in vl] aligned_data_offset = max_len row_count = len(key_list) next_idx = 0 newline_indicator = 0 iterations = 0 for n in range(len(value_list)): key = rc_len_values[next_idx][1][0] rc_len = rc_len_values[next_idx][0] line = (''{:{}} '' + " " * len(key)).format(value_list[next_idx], str(rc_len + additional_spacing)) + horizontal_split if next_idx >= (len(value_list) - aligned_data_offset): next_idx = iterations + 1 iterations += 1 else: next_idx += aligned_data_offset if newline_indicator >= row_count: if full_row: stdout.flush() stdout.write(''/n'' + rc_separator + ''/n'') else: stdout.flush() stdout.write(''/n'') newline_indicator = 0 stdout.write(line) newline_indicator += 1 stdout.write(''/n'' + rc_separator + ''/n'') stdout.flush()

Ejemplo:

table = { "uid": ["0", "1", "2", "3"], "name": ["Jon", "Doe", "Lemma", "Hemma"] } create_table(table)

Salida:

uid | name | ------+------------+- 0 | Jon | 1 | Doe | 2 | Lemma | 3 | Hemma | ------+------------+-