使用webpy时为什么中文乱码但使用MySQLdb时是正常的?

时间:2012-11-07 10:45:41

标签: python mysql-python web.py

我在mysql中创建一个数据库,并使用webpy构建我的Web服务器。

但是,当webpy和MySQLdb分别使用它们来访问数据库时,对于中文字符来说很奇怪。

以下是我的问题:

我的表t_test(utf8数据库):

id     name
1      测试

“测试”的utf8代码是:\ xe6 \ xb5 \ x8b \ xe8 \ xaf \ x95

使用MySQLdb进行“select”时这样:

    c=conn.cursor()
    c.execute("SELECT * FROM t_test")
    items = c.fetchall()
    c.close()
    print "items=%s, name=%s"%(eval_items, eval_items[1])

结果正常,打印出来:

    items=(127L, '\xe6\xb5\x8b\xe8\xaf\x95'), name=测试

但是当我使用webpy做同样的事情时:

    db = web.database(dbn='mysql', host="127.0.0.1", 
             user='test', pw='test', db='db_test', charset="utf8")
    eval_items=db.select('t_test')
    comment=eval_items[0].name
    print "comment code=%s"%repr(comment)
    print "comment=%s"%comment.encode("utf8")

发生中文乱码,打印结果为:

    comment code=u'\xe6\xb5\u2039\xe8\xaf\u2022'
    comment=忙碌鈥姑€

我知道webpy的数据库也依赖于MySQLdb,但这两种方式都有所不同。为什么呢?

顺便说一下,由于上面的原因,我可以直接使用MySQLdb来解决我的汉字乱码问题,但它丢失了表中的列名 - 它太不合适了。我想知道如何用webpy解决它?

1 个答案:

答案 0 :(得分:1)

确实发生了一些非常错误的事情 - 正如你在评论中所说,unicode repr。 “测试”的字节是E6B5 8BE8 AF95 - 这可以在我的utf-8终端上运行:

>>> d
'\xe6\xb5\x8b\xe8\xaf\x95'
>>> print d
测试

但请查看“comment”unicode对象上的字节:

comment code=u'\xe6\xb5\u2039\xe8\xaf\u2022'

您的内容的含义部分是注释的utf-8字节 (字符表示为“\ xYY”,部分编码为Unicode点 (用\ uYYYY表示的chares) - 这表示严重的垃圾。

MySQL有一些捕获正确解码(utf-8或其他)编码 其中的文本 - 其中一个是传递一个适当的“charset”参数 连接。但你已经这样做了 -

您可以尝试的一种方法是将选项use_unicode=False传递给连接 - 并在您自己的代码中解码utf-8字符串。

db = web.database(dbn='mysql', host="127.0.0.1", 
         user='test', pw='test', db='db_test', charset="utf8", use_unicode=False)

检查要连接的选项以及您可能尝试的其他参数:

http://mysql-python.sourceforge.net/MySQLdb.html

无论使用正确如何,通过上面的提示,我得到了一个解决方法 - 它看起来像Unicode字符(不是unicode对象中的utf-8原始字节) 在您编码的字符串中编码为以下编码之一: (“cp1258”,“cp1252”,“palmos”,“cp1254”)

其中,cp1252与“latin1”几乎相同 - 这是MySQL使用的默认字符集 如果它没有得到连接中的“charset”参数。但这不仅仅是一个问题 web2py没有将它传递给数据库,因为你得到了错误的字符,而不是 只是错误的编码 - 就好像web2py来回编码和解码你的字符串,并忽略编码错误

从所有这些编码中,我可以检索原始的“测试”字符串,作为utf-8字节字符串,例如:

comment = comment.encode("cp1252", errors="ignore")

所以,放置这一行可能对你有用,但猜测unicode永远不会好 - proepr的事情是缩小使web2py首先给你那些半解码的utf-8字符串,然后让它停在那里。

<强>更新

我在这里检查 - 这是发生了什么 - 从mysql读取正确的utf-8 '\xe6\xb5\x8b\xe8\xaf\x95'字符串,然后在交付给你之前,(在use_unicode = True情况下)0-这些字节是被解码好像他们是“cp1252” - 这会产生不正确的u'\xe6\xb5\u2039\xe8\xaf\u2022' unicode。它可能是一个web2py错误,例如,它没有将“charset = utf8”参数传递给实际连接。当您设置“use_unicode = False”而不是给出原始字节时,它显然选择了不正确的unicode,使用“utf-8”对其进行了编码 - 这会产生 你评论过的'\xc3\xa6\xc2\xb5\xe2\x80\xb9\xc3\xa8\xc2\xaf\xe2\x80\xa2'序列(更不正确)。

总而言之,我上面提到的解决方法似乎是检索原始正确字符串的唯一方法 - 即,给定错误的unicode,执行u'\xe6\xb5\u2039\xe8\xaf\u2022'.encode("cp1252", errors="ignore") - 即 做其他事情来建立数据库连接(或者如果可能的话,可以更新web2py或mysql驱动程序)

**更新2 ** 我更好地检查了web2py dal.py文件本身的代码 - 它默认尝试将连接设置为utf-8 - 但看起来它会尝试MySQLdb和pymysql驱动程序 - 如果你已经安装了两个尝试卸载pymysql ,只留下MySQLdb。