用Python将UTF-8字符串写入MySQL

用Python将UTF-8字符串写入MySQL,python,unicode,utf-8,Python,Unicode,Utf 8,我正在尝试将用户帐户数据从Active Directory推送到我们的MySQL服务器。这可以完美地工作,但不知何故,字符串最终显示了umlauts和其他特殊字符的编码版本 Active Directory使用以下示例格式返回字符串:M\xc3\xbcller 这实际上是Müller的UTF-8编码,但我想将Müller写入我的数据库,而不是M\xc3\xbcller 我尝试使用此行转换字符串,但它在数据库中产生相同的字符串: tempEntry[1]=tempEntry[1]。解码(“utf-

我正在尝试将用户帐户数据从Active Directory推送到我们的MySQL服务器。这可以完美地工作,但不知何故,字符串最终显示了umlauts和其他特殊字符的编码版本

Active Directory使用以下示例格式返回字符串:
M\xc3\xbcller

这实际上是
Müller
的UTF-8编码,但我想将
Müller
写入我的数据库,而不是
M\xc3\xbcller

我尝试使用此行转换字符串,但它在数据库中产生相同的字符串:
tempEntry[1]=tempEntry[1]。解码(“utf-8”)

如果在python控制台中运行
print“M\xc3\xbcller.decode(“utf-8”)
,则输出是正确的

有没有办法正确插入这个字符串?我需要这个特定的格式,一个web开发人员谁想要有这个确切的格式,我不知道为什么他不能直接使用PHP转换字符串


其他信息:我正在使用MySQLdb;表和列编码为utf8_general_ci

假设您正在使用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所指出的,unicode和字符集的结合使用对于连接来说是冗长的,但我对标准库之外最有用的python库也有一种天生的偏执,所以我尝试显式地让bug在库发生变化时易于发现。

正如@marr75所建议的,确保在连接上设置了
charset='utf8'
。设置
use\u unicode=True
并不是绝对必要的,因为设置字符集意味着这一点

然后确保将unicode对象传递给db连接,因为它将使用传递给光标的字符集对其进行编码。如果您传递的是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_命令param来强制连接使用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')
对字符串进行解码终于奏效了。现在,所有内容都按应有的方式插入。另一个完整的解决方案可以在这里找到:

和db.set\u character\u set('utf8'),意味着 使用unicode=True

(希望回复上述答案,但没有足够的声誉…)

在这种情况下,无法获得unicode结果的原因是:

>>> print c.fetchall()
(('M\xc3\xbcller',),)
是MySQLdb 1.2.x中带有*bin排序规则的错误,请参阅:

http://sourceforge.net/tracker/index.php?func=detail&aid=2663436&group_id=22307&atid=374932


在这种特殊情况下(排序规则utf8\u-bin-或[任何东西]\u-bin…),您必须期望“原始”值,这里是utf-8(是的,这很糟糕,因为没有通用的修复)。

最近我遇到了同样的问题,字段值是字节字符串而不是unicode。这里有一些分析

概述 一般来说,要从游标中获得unicode值,只需将
charset
参数传递给连接构造函数,并具有非二进制表字段(例如
utf8\u general\u ci
)。传递
use\u unicode
无效,因为只要
charset
有值,它就会被设置为true

MySQLdb尊重游标描述字段类型,因此如果游标中有
DATETIME
列,则值将转换为Python
datatime.DATETIME
实例、
DECIMAL
DECIMAL.DECIMAL
等等,但二进制值将通过字节字符串按原样表示。大多数解码器都是在中定义的,通过向连接构造函数提供
conv
参数,可以在实例基础上重写它们

但unicode解码器在这里是个例外,这可能是一个设计缺陷。它们在构造函数中连接到实例转换器。因此,只能在instance basic上重写它们

变通办法 让我们看看问题代码

import MySQLdb

connection = MySQLdb.connect(user = 'guest', db = 'test', charset = 'utf8')
cursor     = connection.cursor()

cursor.execute(u"SELECT 'abcdё' `s`, ExtractValue('<a>abcdё</a>', '/a') `b`")

print cursor.fetchone() 
# (u'abcd\u0451', 'abcd\xd1\x91')
print cursor.description 
# (('s', 253, 6, 15, 15, 31, 0), ('b', 251, 6, 50331648, 50331648, 31, 1))
print cursor.description_flags 
# (1, 0)
因此,通过操纵连接实例
converter
dict,可以实现所需的unicode解码行为

如果您想覆盖该行为,这里是可能文本字段的dict条目在构造函数之后的样子

import MySQLdb
import MySQLdb.constants as const

connection = MySQLdb.connect(user = 'guest', db = 'test', charset = 'utf8')
print connection.converter[const.FIELD_TYPE.BLOB]
# [(128, <type 'str'>), (None, <function string_decoder at 0x7fa472dda488>)]
导入MySQLdb
将MySQLdb.constants作为常量导入
connection=MySQLdb.connect(用户='guest',数据库='test',字符集='utf8')
打印连接.const.FIELD\u TYPE.BLOB]转换器
#[(128,),(无,)]

MySQLdb.constants.FLAG.BINARY==128
。这意味着如果一个字段有二进制标志,它将是
str
,否则将应用unicode解码器。因此,如果您想尝试转换二进制值,可以弹出第一个元组。

还有一种情况可能有点罕见

如果您首先在mysqlworkbench中创建一个模式,您将得到编码错误,并且无法通过添加字符集配置来解决它

这是因为默认情况下,mysqlworkbench是通过拉丁1创建模式的,所以您应该首先设置字符集!

是的,我正在使用MySQLdb。在我之前的帖子里忘了提到这一点。我尝试设置字符集并手动使用unicode(虽然前者似乎意味着后者),但结果是一样的。我还尝试在INSERT语句中设置.decode(“utf-8”)。仍然具有相同的格式…数据库中列的编码设置为什么?尝试utf8-bin。您可能完全正确地传输了数据,但它是用一些不包含字符的编码编写的
import MySQLdb
import MySQLdb.converters as conv
import MySQLdb.constants as const

connection = MySQLdb.connect(user = 'guest', db = 'test', charset = 'utf8')
connection.converter[const.FIELD_TYPE.LONG_BLOB] = connection.converter[const.FIELD_TYPE.BLOB]
cursor = connection.cursor()

cursor.execute(u"SELECT 'abcdё' `s`, ExtractValue('<a>abcdё</a>', '/a') `b`")

print cursor.fetchone()
# (u'abcd\u0451', u'abcd\u0451')
print cursor.description
# (('s', 253, 6, 15, 15, 31, 0), ('b', 251, 6, 50331648, 50331648, 31, 1))
print cursor.description_flags
# (1, 0)
import MySQLdb
import MySQLdb.constants as const

connection = MySQLdb.connect(user = 'guest', db = 'test', charset = 'utf8')
print connection.converter[const.FIELD_TYPE.BLOB]
# [(128, <type 'str'>), (None, <function string_decoder at 0x7fa472dda488>)]