现在的位置: 首页 > 综合 > 正文

Python 和 数据库相关的编码问题

2018年04月30日 ⁄ 综合 ⁄ 共 2283字 ⁄ 字号 评论关闭

关键字: python, mysqldb, unicode

页面是用python 写的,说一下版本:

Mysql 4.1.20

Python 2.3.4

MySQL-python 1.2.1_p2

数据库的一个表里面的一个字段是中文(没办法,人家的名字,总不能写拼音阿),这个字段就用了gbk的字符集。

开发的时候,也是花了好长时间折腾这个问题,encode/decode/Unicode…什么都用了,不行,最后,在执行带有中文

字符的语句的时候,执行一个 “SET NAMES ‘gbk’” 就可以了。

>>cursor.execute(“SET NAMES ‘gbk’”)

然后执行自己的语句,插入中文无误。

但这几天突然不行了。。想想没改什么啊,,,

中间尝试了讲脚本文件的编码改了,把python的defaultencoding改了,等等,都是按下葫芦起了瓢//

最后,在python的命令行里面试

Python 2.3.4 (#1, Feb 22 2005, 04:09:37)

[GCC 3.4.3 20041212 (Red Hat 3.4.3-9.EL4)] on linux2

Type "help", "copyright", "credits" or "license" for more information.

>>> import MySQLdb

>>> conn.character_set_name()

'latin1'

>>> cursor=conn.cursor()

>>> a="中国"

>>> a

'/xd6/xd0/xb9/xfa'

>>> cursor.execute("set names 'gbk'")

0L

>>> conn.character_set_name()

'latin1'

>>> query="update users.accounts set display='%s' where id=92" % a

>>> query

"update users.accounts set display='/xd6/xd0/xb9/xfa' where id=92"

>>> cursor.execute(query)

Traceback (most recent call last):

File "<stdin>", line 1, in ?

File "/usr/lib/python2.3/site-packages/MySQLdb/cursors.py", line 146, in execute

query = query.encode(charset)

UnicodeDecodeError: 'ascii' codec can't decode byte 0xd6 in position 35: ordinal not in range(128)

>>>

 

Ooo,出错了

但是,如果这个中文定义为unicode,就可以

>>> a=u"中国"

>>> query="update users.accounts set display='%s' where id=92" % a

>>> cursor.execute(query)

1L

>>>

那么,u和不u有啥区别呢?

>>> b="中国"

>>> b

'/xd6/xd0/xb9/xfa'

>>> a=u"中国"

>>> a

u'/xd6/xd0/xb9/xfa'

>>>

原来是这样,b只是一个str对象,a是一个unicode的对象

那么,现在做的工作就是,把b换成a

>>> c=b.decode("gb2312")

>>> c

u'/u4e2d/u56fd'

>>>

不太对,出来的是gb2312的..这个到了mysql里面就是乱码了。

>>> c=b.decode("utf8")

Traceback (most recent call last):

File "<stdin>", line 1, in ?

UnicodeDecodeError: 'utf8' codec can't decode bytes in position 0-1: invalid data

>>>

出错了…,看来这个str不是用utf8编码的

同样,ascii的编码也不行

最后,想起了latin1

>>> c=b.decode("latin1")

>>> c

u'/xd6/xd0/xb9/xfa'

>>> a

u'/xd6/xd0/xb9/xfa'

>>>

Yeah!就是它!

查了一下手册,发现转换也可以这样来

>>> c=unicode(b,'latin1')

>>> c

u'/xd6/xd0/xb9/xfa'

>>>

所以,最后在所有需要插入中文的地方,除了要set names gbk之外,还需要一个,就是把字符串转换为latin1编码的unicode对象。

实际上,再MySQLdb的cursor.py里面,有一句

charset = db.character_set_name() //这里返回的是latin1,也就是目前我使用的mysql的默认编码

query = query.encode(charset) //这里是query语句用数据库默认的编码来encode这个query string。

所可以看出,如果我的这个query 是utf8的string,那么,我就需要指定charset为 utf8,这个可能也是一种方法,看来变更mysql的默认字符集也是一种选择。(以后再试验吧)

总结一下:解决python+MySQLdb插入中文字符的一个方法,假设MySQL的默认字符集是latin1,那么需要两个步骤:

1. 执行insert前,先要执行cursor.execute(“set names ‘gbk’”)

2. 要将query这个字符串转换为 unicode对象 : query = unicode(query,’latin1’)


前提是,这些query都是latin1编码的…

抱歉!评论已关闭.