Python 使用psycopg2以列表形式返回PostgreSQL UUID数组

Python 使用psycopg2以列表形式返回PostgreSQL UUID数组,python,postgresql,type-conversion,uuid,psycopg2,Python,Postgresql,Type Conversion,Uuid,Psycopg2,我有一个SQL语句,它包含一个子查询,嵌入在ARRAY()中,如下所示: SELECT foo, ARRAY(SELECT x from y) AS bar ... 查询工作正常,但是在psycopg2结果游标中,数组返回为字符串(如“{1,2,3}”),而不是列表 我的问题是,将这样的字符串转换为python列表的最佳方式是什么?如果每个结果游标数组的格式都是'{x,y,z}',那么您可以这样做来剥离大括号字符串,并通过逗号分隔符将其拆分为一个列表: >>> s = '{1

我有一个SQL语句,它包含一个子查询,嵌入在
ARRAY()
中,如下所示:

SELECT foo, ARRAY(SELECT x from y) AS bar ...
查询工作正常,但是在psycopg2结果游标中,数组返回为字符串(如
“{1,2,3}”
),而不是列表


我的问题是,将这样的字符串转换为python列表的最佳方式是什么?

如果每个结果游标数组的格式都是
'{x,y,z}'
,那么您可以这样做来剥离大括号字符串,并通过逗号分隔符将其拆分为一个列表:

>>> s = '{1,2,3}'
>>> s
'{1,2,3}'
>>> l = s.rstrip('}').lstrip('{').split(',')
>>> l
['1', '2', '3']
>>>
>>> s = '{1,2,3,a,b,c}'
>>> s
'{1,2,3,a,b,c}'
>>> l = s.rstrip('}').lstrip('{').split(',')
>>> l
['1', '2', '3', 'a', 'b', 'c']

它适用于我,无需解析:

import psycopg2

query = """
    select array(select * from (values (1), (2)) s);
"""

conn = psycopg2.connect('dbname=cpn user=cpn')
cursor = conn.cursor()
cursor.execute(query)
rs = cursor.fetchall()

for l in rs:
    print l[0]

cursor.close()
conn.close()
执行时的结果:

$ python stackoverflow_select_array.py 
[1, 2]
更新 您需要注册uuid类型:

import psycopg2, psycopg2.extras

query = """
    select array(
        select *
        from (values
            ('A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11'::uuid),
            ('A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11'::uuid)
        )s
    );
"""

psycopg2.extras.register_uuid()

conn = psycopg2.connect('dbname=cpn user=cpn')
cursor = conn.cursor()
cursor.execute(query)
rs = cursor.fetchall()

for l in rs:
    print l[0]

cursor.close()
conn.close()
结果:

$ python stackoverflow_select_array.py 
[UUID('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'), UUID('a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11')]

另一种处理方法是显式地告诉postgres您需要文本,然后默认的psycopg2字符串解析逻辑将启动,您将得到一个列表:

db = psycopg2.connect('...')
curs = db.cursor()
curs.execute("""
    SELECT s.id, array_agg(s.kind::text)
        FROM (VALUES ('A', 'A0EEBC99-9C0B-AEF8-BB6D-6BB9BD380A11'::uuid),
                     ('A', 'A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A12'::uuid)) AS s (id, kind)
    GROUP BY s.id
""")
for row in curs:
    print "row: {}".format(row)
结果:

row: (u'A', [u'a0eebc99-9c0b-aef8-bb6d-6bb9bd380a11', u'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12'])
row: ([u'a0eebc99-9c0b-aef8-bb6d-6bb9bd380a11', u'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12'],)
以及查询

curs.execute("""
    SELECT array(
        SELECT s.kind::text
        FROM (VALUES ('A0EEBC99-9C0B-AEF8-BB6D-6BB9BD380A11'::uuid),
                     ('A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A12'::uuid)) AS s (kind))
""")
for row in curs:
    print "row: {}".format(row)
结果:

row: (u'A', [u'a0eebc99-9c0b-aef8-bb6d-6bb9bd380a11', u'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12'])
row: ([u'a0eebc99-9c0b-aef8-bb6d-6bb9bd380a11', u'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a12'],)

诀窍是将
::text
附加到您关心的字段。

非常感谢这一点,我又回去玩了一些代码,您是对的,它确实有效,但仅适用于整数和字符串列类型。我在数组中检索的列实际上是UUID类型,它仍然以字符串的形式返回。对不起,当我最初发布时,我过度简化了我的代码,我没有意识到列类型会影响这一点。谢谢,这确实有效。如果我不能找出为什么ARRAY()不适用于UUID字段(见下文),我将采用这种方法。