Python으로 ASCII 테이블을 어떻게 예쁘게 인쇄 할 수 있습니까?
다음과 같이 테이블을 예쁘게 인쇄하는 방법을 찾고 있습니다.
=======================
| column 1 | column 2 |
=======================
| value1 | value2 |
| value3 | value4 |
=======================
asciitable 라이브러리를 찾았 지만 테두리 등을 수행하지 않습니다. 복잡한 데이터 항목 서식이 필요하지 않으며 문자열 일뿐입니다. 열 크기를 자동으로 조정하는 데 필요합니다.
다른 라이브러리 또는 메소드가 존재합니까? 아니면 직접 작성하는 데 몇 분을 소비해야합니까?
나는이 질문을 오래 전에 읽었고 테이블에 대한 내 자신의 예쁜 프린터 작성을 마쳤습니다 tabulate
..
내 사용 사례는 다음과 같습니다.
- 나는 대부분의 경우 한 줄짜리를 원합니다.
- 나에게 가장 적합한 형식을 찾을 수있을만큼 똑똑합니다.
- 다른 일반 텍스트 형식을 출력 할 수 있습니다.
예를 들어, grid
아마도 가장 유사한 출력 형식 일 것입니다.
from tabulate import tabulate
print tabulate([["value1", "value2"], ["value3", "value4"]], ["column 1", "column 2"], tablefmt="grid")
+------------+------------+
| column 1 | column 2 |
+============+============+
| value1 | value2 |
+------------+------------+
| value3 | value4 |
+------------+------------+
기타 지원되는 형식은 plain
(줄 없음), simple
(Pandoc 단순 테이블), pipe
(PHP Markdown Extra의 orgtbl
테이블과 같음 ), (Emacs의 조직 모드의 rst
테이블과 같음 ), (reStructuredText의 단순 테이블과 같음)입니다. grid
그리고 orgtbl
쉽게 이맥스에서 편집 할 수 있습니다.
성능 측면에서는 tabulate
보다 약간 느리지 asciitable
만 PrettyTable
및 보다 훨씬 빠릅니다 texttable
.
추신 나는 또한 소수 열로 숫자를 정렬하는 것을 좋아 합니다. 따라서 이것은 숫자에 대한 기본 정렬입니다 (재정의 가능).
다음은 SOAP API를 통해서만 만들 수있는 SQL 쿼리의 결과를 표시하기 위해 작성한 빠르고 더러운 함수입니다. 하나 이상의 시퀀스 입력을 namedtuples
테이블 행으로 예상합니다 . 레코드가 하나만 있으면 다르게 인쇄합니다.
나에게 편리하고 시작점이 될 수 있습니다.
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])
샘플 출력 :
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
예
>>> 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
어떤 이유로 Google 검색에 'docutils'를 포함했을 때 texttable을 우연히 발견 했습니다 . 이것은 내가 찾고있는 것 같습니다.
나도 이것에 대한 내 자신의 해결책을 썼습니다. 나는 그것을 단순하게 유지하려고 노력했다.
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 |
+--------------+--------------+
유형을 처리하도록 설계된 w3m을 사용하는 버전 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])
결과 :
┌───────┬─┐
│ first │1│
├───────┼─┤
│second │2│
├───────┼─┤
│ third │3│
└───────┴─┘
┌─────┬───────┬─────┐
│first│second │third│
├─────┼───────┼─────┤
│1 │2 │3 │
├─────┼───────┼─────┤
│4 │5 │6 │
└─────┴───────┴─────┘
열 및 행 범위가있는 테이블을 원한다면 내 라이브러리 대시 테이블을 사용해보십시오
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))
출력되는 내용 :
+----------+------------+----------+----------+
| 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 |
+----------+------------+---------------------+
BeautifulTable 을 사용해 볼 수 있습니다 . 당신이하고 싶은 일을합니다. 다음은 문서 의 예입니다.
>>> 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 |
+----------+------+--------+
나는 질문이 조금 오래되었다는 것을 알고 있지만 여기에 대한 나의 시도가 있습니다.
https://gist.github.com/lonetwin/4721748
좀 더 읽기 쉬운 IMHO입니다 (@MattH의 솔루션과 같이 단일 / 다중 행을 구분하지 않고 NamedTuples를 사용하지도 않음).
이 작은 유틸리티 기능을 사용합니다.
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'])
산출
-----------------
|header 1|header 2|
-----------------
|1 |2 |
|3 |4 |
-----------------
이 목적을 위해 방금 용어 표 를 출시 했습니다 . 예를 들어,
import termtables as tt
string = tt.to_string(
[[1, 2, 3], [613.23236243236, 613.23236243236, 613.23236243236]],
header=["a", "bb", "ccc"],
style=tt.styles.ascii_thin_double,
padding=(0, 1),
alignment="lcr"
)
print(string)
당신을 얻습니다
+-----------------+-----------------+-----------------+
| a | bb | ccc |
+=================+=================+=================+
| 1 | 2 | 3 |
+-----------------+-----------------+-----------------+
| 613.23236243236 | 613.23236243236 | 613.23236243236 |
+-----------------+-----------------+-----------------+
기본적으로 테이블은 유니 코드 상자 그리기 문자로 렌더링됩니다 .
┌─────────────────┬─────────────────┬─────────────────┐
│ a │ bb │ ccc │
╞═════════════════╪═════════════════╪═════════════════╡
│ 1 │ 2 │ 3 │
├─────────────────┼─────────────────┼─────────────────┤
│ 613.23236243236 │ 613.23236243236 │ 613.23236243236 │
└─────────────────┴─────────────────┴─────────────────┘
termtable은 매우 구성 가능합니다. 더 많은 예를 보려면 테스트 를 확인하십시오 .
내 해결책은 다음과 같습니다.
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)
이것은 목록 및 문자열 이해를 사용하여 상당히 간결하게 내장 모듈로만 수행 할 수 있습니다. 동일한 형식의 사전 목록을 모두 허용합니다.
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
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()
예:
table = {
"uid": ["0", "1", "2", "3"],
"name": ["Jon", "Doe", "Lemma", "Hemma"]
}
create_table(table)
산출:
uid | name |
------+------------+-
0 | Jon |
1 | Doe |
2 | Lemma |
3 | Hemma |
------+------------+-
참고 URL : https://stackoverflow.com/questions/5909873/how-can-i-pretty-print-ascii-tables-with-python
'IT Share you' 카테고리의 다른 글
Eclipse에서 LogCat 실행이 중지되면 다시 시작해야 함 (0) | 2020.12.03 |
---|---|
파일 찾기에서 정규식을 사용하는 방법 (0) | 2020.12.03 |
setCurrentItem (0)을 호출 할 때 onPageSelected가 트리거되지 않습니다. (0) | 2020.12.03 |
PHP를 사용한 Python SimpleHTTPServer (0) | 2020.12.03 |
Mac OSX Java 터미널 버전이 잘못되었습니다. (0) | 2020.12.03 |