关键字: 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编码的…