使用Python将UTF-8字符串写入MySQL
我正在尝试把用户账户数据从一个活动目录(Active Directory)推送到我们的MySQL服务器。这一过程运行得很顺利,但不知道为什么,字符串中的变音符号和其他特殊字符显示成了编码后的版本。
活动目录返回的字符串格式是这样的:M\xc3\xbcller
这实际上是
我试着用这一行代码来转换字符串,但结果在数据库中还是显示同样的字符串:tempEntry[1] = tempEntry[1].decode("utf-8")
如果我在Python控制台运行print "M\xc3\xbcller".decode("utf-8")
,输出是正确的。
有没有什么方法可以正确插入这个字符串?我需要这种特定格式,因为有个网页开发者希望得到这个确切的格式,我不知道他为什么不能直接用PHP来转换这个字符串。
补充信息:我使用的是MySQLdb;表和列的编码是utf8_general_ci。
8 个回答
假设你在使用MySQLdb,连接数据库的时候需要设置两个参数:use_unicode=True 和 charset="utf8"。
更新内容:
如果我在一个测试表上运行以下代码,我得到的结果是 -
>>> db = MySQLdb.connect(host="localhost", user='root', passwd='passwd', db='sandbox', use_unicode=True, charset="utf8")
>>> c = db.cursor()
>>> c.execute("INSERT INTO last_names VALUES(%s)", (u'M\xfcller', ))
1L
>>> c.execute("SELECT * FROM last_names")
1L
>>> print c.fetchall()
(('M\xc3\xbcller',),)
这就是“正确的方式”,字符被正确地存储和取回了。你朋友写的PHP脚本在输出的时候没有正确处理编码。
正如Rob所指出的,use_unicode和charset一起使用是为了让连接更加明确,但我对即使是最有用的Python库也有点小担心,所以我尽量把参数写得清楚,这样如果库有变化,出错的时候更容易找到问题。
正如@marr75所建议的,确保在你的连接中设置 charset='utf8'
。设置 use_unicode=True
并不是绝对必要的,因为设置字符集时已经包含了这个意思。
接下来,确保你传递给数据库连接的是unicode对象,因为它会使用你传给游标的字符集进行编码。如果你传递的是一个已经用utf8编码的字符串,那么在到达数据库时会被重复编码。
所以,像这样:
conn = MySQLdb.connect(host="localhost", user='root', password='', db='', charset='utf8')
data_from_ldap = 'M\xc3\xbcller'
name = data_from_ldap.decode('utf8')
cursor = conn.cursor()
cursor.execute(u"INSERT INTO mytable SET name = %s", (name,))
你也可以尝试通过传递 init_command 参数来强制连接使用utf8,不过我不太确定这是否必要。测试5分钟应该能帮你决定。
conn = MySQLdb.connect(charset='utf8', init_command='SET NAMES UTF8')
另外,虽然这几乎不值得一提,因为4.1版本已经很旧了,但请确保你使用的是 MySQL >= 4.1。
我找到了我的问题的解决办法。用 .decode('unicode_escape').encode('iso8859-1').decode('utf8')
来解码字符串,最后终于成功了。现在所有内容都能正确插入了。完整的其他解决方案可以在这里找到:通过python-ldap处理来自Active Directory的unicode编码字符串