Ste*_*son 6 python postgresql psycopg2
这是故事.
我有一堆存储过程,并且都有自己的参数类型.
我想要做的是在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';
Run Code Online (Sandbox Code Playgroud)
然后我从python运行它,对于'proargtypes',我为每个结果得到一个这样的字符串
'1043 23 1043'
Run Code Online (Sandbox Code Playgroud)
我敏锐的眼睛告诉我这些是postgresql类型的oid,由空格分隔,这个特定的字符串意味着该函数接受varchar,integer,varchar.所以在python中说,这应该是
(unicode, int, unicode)
Run Code Online (Sandbox Code Playgroud)
现在我如何从这些数字中获取python类型?
理想的最终结果将是这样的
In [129]: get_python_type(23)
Out[129]: int
Run Code Online (Sandbox Code Playgroud)
我看了整个psycopg2,我发现最接近的是'extensions.string_types',但这只是将oids映射到sql类型名称.
If you want the Python type classes, like you might get from a SQLALchemy column object, you'll need to build and maintain your own mapping. psycopg2 doesn't have one, even internally.
But if what you want is a way to get from an oid to a function that will convert raw values into Python instances, psycopg2.extensions.string_types is actually already what you need. It might look like it's just a mapping from oid to a name, but that's not quite true: its values aren't strings, they're instances of psycopg2._psycopg.type. Time to delve into a little code.
psycopg2 exposes an API for registering new type converters which we can use to trace back into the C code involved with typecasts; this centers around the typecastObject in
typecast.c, which, unsurprisingly, maps to the psycopg2._psycopg.type we find in our old friend string_types. This object contains pointers to two functions, pcast (for Python casting function) and ccast (for C casting function), which would seem like what we want— just pick whichever one exists and call it, problem solved. Except they're not among the attributes exposed (name, which is just a label, and values, which is a list of oids). What the type does expose to Python is __call__, which, it turns out, just chooses between pcast and ccast for us. The documentation for this method is singularly unhelpful, but looking at the C code further shows that it takes two arguments: a string containing the raw value, and a cursor object.
>>> 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)
Run Code Online (Sandbox Code Playgroud)
The need for a cursor is unfortunate, and in fact, a cursor isn't always required:
>>> string_types[23]('100', None)
100
Run Code Online (Sandbox Code Playgroud)
But anything having to with converting actual string (varchar, for example) types is dependent on the PostgreSQL server's locale, at least in a Python 3 compilation, and passing None to those casters doesn't just fail— it segfaults. The method you mention, cursor.cast(oid, raw), is essentially a wrapper around the casters in psycopg2.extensions.string_types and may be more convenient in some instances.
我能想到的需要游标和连接的唯一解决方法是基本上构建一个模拟连接对象。如果它在不连接实际数据库的情况下公开所有相关的环境信息,则可以将其附加到游标对象并与string_types[oid](raw, cur)或 一起使用cur.cast(oid, raw),但模拟将用 C 构建,并留给读者作为练习。
这里给出了 postgres 类型和 python 类型的映射。这有帮助吗?
编辑:当您从表中读取记录时,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))
Run Code Online (Sandbox Code Playgroud)
现在,您只需在编写 MySQL 接口代码时将 Python 类型映射到 MySQL 类型即可。但是,坦率地说,这是将类型从 PostgreSQL 类型映射到 MySQL 类型的一种迂回方式。我只想引用这两个数据库之间的众多类型映射之一,如下所示
| 归档时间: |
|
| 查看次数: |
2441 次 |
| 最近记录: |