6

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

但是webpy和mysqldb分别使用它们访问数据库时的行为之间的汉字就很奇怪了。

以下是我的问题:

我的表 t_test(utf8 数据库):

id     name
1      测试

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

当使用 MySQLdb 做这样的“选择”时:

    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 的,但是这两种方式有很大的不同。为什么?

BTW,由于上面的原因,我可以直接使用MySQLdb来解决我的汉字乱码问题,但是它丢失了表中的列名——太不雅了。我想知道如何用 webpy 解决它?

4

1 回答 1

1

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

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

但是看看你的“评论”unicode对象上的字节:

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

这意味着您的内容的一部分是注释的 utf-8 字节(表示为 "\xYY" 的字符和部分编码为 Unicode 点(用 \uYYYY 表示的字符) - 这表示严重的垃圾。

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”几乎相同——如果它在连接中没有获得“charset”参数,则这是 MySQL 使用的默认字符集。但这不仅是 web2py 没有将其传递给数据库的问题,因为您得到了损坏的字符,而不仅仅是错误的编码 - 就好像 web2py 正在来回编码和解码您的字符串,并忽略编码错误

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

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

所以,现在放置这条线可能对你有用,但是用 unicode 猜测从来都不是一件好事 - 正确的事情是缩小 web2py 的范围,首先为你提供那些半解码的 utf-8 字符串,然后让它停在那里。

更新

我在这里检查过 - 这是发生了什么 -'\xe6\xb5\x8b\xe8\xaf\x95'从 mysql 读取正确的 utf-8 字符串,然后在将其交付给您之前,(在 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 ** 我进一步检查了 web2pydal.py文件本身中的代码 - 它默认尝试将连接设置为 utf-8 - 但它看起来会同时尝试 MySQLdb 和 pymysql 驱动程序 - 如果你都安装了尝试卸载pymysql,只留下 MySQLdb。

于 2012-11-07T21:43:12.217 回答