97 votes

Python: de jolies tables ascii?

Je cherche une bibliothèque python pour imprimer des tables comme celle-ci:

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

J'ai trouvé asciitable, mais cela ne fait pas les frontières, etc. Je n'ai besoin d'aucun formatage complexe d'éléments de données, ce sont juste des chaînes. J'en ai besoin pour dimensionner automatiquement les colonnes.

Existe-t-il une telle chose ou dois-je passer quelques minutes à écrire moi-même?

98voto

sastanin Points 16061

J'ai lu cette question depuis longtemps, et a terminé l'écriture de mon propre imprimeur pour les tableaux: tabulate.

Mon cas d'utilisation est:

  • Je veux un one-liner, la plupart du temps
  • ce qui est assez intelligent pour comprendre la meilleure mise en forme pour moi
  • et pouvez de sortie différente de la plaine-formats de texte

Compte tenu de votre exemple, grid est probablement le plus semblable format de sortie:

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

D'autres formats pris en charge, plain (pas de lignes), simple (Pandoc les tableaux simples), pipe (comme les tableaux en PHP Markdown Extra), orgtbl (les tables dans Emacs' org-mode), rst (comme de simples tables en reStructuredText). grid et orgtbl sont facilement modifiables dans Emacs.

Performance sage, tabulate est légèrement plus lent que l' asciitable, mais beaucoup plus vite qu' PrettyTable et texttable.

P. S. je suis également un grand fan de l'alignement de chiffres par un nombre décimal de la colonne. Donc, c'est l'alignement par défaut pour les nombres, si il y a de tout (substituables).

40voto

MattH Points 15352

Voici un moyen rapide et sale petite fonction que j'ai écrit pour l'affichage des résultats à partir de requêtes SQL, je ne peux que faire sur une API SOAP. Il s'attend à une entrée d'une séquence d'un ou de plusieurs namedtuples comme les lignes de la table. Si il n'y a qu'un seul enregistrement, qu'il imprime différemment.

Il est pratique pour moi et pourrait être un point de départ pour vous:

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
    for line in rows:
      print pattern % tuple(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])

Exemple de sortie:

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

Exemple

>>> 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

20voto

kdt Points 6185

Pour une raison quelconque, lorsque j'ai inclus «docutils» dans mes recherches google, je suis tombé sur une table de texte , ce qui semble être ce que je recherche.

17voto

clh Points 471

ok vieux fil, mais le meilleur que j'ai trouvé pour cela est Prettytable ... y a-t-il mieux?

14voto

Robpol86 Points 116

Moi aussi j'ai écrit ma propre solution à cela. J'ai essayé de garder les choses simples.

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 |
+--------------+--------------+
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X