出于某些目的,我必须在数据库中将字段排序从utf8_unicode_ci
更改为utf8_bin
。事实证明,这种变化会导致python的数据类型发生变化。
问题是如何强制mysql-python将unicode对象返回到python 。
这是一个显示问题的示例(显式字符集强制use_unicode = 1):
>>> con = MySQLdb.connect(..., charset='utf8')
>>> c = c.cursor()
>>> c.execute('SELECT %s COLLATE utf8_bin', u'м')
1L
>>> c.fetchone()
('\xd0\xbc',)
>>> c.description
(("'\xd0\xbc' COLLATE utf8_bin", 253, 2, 3, 3, 31, 0),)
>>> c.execute('SELECT %s COLLATE utf8_unicode_ci', u'м')
1L
>>> c.fetchone()
(u'\u043c',)
>>> c.description
(("'\xd0\xbc' COLLATE utf8_unicode_ci", 253, 2, 3, 3, 31, 0),)
在我的数据库中,字段的类型为VARCHAR,但在更改后,它们的行为类似于BINARY,这不是我想要的。
答案 0 :(得分:2)
因此,MySQL的VARCHAR
,VARBINARY
和字符串文字映射到列类型定义中的相同MySQLdb.constants.FIELD_TYPE.VAR_STRING
类型,但在类型时有一个额外的MySQLdb.constants.FLAG.BINARY
标志是VARBINARY
或与*_bin
归类整理的字符串。
即使有MySQLdb.constants.FIELD_TYPE.VARCHAR
类型,我也未能找到它的使用时间。正如我所说,MySQL VARCHAR
列映射到FIELD_TYPE.VAR_STRING
。
如果您的应用程序使用真正的二进制字符串(例如,您存储图像并使用与文本相同的连接来获取它们),则解决方案变得相当脆弱,因为它假定将所有二进制字符串解码为unicode。虽然,它有效。
正如docs官方所述:
因为MySQL将所有数据作为字符串返回,并希望您自己转换它。这对屁股来说真的很痛苦,但事实上,_mysql可以为你做到这一点。 (并且MySQLdb会为您执行此操作。)要完成自动类型转换,您需要创建一个类型转换器字典,并将其作为 conv 关键字参数传递给connect()。
在实践中,屁股的真正痛苦可能是构建自己的转换器字典的过程。但是您可以从MySQLdb.converters.conversions
导入默认值并对其进行修补,甚至可以在Connection的实例上进行修补。诀窍是删除FLAG.BINARY
标志的特殊转换器,并为所有情况添加解码器。如果您为charset
明确指定了MySQLdb.connect
参数,则会强制use_unicode=1
参数,这会为您添加解码器,但您可以自行完成:
>>> con = MySQLdb.connect(**params)
>>> con.converter[FIELD_TYPE.VAR_STRING]
[(128, <type 'str'>), (None, <function string_decoder at 0x01FFA130>)]
>>> con.converter[FIELD_TYPE.VAR_STRING] = [(None, con.string_decoder)]
>>> c = con.cursor()
>>> c.execute("SELECT %s COLLATE utf8_bin", u'м')
1L
>>> c.fetchone()
(u'\u043c',)
如果需要,您可能需要对FIELD_TYPE.STRING
进行相同的黑客攻击。
另一个解决方案是将显式use_unicode=0
传递给MySQLdb.connect
并在代码中进行所有解码,但我不会。
希望,这可能对某人有用。
答案 1 :(得分:1)
在低级别使用Mysql-Python是一个很大的变化,但我认为更好的想法是使用sqlalchemy之类的东西而不是直接使用db-api,然后你可以使用例如types.Unicode并且知道它正在执行db-api的unicode支持所需的内容
在你跳过我没有直接回答这个问题之前,请考虑一下:mysql-python又称MySQLdb只是MySQL的几个db-api之一。新版本可能会继续支持MySQLdb,但有些情况(例如转移到python 3x,或者你无法安装二进制模块的主机)可能会迫使你在将来使用其他东西,例如:为oursql或myconnpy。制作sqlalchemy的人已经付出了很多努力来支持多个db-api,而在mysql-python的情况下,他们甚至在过去遇到了严重的错误。使用sqlalchemy,更改为不同的db-api就像更改连接URL一样简单,它可以确保处理数据类型强制的任何内容都按照您的预期处理。
那就是说,为了利用它,你需要根据sqlalchemy的模式定义你的表并使用他们的查询API,但你会得到很多。