मैं पायथन डिक्शनरी के रूप में pyodbc कर्सर आउटपुट (से .fetchone
, .fetchmany
या .fetchall
) को कैसे अनुक्रमित करूं ?
मैं बोतल का उपयोग कर रहा हूं और उसे वापस लौटने की जरूरत है ताकि वह इसे JSON के रूप में वापस कर सके।
मैं पायथन डिक्शनरी के रूप में pyodbc कर्सर आउटपुट (से .fetchone
, .fetchmany
या .fetchall
) को कैसे अनुक्रमित करूं ?
मैं बोतल का उपयोग कर रहा हूं और उसे वापस लौटने की जरूरत है ताकि वह इसे JSON के रूप में वापस कर सके।
जवाबों:
यदि आप समय से पहले कॉलम नहीं जानते हैं, तो शब्दकोशों की सूची बनाने के लिए कॉलम नामों की सूची बनाने के लिए Cursor.description का उपयोग करें और प्रत्येक पंक्ति के साथ ज़िप करें। उदाहरण मानता है कि कनेक्शन और क्वेरी निर्मित हैं:
>>> cursor = connection.cursor().execute(sql)
>>> columns = [column[0] for column in cursor.description]
>>> print(columns)
['name', 'create_date']
>>> results = []
>>> for row in cursor.fetchall():
... results.append(dict(zip(columns, row)))
...
>>> print(results)
[{'create_date': datetime.datetime(2003, 4, 8, 9, 13, 36, 390000), 'name': u'master'},
{'create_date': datetime.datetime(2013, 1, 30, 12, 31, 40, 340000), 'name': u'tempdb'},
{'create_date': datetime.datetime(2003, 4, 8, 9, 13, 36, 390000), 'name': u'model'},
{'create_date': datetime.datetime(2010, 4, 2, 17, 35, 8, 970000), 'name': u'msdb'}]
cursor.description
। इसने मुझे समय की एक नाव को बचाया।
बॉटलफी के साथ @ बर्गल के परिणाम का उपयोग करते हुए, मैं समापन बिंदु को उजागर करते हुए यह बहुत संक्षिप्त प्रश्न बनाने में सक्षम था:
@route('/api/query/<query_str>')
def query(query_str):
cursor.execute(query_str)
return {'results':
[dict(zip([column[0] for column in cursor.description], row))
for row in cursor.fetchall()]}
यहाँ एक संक्षिप्त रूप संस्करण है जिसका आप उपयोग कर सकते हैं
>>> cursor.select("<your SQL here>")
>>> single_row = dict(zip(zip(*cursor.description)[0], cursor.fetchone()))
>>> multiple_rows = [dict(zip(zip(*cursor.description)[0], row)) for row in cursor.fetchall()]
जैसा कि आप जानते हैं कि जब आप एक सूची में * जोड़ते हैं, तो आप मूल रूप से सूची को हटा देते हैं, व्यक्तिगत सूची प्रविष्टियों को उस फ़ंक्शन के मापदंडों के रूप में छोड़ देते हैं जिसे आप कॉल कर रहे हैं। जिप का उपयोग करके हम 1 से n एंट्री लेते हैं और उन्हें आप की पैंट में जिपर की तरह एक साथ जिप करते हैं।
का उपयोग करके
zip(*[(a,1,2),(b,1,2)])
# interpreted by python as zip((a,1,2),(b,1,2))
आपको मिला
[('a', 'b'), (1, 1), (2, 2)]
चूंकि विवरण टुपल्स के साथ एक ट्यूपल है, जहां प्रत्येक टपल हेडर और प्रत्येक कॉलम के लिए डेटा प्रकार का वर्णन करता है, आप प्रत्येक टपल के पहले को निकाल सकते हैं
>>> columns = zip(*cursor.description)[0]
के बराबर
>>> columns = [column[0] for column in cursor.description]
TypeError: 'zip' object is not subscriptable
इसलिए मैं zip(*description)[0]
ट्रिक का उपयोग नहीं कर सकता ।
columns
चर के साथ एक पंक्ति को बचाया , लेकिन प्रत्येक पंक्ति के लिए अलग से कॉलम के नामों की गणना करके फ़ंक्शन की जटिलता को गुणा किया
मुख्य रूप से @Torxed प्रतिक्रिया से दूर होने पर, मैंने स्कीमा और डेटा को एक शब्दकोश में खोजने के लिए फ़ंक्शन का एक सामान्यीकृत सेट बनाया:
def schema_dict(cursor):
cursor.execute("SELECT sys.objects.name, sys.columns.name FROM sys.objects INNER JOIN sys.columns ON sys.objects.object_id = sys.columns. object_id WHERE sys.objects.type = 'U';")
schema = {}
for it in cursor.fetchall():
if it[0] not in schema:
schema[it[0]]={'scheme':[]}
else:
schema[it[0]]['scheme'].append(it[1])
return schema
def populate_dict(cursor, schema):
for i in schema.keys():
cursor.execute("select * from {table};".format(table=i))
for row in cursor.fetchall():
colindex = 0
for col in schema[i]['scheme']:
if not 'data' in schema[i]:
schema[i]['data']=[]
schema[i]['data'].append(row[colindex])
colindex += 1
return schema
def database_to_dict():
cursor = connect()
schema = populate_dict(cursor, schema_dict(cursor))
लाइनों को कम करने के लिए इस पर सभी कोड-गोल्फ जाने के लिए स्वतंत्र महसूस करें; लेकिन इस बीच, यह काम करता है!
;)
उन स्थितियों के लिए जहां कर्सर उपलब्ध नहीं है - उदाहरण के लिए, जब पंक्तियों को किसी फ़ंक्शन कॉल या आंतरिक विधि द्वारा वापस किया गया है, तब भी आप row.cursor_description का उपयोग करके एक शब्दकोश प्रतिनिधित्व बना सकते हैं।
def row_to_dict(row):
return dict(zip([t[0] for t in row.cursor_description], row))
मुझे पता है कि यह सवाल पुराना है, लेकिन इससे मुझे यह पता लगाने में मदद मिली कि मुझे क्या करने की ज़रूरत है, जो ओपी के लिए पूछ रहा था की तुलना में थोड़ा अलग है, इसलिए मैंने सोचा कि मैं साझा करूँगा, किसी और की मदद करने के लिए जो मुझे चाहिए: अगर आप SQL रूटीन क्वेरीज़ को निष्पादित करने वाले एक रूटीन को पूरी तरह से सामान्य करना चाहते हैं, लेकिन आपको एक इंडेक्स नंबर द्वारा परिणामों को संदर्भित करने की आवश्यकता है, एक नाम नहीं, आप एक शब्दकोश के बजाय सूचियों की सूची के साथ ऐसा कर सकते हैं। लौटे डेटा की प्रत्येक पंक्ति को फ़ील्ड (स्तंभ) मानों की सूची के रूप में लौटी सूची में दर्शाया गया है। कॉलम नामों को लौटी हुई सूची की पहली प्रविष्टि के रूप में प्रदान किया जा सकता है, इसलिए कॉलिंग रूटीन में लौटी सूची को पार्स करना वास्तव में आसान और लचीला हो सकता है। इस तरह, डेटाबेस कॉल करने वाली दिनचर्या को उस डेटा के बारे में कुछ भी जानने की आवश्यकता नहीं है जिसे वह संभाल रहा है। यहाँ इस तरह की एक दिनचर्या है:
def read_DB_Records(self, tablename, fieldlist, wherefield, wherevalue) -> list:
DBfile = 'C:/DATA/MyDatabase.accdb'
# this connection string is for Access 2007, 2010 or later .accdb files
conn = pyodbc.connect(r'Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ='+DBfile)
cursor = conn.cursor()
# Build the SQL Query string using the passed-in field list:
SQL = "SELECT "
for i in range(0, len(fieldlist)):
SQL = SQL + "[" + fieldlist[i] + "]"
if i < (len(fieldlist)-1):
SQL = SQL + ", "
SQL = SQL + " FROM " + tablename
# Support an optional WHERE clause:
if wherefield != "" and wherevalue != "" :
SQL = SQL + " WHERE [" + wherefield + "] = " + "'" + wherevalue + "';"
results = [] # Create the results list object
cursor.execute(SQL) # Execute the Query
# (Optional) Get a list of the column names returned from the query:
columns = [column[0] for column in cursor.description]
results.append(columns) # append the column names to the return list
# Now add each row as a list of column data to the results list
for row in cursor.fetchall(): # iterate over the cursor
results.append(list(row)) # add the row as a list to the list of lists
cursor.close() # close the cursor
conn.close() # close the DB connection
return results # return the list of lists
मुझे @bryan और @ फू-स्टैक उत्तर पसंद हैं। आप PostgreSQL के साथ काम कर रहे हैं और आप उपयोग कर रहे हैं psycopg2
आप कुछ इस्तेमाल कर सकते हैं psycopg2 से उपहार cursorfactory किया जा रहा है एक निर्दिष्ट करने के द्वारा एक ही प्राप्त करने के लिए DictCursor
जब कनेक्शन से अपने कर्सर बनाने, इस तरह:
cur = conn.cursor( cursor_factory=psycopg2.extras.DictCursor )
तो अब आप अपनी sql क्वेरी को निष्पादित कर सकते हैं और आपको अपने परिणामों को लाने के लिए एक शब्दकोश मिलेगा, बिना हाथ से उन्हें मैप करने की आवश्यकता के बिना।
cur.execute( sql_query )
results = cur.fetchall()
for row in results:
print row['row_no']
कृपया ध्यान दें कि आपको import psycopg2.extras
उस काम के लिए होना पड़ेगा ।
मान लें कि आप कॉलम नाम जानते हैं! इसके अलावा, यहां तीन अलग-अलग समाधान हैं,
आप शायद पिछले एक को देखना चाहते हैं!
colnames = ['city', 'area', 'street']
data = {}
counter = 0
for row in x.fetchall():
if not counter in data:
data[counter] = {}
colcounter = 0
for colname in colnames:
data[counter][colname] = row[colcounter]
colcounter += 1
counter += 1
यह एक अनुक्रमित संस्करण है, सबसे सुंदर समाधान नहीं है लेकिन यह काम करेगा। पंक्ति संख्या के क्रम में डेटा वाली प्रत्येक कुंजी के भीतर एक सूची के साथ शब्दकोष कुंजी के रूप में कॉलम नाम को अनुक्रमित करना एक और होगा। ऐसा करके:
colnames = ['city', 'area', 'street']
data = {}
for row in x.fetchall():
colindex = 0
for col in colnames:
if not col in data:
data[col] = []
data[col].append(row[colindex])
colindex += 1
इसे लिखते हुए, मैं समझता हूं कि कर की for col in colnames
जगह ले ली जा सकती है for colindex in range(0, len())
लेकिन आपको इसका विचार है। उदाहरण के लिए, बाद का उदाहरण उपयोगी होगा जब सभी डेटा को नहीं लाया जाएगा, लेकिन उदाहरण के लिए एक बार में एक पंक्ति:
def fetchone_dict(stuff):
colnames = ['city', 'area', 'street']
data = {}
for colindex in range(0, colnames):
data[colnames[colindex]] = stuff[colindex]
return data
row = x.fetchone()
print fetchone_dict(row)['city']
Tablenames हो रही है (मुझे लगता है .. फू स्टैक के लिए धन्यवाद): नीचे दाढ़ी से
एक अधिक प्रत्यक्ष समाधान !
cursor.execute("SELECT sys.objects.name, sys.columns.name FROM sys.objects INNER JOIN sys.columns ON sys.objects.object_id = sys.columns. object_id WHERE sys.objects.type = 'U';")
schema = {}
for it in cursor.fetchall():
if it[0] in schema:
schema[it[0]].append(it[1])
else:
schema[it[0]] = [it[1]]
cursor.execute("SELECT sys.objects.name, sys.columns.name FROM sys.objects INNER JOIN sys.columns ON sys.objects.object_id = sys.columns. object_id WHERE sys.objects.type = 'U';") schema = {} for it in cursor.fetchall(): if it[0] in schema: schema[it[0]].append(it[1]) else: schema[it[0]] = [it[1]]