Python – Imprimir un diccionario como una tabla horizontal con encabezados

Tengo un diccionario:

d = {1: ["Spices", math.floor(random.gauss(40, 5))], 2: ["Other stuff", math.floor(random.gauss(20, 5))], 3: ["Tea", math.floor(random.gauss(50, 5))], 10: ["Contraband", math.floor(random.gauss(1000, 5))], 5: ["Fruit", math.floor(random.gauss(10, 5))], 6: ["Textiles", math.floor(random.gauss(40, 5))] } 

Quiero imprimirlo para que se alinee bien con los encabezados. ¿Puedo agregar los encabezados al diccionario y siempre estar seguro de que salgan en la parte superior? He visto algunas formas de hacerlo verticalmente, pero me gustaría que salga con anchos de columna máximos cercanos al máximo str () o int ().

Ejemplo:

Tecla_ _ __ _ __ _ Etiqueta _ __ _ __ _ ___ Número
1 _ __ _ __ _ ___ Especias _ __ _ __ _ __ 42
2 _ __ _ __ _ ___ Otras cosas _ ____ _16
etc

Aparentemente, ni siquiera puedo hacer esto dentro de este editor manualmente, pero espero que la idea se presente. Tampoco quiero realmente el __ tampoco. Sólo un marcador de posición.
Gracias a todos.

Puede utilizar el formato de cadena :

 print "{:<8} {:<15} {:<10}".format('Key','Label','Number') for k, v in d.iteritems(): label, num = v print "{:<8} {:<15} {:<10}".format(k, label, num) 

Salida:

 Key Label Number 1 Spices 38.0 2 Other stuff 24.0 3 Tea 44.0 5 Fruit 5.0 6 Textiles 37.0 10 Contraband 1000.0 

Estaba buscando una solución con un ancho de columnas desconocido para imprimir una tabla de base de datos. Asi que aqui esta:

 def printTable(myDict, colList=None): """ Pretty print a list of dictionaries (myDict) as a dynamically sized table. If column names (colList) aren't specified, they will show in random order. Author: Thierry Husson - Use it as you want but don't blame me. """ if not colList: colList = list(myDict[0].keys() if myDict else []) myList = [colList] # 1st row = header for item in myDict: myList.append([str(item[col] or '') for col in colList]) colSize = [max(map(len,col)) for col in zip(*myList)] formatStr = ' | '.join(["{{:<{}}}".format(i) for i in colSize]) myList.insert(1, ['-' * i for i in colSize]) # Seperating line for item in myList: print(formatStr.format(*item)) 

Muestra:

 printTable([{'a':123,'bigtitle':456,'c':789},{'a':'x','bigtitle':'y','c':'z'}, \ {'a':'2016-11-02','bigtitle':1.2,'c':78912313213123}], ['a','bigtitle','c']) 

Salida:

 a | bigtitle | c ---------- | -------- | -------------- 123 | 456 | 789 x | y | z 2016-11-02 | 1.2 | 78912313213123 

En el contexto de Psycopg, puedes usarlo de esta manera:

 curPG.execute("SELECT field1, field2, ... fieldx FROM mytable") printTable(curPG.fetchall(), [c.name for c in curPG.description]) 

Si necesita una variante para filas de líneas múltiples, aquí está:

 def printTable(myDict, colList=None, sep='\uFFFA'): """ Pretty print a list of dictionaries (myDict) as a dynamically sized table. If column names (colList) aren't specified, they will show in random order. sep: row separator. Ex: sep='\n' on Linux. Default: dummy to not split line. Author: Thierry Husson - Use it as you want but don't blame me. """ if not colList: colList = list(myDict[0].keys() if myDict else []) myList = [colList] # 1st row = header for item in myDict: myList.append([str(item[col] or '') for col in colList]) colSize = [max(map(len,(sep.join(col)).split(sep))) for col in zip(*myList)] formatStr = ' | '.join(["{{:<{}}}".format(i) for i in colSize]) line = formatStr.replace(' | ','-+-').format(*['-' * i for i in colSize]) item=myList.pop(0); lineDone=False while myList: if all(not i for i in item): item=myList.pop(0) if line and (sep!='\uFFFA' or not lineDone): print(line); lineDone=True row = [i.split(sep,1) for i in item] print(formatStr.format(*[i[0] for i in row])) item = [i[1] if len(i)>1 else '' for i in row] 

Muestra:

 sampleDict = [{'multi lines title': 12, 'bigtitle': 456, 'third column': '7 8 9'}, {'multi lines title': 'wxy z', 'bigtitle': 'b1 b2', 'third column': 'zy x'}, {'multi lines title': '2', 'bigtitle': 1.2, 'third column': 78912313213123}] printTable(sampleDict, sep=' ') 

Salida:

 bigtitle | multi | third | lines | column | title | ---------+-------+--------------- 456 | 12 | 7 | | 8 | | 9 ---------+-------+--------------- b1 | w | z b2 | x | y | y | x | z | ---------+-------+--------------- 1.2 | 2 | 78912313213123 

Sin el parámetro sep , printTable(sampleDict) le ofrece:

 bigtitle | multi lines title | third column ---------+-------------------+--------------- 456 | 12 | 7 8 9 b1 b2 | wxyz | zyx 1.2 | 2 | 78912313213123 

Basándome en el código de Le Droid, agregué el separador ‘-‘ para cada fila, lo que podría aclarar la impresión. Gracias, Le Droid.

 def printTable(myDict, colList=None): if not colList: colList = list(myDict[0].keys() if myDict else []) myList = [colList] # 1st row = header for item in myDict: myList.append([str(item[col] or '') for col in colList]) #maximun size of the col for each element colSize = [max(map(len,col)) for col in zip(*myList)] #insert seperating line before every line, and extra one for ending. for i in range(0, len(myList)+1)[::-1]: myList.insert(i, ['-' * i for i in colSize]) #two format for each content line and each seperating line formatStr = ' | '.join(["{{:<{}}}".format(i) for i in colSize]) formatSep = '-+-'.join(["{{:<{}}}".format(i) for i in colSize]) for item in myList: if item[0][0] == '-': print(formatSep.format(*item)) else: print(formatStr.format(*item)) 

Salida:

 -----------+----------+--------------- a | bigtitle | c -----------+----------+--------------- 123 | 456 | 789 -----------+----------+--------------- x | y | z -----------+----------+--------------- 2016-11-02 | 1.2 | 78912313213123 -----------+----------+--------------- 

Puedes usar los métodos ljust o rjust string:

 print key.ljust(10), label.ljust(30), number.ljust(20)