使用psycopg2将psql类型oid映射到python类型

2024-05-20 17:59:34 发布

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

故事是这样的。在

我有一堆存储过程,它们都有自己的参数类型。
我要做的是在python中创建一个类型安全层,这样我就可以在访问数据库之前确保所有值的类型都是正确的。在

当然,我不想再用python编写整个模式,所以我想我可以在启动时通过从数据库中获取参数名和类型来自动生成这些信息。在

所以我继续破解这个查询,只是为了测试

SELECT proname, proargnames, proargtypes 
FROM pg_catalog.pg_namespace n
JOIN pg_catalog.pg_proc p
ON pronamespace = n.oid
WHERE nspname = 'public';

然后我从python运行它,对于“proargtypes”,我为每个结果得到一个类似这样的字符串

^{pr2}$

我敏锐的目光告诉我这些是postgresql类型的oid,用空格分隔,这个特定的字符串意味着函数接受varchar、integer、varchar。 所以在python中,这应该是

(unicode, int, unicode)

现在我如何从这些数字中得到python类型呢?在

理想的最终结果应该是这样

In [129]: get_python_type(23)
Out[129]: int

我找到了最接近的extensions.string_类型'但这只是将OID映射到sql类型名称。在


Tags: 字符串信息数据库类型参数过程unicode模式
2条回答

如果您想要Python类型的类,就像您可能从SQLALchemy列对象获得的那样,您需要构建和维护自己的映射。^{cd2>内部没有。在

但是如果您想要的是从oid到一个将原始值转换为Python实例的函数,psycopg2.extensions.string_types实际上已经是您需要的了。它看起来像是从oid到一个名称的映射,但事实并非如此:它的值不是字符串,而是psycopg2._psycopg.type的实例。是时候深入研究一些代码了。在

psycopg2公开了一个用于注册新类型转换器的API,我们可以使用它来追溯到与类型转换相关的C代码;这一点围绕中的typecastObject展开 typecast.c,毫不奇怪,它映射到我们在老朋友string_types中找到的{}。这个对象包含指向两个函数的指针,pcast(对于Python casting函数)和{}(对于C转换函数),这看起来就像我们想要的那样-只需选择其中一个存在的函数并将其调用,问题已解决。但它们不在公开的属性中(name,这只是一个标签,values,这是一个oid列表)。该类型向Python公开的是__call__,事实证明,它只是在pcast和{}之间进行选择。这个方法的文档毫无用处,但是进一步看一下C代码shows,它有两个参数:一个包含原始值的字符串和一个cursor对象。在

>>> import psycopg2.extensions
>>> cur = something_that_gets_a_cursor_object()
>>> psycopg2.extensions.string_types[23]
<psycopg2._psycopg.type 'INTEGER' at 0xDEADBEEF>
>>> psycopg2.extensions.string_types[23]('100', cur)
100
>>> psycopg2.extensions.string_types[23]('10.0', cur)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '10.0'
>>> string_types[1114]
<psycopg2._psycopg.type 'DATETIME' at 0xDEADBEEF>
>>> string_types[1114]('2018-11-15 21:35:21', cur)
datetime.datetime(2018, 11, 15, 21, 35, 21)

对光标的需求是不幸的,事实上,并不总是需要光标:

^{2}$

但是转换实际字符串(varchar)类型的任何操作都依赖于PostgreSQL服务器的语言环境,至少在python3编译中是这样的,并且将None传递给这些caster并不仅仅是失败,而是segfaults。您提到的方法cursor.cast(oid, raw),实际上是psycopg2.extensions.string_types中caster的包装,在某些情况下可能更方便。在

对于需要游标和连接的唯一解决方法,我能想到的是构建一个基本上是一个模拟连接对象。如果它在没有连接到实际数据库的情况下公开了所有相关的环境信息,那么它可以附加到一个cursor对象,并与string_types[oid](raw, cur)或{}一起使用,但是mock将在C中构建并留给读者作为练习。在

postgres类型和python类型的映射是here。这有帮助吗?在

编辑: 从表中读取记录时,postgres(或任何数据库)驱动程序将自动将记录列类型映射到Python类型。在

cur = con.cursor()
cur.execute("SELECT * FROM Writers")

row = cur.fetchone()

for index, val in enumerate(row):
    print "column {0} value {1} of type {2}".format(index, val, type(val))

现在,您只需在编写MySQL接口代码时将Python类型映射到MySQL类型。 但是,坦率地说,这是一种将类型从PostgreSQL类型映射到MySQL类型的迂回方式。我只引用这两个数据库之间的众多类型映射中的一个,比如this

相关问题 更多 >