¿Cómo obtengo una lista de nombres de columna de un cursor psycopg2?

137

Me gustaría una forma general de generar etiquetas de columna directamente a partir de los nombres de columna seleccionados, y recuerdo haber visto que el módulo psycopg2 de python admite esta función.

Setjmp
fuente

Respuestas:

224

De "Programming Python" de Mark Lutz:

curs.execute("Select * FROM people LIMIT 0")
colnames = [desc[0] for desc in curs.description]
Setjmp
fuente
64
Si solo desea los nombres de columna, no seleccione todas las filas de la tabla. Esto es más eficiente:curs.execute("SELECT * FROM people LIMIT 0")
Demitri
2
Puede valer la pena agregar que esto funciona tanto para las vistas como para las tablas, mientras que no es (fácilmente) posible obtener nombres de columnas para las vistas information_schema.
wjv
55
Podría ser más intuitivo obtener el nombre como un atributo: colnames = [desc.name para desc en curs.description]
rovyko
Es importante tener en cuenta que los nombres de columna leídos de la función de descripción del cursor aparecen en minúsculas. curs.execute("Select userId FROM people") colnames = [desc[0] for desc in curs.description] assert colnames == ['userid']
dyltini el
Debes actualizar tu respuesta con la sugerencia LIMIT 0. De lo contrario, recuperará toda la tabla solo para verificar los nombres.
Carlos Pinzón
41

Otra cosa que puede hacer es crear un cursor con el que podrá hacer referencia a sus columnas por sus nombres (esa es una necesidad que me llevó a esta página en primer lugar):

import psycopg2
from psycopg2.extras import RealDictCursor

ps_conn = psycopg2.connect(...)
ps_cursor = psql_conn.cursor(cursor_factory=RealDictCursor)

ps_cursor.execute('select 1 as col_a, 2 as col_b')
my_record = ps_cursor.fetchone()
print (my_record['col_a'],my_record['col_b'])

>> 1, 2
Dennis
fuente
26

Para obtener los nombres de columna en una consulta separada , puede consultar la tabla information_schema.columns.

#!/usr/bin/env python3

import psycopg2

if __name__ == '__main__':
  DSN = 'host=YOUR_DATABASE_HOST port=YOUR_DATABASE_PORT dbname=YOUR_DATABASE_NAME user=YOUR_DATABASE_USER'

  column_names = []

  with psycopg2.connect(DSN) as connection:
      with connection.cursor() as cursor:
          cursor.execute("select column_name from information_schema.columns where table_schema = 'YOUR_SCHEMA_NAME' and table_name='YOUR_TABLE_NAME'")
          column_names = [row[0] for row in cursor]

  print("Column names: {}\n".format(column_names))

Para obtener los nombres de columna en la misma consulta que las filas de datos , puede usar el campo de descripción del cursor:

#!/usr/bin/env python3

import psycopg2

if __name__ == '__main__':
  DSN = 'host=YOUR_DATABASE_HOST port=YOUR_DATABASE_PORT dbname=YOUR_DATABASE_NAME user=YOUR_DATABASE_USER'

  column_names = []
  data_rows = []

  with psycopg2.connect(DSN) as connection:
    with connection.cursor() as cursor:
      cursor.execute("select field1, field2, fieldn from table1")
      column_names = [desc[0] for desc in cursor.description]
      for row in cursor:
        data_rows.append(row)

  print("Column names: {}\n".format(column_names))
bitek
fuente
16

Si desea tener un obj de tupla con nombre de una consulta db, puede usar el siguiente fragmento:

from collections import namedtuple

def create_record(obj, fields):
    ''' given obj from db returns named tuple with fields mapped to values '''
    Record = namedtuple("Record", fields)
    mappings = dict(zip(fields, obj))
    return Record(**mappings)

cur.execute("Select * FROM people")
colnames = [desc[0] for desc in cur.description]
rows = cur.fetchall()
cur.close()
result = []
for row in rows:
    result.append(create_record(row, colnames))

Esto le permite acceder a los valores de registro como si fueran propiedades de clase, es decir

record.id, record.other_table_column_name, etc.

o incluso más corto

from psycopg2.extras import NamedTupleCursor
with cursor(cursor_factory=NamedTupleCursor) as cur:
   cur.execute("Select * ...")
   return cur.fetchall()
zzart
fuente
4

Después de ejecutar la consulta SQL, escriba el siguiente script de Python escrito en 2.7

total_fields = len(cursor.description)    
fields_names = [i[0] for i in cursor.description   
    Print fields_names
RAFI AFRIDI
fuente
0

También solía enfrentar un problema similar. Utilizo un simple truco para resolver esto. Supongamos que tiene nombres de columna en una lista como

col_name = ['a', 'b', 'c']

Entonces puedes hacer lo siguiente

for row in cursor.fetchone():
    print zip(col_name, row)
usuario2925213
fuente
0
 # You can use this function
 def getColumns(cursorDescription):
     columnList = []
     for tupla in cursorDescription:
         columnList.append(tupla[0])
     return columnList 
Francis Fulgencio
fuente
-7
#!/usr/bin/python
import psycopg2
#note that we have to import the Psycopg2 extras library!
import psycopg2.extras
import sys

def main():
    conn_string = "host='localhost' dbname='my_database' user='postgres' password='secret'"
    # print the connection string we will use to connect
    print "Connecting to database\n ->%s" % (conn_string)

    # get a connection, if a connect cannot be made an exception will be raised here
    conn = psycopg2.connect(conn_string)

    # conn.cursor will return a cursor object, you can use this query to perform queries
    # note that in this example we pass a cursor_factory argument that will
    # dictionary cursor so COLUMNS will be returned as a dictionary so we
    # can access columns by their name instead of index.
    cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)

    # tell postgres to use more work memory
    work_mem = 2048

    # by passing a tuple as the 2nd argument to the execution function our
    # %s string variable will get replaced with the order of variables in
    # the list. In this case there is only 1 variable.
    # Note that in python you specify a tuple with one item in it by placing
    # a comma after the first variable and surrounding it in parentheses.
    cursor.execute('SET work_mem TO %s', (work_mem,))

    # Then we get the work memory we just set -> we know we only want the
    # first ROW so we call fetchone.
    # then we use bracket access to get the FIRST value.
    # Note that even though we've returned the columns by name we can still
    # access columns by numeric index as well - which is really nice.
    cursor.execute('SHOW work_mem')

    # Call fetchone - which will fetch the first row returned from the
    # database.
    memory = cursor.fetchone()

    # access the column by numeric index:
    # even though we enabled columns by name I'm showing you this to
    # show that you can still access columns by index and iterate over them.
    print "Value: ", memory[0]

    # print the entire row 
    print "Row: ", memory

if __name__ == "__main__":
    main()
Ajay Menon
fuente