2011-07-18 109 views
36

我以前沒有使用psycopg2,但我試圖將遊標工廠更改爲DictCursor,以便fetchall或fetchone將返回字典而不是列表。DictCursor似乎不能在psycopg2下工作

我創建了一個測試腳本,使事情變得簡單,只測試這個功能。這是我覺得應該工作的一小段代碼

import psycopg2 
import psycopg2.extras 

conn = psycopg2.connect("dbname=%s user=%s password=%s" % (DATABASE, USERNAME, PASSWORD)) 

cur = conn.cursor(cursor_factory = psycopg2.extras.DictCursor) 
cur.execute("SELECT * from review") 

res = cur.fetchall() 

print type(res) 
print res 

res變量總是一個列表,而不是我所期望的字典。

我已經實現的一個當前的解決方法是使用這個函數來構建一個字典並運行fetchall通過它返回的每一行。

def build_dict(cursor, row): 
    x = {} 
    for key,col in enumerate(cursor.description): 
     x[col[0]] = row[key] 
    return d 

Python是版本2.6.7和psycopg2是版本2.4.2。

回答

20
res = cur.fetchall() 

使得res列表psycopg2.extras.DictRow s。


或者,而不是調用cur.fetchall您可以利用的事實,即cur是一個迭代:

cur.execute("SELECT * from review") 
for row in cur: 
    print(row['column_name']) 

這樣的話你就可以用dict樣的語法來訪問數據。

+0

謝謝,我認爲你現在與「字典」。這是一個列表,但像字典一樣。這似乎是一個奇怪的設計決定,但至少現在正在工作。再次感謝。 – Jim

+12

@Seth:如果你想要一個真正的字典,使用恰當命名的'RealDictCursor'。 –

+0

@Seth:字典沒有順序,所以你不能再使用它作爲元組,查詢中的第一列不再是'row [0]',而是任意的。所以有一些優點:) – Wolph

64

使用RealDictCursor:

cur = conn.cursor(cursor_factory = psycopg2.extras.RealDictCursor) 
cur.execute("SELECT * from review") 
res = cur.fetchall()  

這給你行作爲真正的Python字典,而不是 「先進psycopg2榜」 名單。

+1

謝謝。它工作正常。 – ibi0tux

+1

是的,這是有效的..提交爲瓶插件中的錯誤https://github.com/raisoblast/bottle-pgsql/issues/2 – PedroMorgan

0

除了使用RealDictCursor功能外,您還可能需要詢問所有列 (在select後使用*符號),正如答案中所做的那樣。

我對結果的某些列不感興趣,因爲他們已知值 已在WHERE條件中使用。但SELECT (..., ..., ..., ...) FROM ... WHERE ... 變種沒有給我字典。

此致敬禮! Harley

+0

捨棄括號和查詢工作:'SELECT ...,..., ...,...從...在哪裏......'。 –

5

另一種解決方案是使用Named Tuple Cursor,因爲Real Dict Cursor將打破使用整數標記的任何查詢,如文檔中所述。

名爲元組光標,你可以用點語法訪問它們像這樣:

import psycopg2 
import psycopg2.extras 
cur = conn.cursor(cursor_factory = psycopg2.extras.NamedTupleCursor) 
cur.execute("SELECT * from review") 
res = cur.fetchone() 
res.key1 
res.key2 

這使事情變得整潔而據我所知不會破壞任何東西。

+0

此外,整個結果可以轉換爲這樣的字典列表:'[row._asdict()for cur in row]'' – GetFree

3

儘管這是一個老問題,但它仍然出現在谷歌,所以我想我會我的代碼添加到該爲別人從大G.

對於我的到來,我有多行,我會喜歡返回到字典,理想情況下不想使用循環或類似的設置數據庫中的字段的密鑰..

所以使用dict comprehension syntax我可以做到以下幾點。

錶行到字典


pgCursor = Conn.cursor(cursor_factory = psycopg2.extras.RealDictCursor) 
pgCursor.execute("SELECT * FROM tablename;",([])) 
dictRows = {n['id']: n for n in pgCursor} 

功能&調用它

#NOTE this is using a class object hence the self param 
def DBTableToDictByID(self, squery): 
    self.Pointer.execute(squery,([])) 
    return {n['id']: n for n in self.Pointer} 

dictRows = self.DBTableToDictByID("SELECT * FROM tablename;") 

儘管這在y循環中使用了for x,但它的pythonic儘可能地告訴我......希望這會對某些人有所幫助。

0

因此,要使這個工作像MySQL版本的字典光標,你將不得不把它包裝在另一個函數或代碼中。我將繼續討論這個問題,並向他們建議將來的代碼部署,以便在fetchall()調用與Dictionary Cursor一起使用時返回字典。下面是一些示例代碼,你可以用它來修復它:

cursor.execute(query) 
# Python 2.7 and beyond with dictionary comprehension 
results = [{key:value for key,value in row.iteritems()} for row in cursor] 
# Python 2.6 and before 
# results = [dict((key,value) for key,value in row.iteritems()) for row in cursor] 

該代碼使得使用使用fetchall相同的格式字典光標的MySQL版本()。不知道他們爲什麼以不同的方式實現它,但這會幫助您獲得相同的實際python字典輸出,而不是fetchall()情況下的列表。