Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 扩展psycopg2的分段错误。\u psycopg.cursor_Python_Psycopg2 - Fatal编程技术网

Python 扩展psycopg2的分段错误。\u psycopg.cursor

Python 扩展psycopg2的分段错误。\u psycopg.cursor,python,psycopg2,Python,Psycopg2,这个小代码片段导致了SIGSEGV(我认为在像python这样有垃圾收集的语言中这是不可能的,但我习惯于在创建新类型的bug方面成为高手),即使数据库存在并且连接正常,无论如何,我试图扩展psycopg2.\u psycopg.cursor类,使其具有以字典形式返回查询结果的函数,我做错了什么 import psycopg2 class dcursor(psycopg2._psycopg.cursor): def __init__(self,parent_cursor):

这个小代码片段导致了SIGSEGV(我认为在像python这样有垃圾收集的语言中这是不可能的,但我习惯于在创建新类型的bug方面成为高手),即使数据库存在并且连接正常,无论如何,我试图扩展psycopg2.\u 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()
这是可能的,因为psycopg2是一个用C编写的模块,它只向Python公开其API。您可以在此处看到代码:

我猜你遇到的是Psycopg中的一个bug。这就是说,
\u psycopg
包名中的下划线表明,在那里定义的类实际上并不意味着要被子类化


为什么不将
dictfetchall()
定义为一个独立的助手函数?它不访问游标对象的任何内部状态,不需要将其设置为游标方法。

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

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

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

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

我特别链接了这个示例,因为它已经完成了您需要的工作,即获取数据并使其作为
dict
s提供。只需导入psycopg.extras.DictCursor(使用类似行类的
dict
)或导入psycopg.extras.RealDictCursor(对每一行使用real
dict
)就可以了。

光标签名将连接作为第一个参数。您重写
\uuuu init\uuuu
的方式使其采用光标。下面是一个错误。您的类与其说是游标,不如说是包装器。您也没有调用
\uuuu init\uuuu
基类,并且
self=parent\u游标
不做任何事情

以您的示例为例,创建游标子类的正确方法如下:

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。我将2.6版本替换为2.4版本,问题得到了解决

您可以通过运行python解释器并导入psycopg2来验证这一点


我需要dictfetchall()作为游标的一种方法,因为openerp中有大量使用cursor.dictfetchall的代码,但我无法找到在那里调用的游标类型,所以我尝试重新实现它。SycproPG游标是可子类化的好吧,它们只需要以正确的方式子类化即可(例如,调用他们的
\uuu init\uuu
并传递正确的参数)。事实上,我忽略了超级构造函数调用的不足,我的错!尽管如此,我还是希望它以比
SIGSEGV
:)更优雅的方式失败。这是一种我没有预料到的失败模式:不调用超类c'tor是一个非常基本的python错误。如果不太难的话,我会考虑添加一个关于这种糟糕用法的保护