分段错误扩展psycopg2_心理医生

2024-10-01 05:04:30 发布

您现在位置:Python中文网/ 问答频道 /正文

这个小的代码片段导致了SIGSEGV(我以为这在像python这样的垃圾回收语言中是不可能的,但是我习惯于在创建新类型的bug时成为高手),即使数据库存在并且连接正常,不管怎么说,我是想扩展psycopg2_心理光标类具有以字典形式返回查询结果的函数,我做错了什么?在

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

Tags: infromselffordefcolcursordesc
3条回答

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

我猜你遇到的是心理医生的一个错误。也就是说,_psycopg包名中的下划线表示,在那里定义的类并不是真正的子类。在

为什么不将dictfetchall()定义为一个独立的辅助函数?它不访问cursor对象的任何内部状态,不需要使它成为cursor方法。在

游标签名将连接作为第一个参数。重写__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()

但也可以参考fog关于使用DictCursor的建议。在

psycopg2是用C编写的,除非您知道自己在做什么,否则在调用/扩展模块时有可能导致SIGSEGV。所有常见的函数和方法都会仔细检查它们的参数,以避免出现破坏和安全问题,但在某些领域,正确操作的负担现在由客户端代码承担。您只需触及其中一个区域:扩展连接或游标类型。在

要正确地执行此操作,您需要在__init__方法中执行一些特定的工作,如下所示:

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

具体地说,cursor(和connection)是新样式的类,需要使用super()和传递给{}的完整参数列表初始化。至少:

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

我特别链接了这个例子,因为它已经完成了您需要的工作,例如,获取数据并使其可用为dicts。只需import psycopg.extras.DictCursor(使用类似于dict的行类)或{}(为每一行使用一个实数dict)就完成了。在

相关问题 更多 >