An adapted version of a similar stack-overflow answer.
The primary tweaks made are to ensure the columns actually take the width of values into account
Accepts two lists
Any keys present in data which haven't been specified in columns are ignored
# Adapted From http://stackoverflow.com/questions/5909873/how-can-i-pretty-print-ascii-tables-with-python
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.'
"""
# Calculate how wide each cell needs to be
cell_widths = {}
for c in columns:
lens = []
values = [lens.append(len(str(d.get(c, "")))) for d in data]
lens.append(len(c))
lens.sort()
cell_widths[c] = max(lens)
# 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) + "|"
end = "-" * len(header)
# 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)
rows.append(end)
return "\n".join([header, sep] + rows)
cols = ["daynumber", "day", "weather"]
data = [
{"day": "Sunday", "daynumber": 0, "weather": "poor", "year": 2016},
{"day": "Monday", "daynumber": 1, "weather": "worse", "year": 2016},
{"day": "Tuesday", "daynumber": 2, "weather": "better", "year": 2016},
{"day": "Wednesday", "daynumber": 3, "weather": "overcast", "year": 2016},
{"day": "Thursday", "daynumber": 4, "weather": "depressing", "year": 2016},
{"day": "Friday", "daynumber": 5, "weather": "stay inside", "year": 2016},
{"day": "Saturday", "daynumber": 6, "weather": "poor", "year": 2016}
]
print make_table(cols,data)
| daynumber | day | weather | |-------------------------------------| | 0 | Sunday | poor | | 1 | Monday | worse | | 2 | Tuesday | better | | 3 | Wednesday | overcast | | 4 | Thursday | depressing | | 5 | Friday | stay inside | | 6 | Saturday | poor | ---------------------------------------