分段错误扩展psycopg2._psycopg.cursor

时间:2014-02-25 15:50:51

标签: python psycopg2

这个小代码片段导致了SIGSEGV(我认为这在使用像python这样的垃圾收集的语言中是不可能的,但我已经习惯于创建新类型的bug了),即使数据库存在并且连接工作,无论如何我试图扩展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()

4 个答案:

答案 0 :(得分: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的建议。

答案 1 :(得分:0)

是可能的,因为psycopg2是用C编写的模块,它只将其API公开给Python。您可以在此处查看代码:http://github.com/psycopg/psycopg2.git

我猜你遇到的是Psycopg中的一个错误。也就是说,_psycopg包名称中的下划线表示,那里定义的类并不是真正意义上的子类。

为什么不将dictfetchall()定义为独立的帮助函数?它不访问游标对象的任何内部状态,没有必要使它成为游标方法。

答案 2 :(得分: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)就可以了。

答案 3 :(得分:0)

我遇到了同样的错误,解决方案是用不同的版本替换psycopg2。我为2.4版本替换了2.6版本,问题得到解决。

您可以通过运行python interpreter并导入psycopg2来验证这一点。

enter image description here