2014-02-25 36 views
0

這個小代碼片段導致SIGSEGV(我認爲這是不可能的,在像python這樣的垃圾收集語言中,但我曾經是一個創造新的錯誤)即使數據庫存在和連接工作,無論如何,我試圖擴展psycopg2._psycopg.cursor類有一個函數返回字典形式的查詢結果,我做錯了什麼?分段錯誤擴展psycopg2._psycopg.cursor

import psycopg2 

class dcursor(psycopg2._psycopg.cursor): 
    def __init__(self,parent_cursor): 
     self=parent_cursor 
    def dictfetchall(self): 
     "Returns all rows from a cursor as a dict" 
     desc = cursor.description 
     return [ 
       dict(zip([col[0] for col in desc], row)) 
       for row in cursor.fetchall() 
     ] 

conn = psycopg2.connect("dbname=dbpgs user=openerp") 
cur = dcursor(conn.cursor()) 
cur.execute('select name_related from hr_employee;') 
print cur.dictfetchall() 

回答

0

可能的,因爲psycopg2是用C寫的一個模塊,它只是暴露了其對Python API。你可以在這裏看到代碼:http://github.com/psycopg/psycopg2.git

我想你遇到的是Psycopg中的一個錯誤。也就是說,_psycopg軟件包名稱中的下劃線表示,那裏定義的類並非真正意義上的子類。

爲什麼不將dictfetchall()定義爲獨立的幫助函數?它不訪問遊標對象的任何內部狀態,因此沒有必要將它變爲遊標方法。

+0

我需要dictfetchall()將光標的方法,因爲我在使用cursor.dictfetchall的OpenERP有大量的代碼,但我無法找出什麼樣的光標被稱爲有這麼我試圖很容易地實現它 – woggio

+1

Psycopg遊標是可分類的,它們只需要以正確的方式進行子類化(例如調用它們的__init__並將正確的參數傳遞給它)。 – piro

+0

確實 - 我忽視了超級構造函數調用的缺失,我的不好!不過,我希望它會比'SIGSEGV'更優雅地失敗:) –

0

psycopg2是用C編寫的,除非你知道你在做什麼,否則調用/擴展模塊時可能會導致SIGSEGV。所有常見的功能和方法都要仔細檢查他們的論點,以避免破壞和安全問題,但是現在有一些地方正在客戶端代碼上執行正確的事情。您只需點擊其中一個區域即可:擴展連接或遊標類型。

要做到這一點的權利,你需要做一些具體的工作在你的__init__方法,如下所示:

https://github.com/psycopg/psycopg2/blob/master/lib/extras.py#L49

具體cursor(和connection)是新樣式類,需要使用初始化super()以及傳遞給__init__的完整參數列表。在最低限度:

def __init__(self, *args, **kwargs): 
    super(DictCursorBase, self).__init__(*args, **kwargs) 

我聯繫這個例子特別是因爲它已經做了你需要的東西,即獲取數據並使其可作爲dict秒。只需要import psycopg.extras.DictCursor(使用類似dict的行類)或import psycopg.extras.RealDictCursor(對於每一行使用實際的dict)即可完成。

1

遊標簽名將連接作爲第一個參數。你重寫了__init__的方式使它成爲一個遊標。 Segfault如下。你的班級比遊標更包裝。您也不會撥打__init__基本類,self=parent_cursor也不會執行任何操作。

子類光標把你的例子正確的做法是這樣的:

class dcursor(psycopg2.extensions.cursor): 
    def dictfetchall(self): 
     "Returns all rows from a cursor as a dict" 
     desc = self.description 
     return [ 
       dict(zip([col[0] for col in desc], row)) 
       for row in self.fetchall() 
     ] 

conn = psycopg2.connect("dbname=dbpgs user=openerp") 
cur = conn.cursor(cursor_factory=dcursor) 
cur.execute('select name_related from hr_employee;') 
print cur.dictfetchall() 

還能看到關於使用DictCursor霧的建議。

0

我有同樣的錯誤,解決方案是用不同的版本替換psycopg2。我替換了2.4版本的2.4版本,問題已修復。

你可以運行python解釋器並導入psycopg2來驗證。

enter image description here