Comment obtenir une liste de noms de colonnes à partir d'un curseur psycopg2?

137

Je voudrais un moyen général de générer des étiquettes de colonne directement à partir des noms de colonne sélectionnés, et je me souviens avoir vu que le module psycopg2 de python prend en charge cette fonctionnalité.

Setjmp
la source

Réponses:

225

Extrait de "Programming Python" de Mark Lutz:

curs.execute("Select * FROM people LIMIT 0")
colnames = [desc[0] for desc in curs.description]
Setjmp
la source
64
Si vous ne voulez que les noms de colonnes, ne sélectionnez pas toutes les lignes du tableau. C'est plus efficace:curs.execute("SELECT * FROM people LIMIT 0")
Demitri
2
Cela peut valoir la peine d'ajouter que cela fonctionne aussi bien pour les vues que pour les tables, alors qu'il n'est pas (facilement) possible d'obtenir des noms de colonnes pour les vues à partir de information_schema.
wjv
5
Peut-être plus intuitif pour obtenir le nom comme attribut: colnames = [desc.name pour desc dans curs.description]
rovyko
Il est important de noter que les noms de colonne lus à partir de la fonction de description du curseur apparaissent en minuscules. curs.execute("Select userId FROM people") colnames = [desc[0] for desc in curs.description] assert colnames == ['userid']
dyltini
Vous devez mettre à jour votre réponse avec la suggestion LIMIT 0. Sinon, vous récupérerez la table entière juste pour vérifier les noms.
Carlos Pinzón
41

Une autre chose que vous pouvez faire est de créer un curseur avec lequel vous pourrez référencer vos colonnes par leurs noms (c'est un besoin qui m'a conduit à cette page en premier lieu):

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
la source
26

Pour obtenir les noms de colonne dans une requête distincte , vous pouvez interroger la table 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))

Pour obtenir les noms de colonnes dans la même requête que les lignes de données , vous pouvez utiliser le champ de description du curseur:

#!/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
la source
16

Si vous souhaitez avoir un tuple obj nommé à partir de la requête db, vous pouvez utiliser l'extrait de code suivant:

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))

Cela vous permet d'accéder aux valeurs d'enregistrement comme s'il s'agissait de propriétés de classe ie

record.id, record.other_table_column_name, etc.

ou même plus court

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

Après avoir exécuté une requête SQL, écrivez en suivant le script python écrit en 2.7

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

J'ai remarqué que vous devez utiliser cursor.fetchone()après la requête pour obtenir la liste des colonnes dans cursor.description(c'est-à-dire dans [desc[0] for desc in curs.description])

user2618351
la source
0

J'avais également l'habitude de faire face à un problème similaire. J'utilise une astuce simple pour résoudre ce problème. Supposons que vous ayez des noms de colonnes dans une liste comme

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

Ensuite, vous pouvez suivre

for row in cursor.fetchone():
    print zip(col_name, row)
user2925213
la source
0
 # You can use this function
 def getColumns(cursorDescription):
     columnList = []
     for tupla in cursorDescription:
         columnList.append(tupla[0])
     return columnList 
Francis Fulgencio
la source
-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
la source