def tableize(obj): colwidths = [] if type(obj) == list: obj = tuple(obj) #make sure we have an iterator of dicts, or a dictionary #import ipdb; ipdb.set_trace() if not(obj and isinstance(obj, dict) or (getattr(obj, '__iter__', False) \ and not [x for x in obj if not isinstance(x,dict)])): raise TypeError("Object must be a dictionary or list/tuple/iterable of dictionaries") if type(obj) == dict: #convert to tuple of tuples obj = tuple([((('key',k),('value',v))) for k,v in obj.items()]) #Convert to tuple of tuples obj = tuple([type(d)==dict and tuple(d.items()) or d for d in obj]) #make sure each dict has the same keys keys = [k for k,v in obj[0]] try: [[dict(d)[k] for k in keys] for d in obj] except KeyError: assert False, "Dictionary keys do not match" #get column widths col_widths = dict([(k, len(k)) for k in keys]) for row in obj: for k,v in row: if len(str(dict(row)[k])) > col_widths.get(k): col_widths[k] = len(str(dict(row)[k])) # build separator sep = '+'+'+'.join(['-'*(col_widths[k]+2) for k in keys])+'+' # print table headers lines = [] lines.append(sep) lines.append('| '+' | '.join([k.ljust(col_widths[k]) for k in keys])+' |') lines.append(sep) # print table rows for row in obj: lines.append('| '+' | '.join([str(v).ljust(col_widths[k]) for k,v in row])+' |') lines.append(sep) return '\n'.join(lines) def ptable(obj): print tableize(obj)