Jak uzyskać listę nazw kolumn z kursora psycopg2?

148

Chciałbym uzyskać ogólny sposób generowania etykiet kolumn bezpośrednio z wybranych nazw kolumn i przypominam sobie, że moduł psycopg2 w Pythonie obsługuje tę funkcję.

Setjmp
źródło

Odpowiedzi:

234

Z artykułu „Programming Python” autorstwa Marka Lutza:

curs.execute("Select * FROM people LIMIT 0")
colnames = [desc[0] for desc in curs.description]
Setjmp
źródło
66
Jeśli chcesz tylko nazwy kolumn, nie zaznaczaj wszystkich wierszy w tabeli. To jest bardziej wydajne:curs.execute("SELECT * FROM people LIMIT 0")
Demitri,
2
Warto dodać, że działa to zarówno w przypadku widoków, jak i tabel, podczas gdy nie jest (łatwo) możliwe pobranie nazw kolumn dla widoków information_schema.
wjv
6
Może być bardziej intuicyjne, aby uzyskać nazwę jako atrybut: colnames = [desc.name for desc in curs.description]
rovyko
Należy zauważyć, że nazwy kolumn odczytywane z funkcji opisu kursora są pisane małymi literami. curs.execute("Select userId FROM people") colnames = [desc[0] for desc in curs.description] assert colnames == ['userid']
dyltini
Powinieneś zaktualizować swoją odpowiedź sugestią LIMIT 0. W przeciwnym razie odzyskasz całą tabelę, aby sprawdzić nazwy.
Carlos Pinzón
48

Inną rzeczą, którą możesz zrobić, jest utworzenie kursora, za pomocą którego będziesz mógł odwoływać się do swoich kolumn według ich nazw (to jest potrzeba, która doprowadziła mnie do tej strony w pierwszej kolejności):

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
źródło
proszę
podać
26

Aby uzyskać nazwy kolumn w oddzielnym zapytaniu , możesz wysłać zapytanie do tabeli 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))

Aby uzyskać nazwy kolumn w tym samym zapytaniu, co wiersze danych , możesz użyć pola opisu kursora:

#!/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))
Alex Bitek
źródło
17

Jeśli chcesz mieć nazwaną krotkę obj z zapytania db, możesz użyć następującego fragmentu:

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

Umożliwia to dostęp do wartości rekordów tak, jakby były one właściwościami klasy, tj

record.id, record.other_table_column_name itp.

lub nawet krócej

from psycopg2.extras import NamedTupleCursor
with cursor(cursor_factory=NamedTupleCursor) as cur:
   cur.execute("Select * ...")
   return cur.fetchall()
zzart
źródło
4

Po wykonaniu zapytania SQL napisz następujący skrypt w języku Python w wersji 2.7

total_fields = len(cursor.description)    
fields_names = [i[0] for i in cursor.description   
    Print fields_names
RAFI AFRIDI
źródło
2

Jeśli chcesz uzyskać ramkę danych pandy z już skojarzonymi nagłówkami kolumn, spróbuj tego:

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))
albielin
źródło
To wydaje mi się najłatwiejsze. Dziwię się, że musiałbyś wykonać oddzielne zapytanie, aby uzyskać nazwy kolumn. Pracował dla mnie.
Chuck Pedro
0

Miałem też podobny problem. Aby to rozwiązać, używam prostej sztuczki. Załóżmy, że masz nazwy kolumn na liście, takiej jak

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

Następnie możesz wykonać następujące czynności

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