210 votes

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

J'aimerais disposer d'un moyen général de générer des étiquettes de colonnes directement à partir des noms de colonnes sélectionnés, et je me souviens avoir vu que le module psycopg2 de python prenait en charge cette fonctionnalité.

328voto

SetJmp Points 4672

Extrait de "Programming Python" par Mark Lutz :

curs.execute("Select * FROM people LIMIT 0")
colnames = [desc[0] for desc in curs.description]

75 votes

Si vous ne voulez que les noms des colonnes, ne sélectionnez pas toutes les lignes du tableau. C'est plus efficace : curs.execute("SELECT * FROM people LIMIT 0")

5 votes

Il peut être utile d'ajouter que cela fonctionne pour les vues comme pour les tables, alors qu'il n'est pas (facilement) possible d'obtenir les noms des colonnes pour les vues à partir de information_schema .

8 votes

Il serait peut-être plus intuitif d'obtenir le nom en tant qu'attribut : colnames = [desc.name for desc in curs.description]

81voto

Dennis Points 1390

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

0 votes

Veuillez indiquer la source de l'information

1 votes

Dans mon cas, le "as col_a" n'était pas nécessaire. Je l'ai omis et les enregistrements renvoyés par le curseur ont utilisé les noms de colonnes de ma table.

32voto

dZkF9RWJT6wN8ux Points 2435

Pour obtenir les noms des colonnes dans une requête séparée 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 des 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))

27voto

zzart Points 2162

Si vous souhaitez obtenir un tuple nommé obj à partir d'une requête de base de données, vous pouvez utiliser l'extrait 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 des enregistrements comme s'il s'agissait de propriétés de classe, c'est-à-dire

record.id, record.other_table_column_name, etc.

ou encore plus court

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

21voto

albielin Points 322

Si vous cherchez à obtenir un cadre de données pandas avec des en-têtes de colonne déjà associés Essayez ceci :

import psycopg2, pandas

con=psycopg2.connect(
    dbname=DBNAME, 
    host=HOST, 
    port=PORT, 
    user=USER, 
    password=PASSWORD
)

sql = """
select * from x
"""

d = pandas.read_sql_query(sql,con)

con.close()

print(type(d))

print(pandas.DataFrame.head(d))

1 votes

Cela me semble être la solution la plus simple. Je suis surpris que vous deviez faire une requête séparée pour obtenir les noms des colonnes. Cela a fonctionné pour moi.

0 votes

Tout à fait d'accord, @ChuckPedro

1 votes

Méthode la plus simple. elle devrait avoir plus de votes positifs

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X