用Python将UTF-8字符串写入MySQL
我正在尝试将用户帐户数据从Active Directory推送到我们的MySQL服务器。这可以完美地工作,但不知何故,字符串最终显示了umlauts和其他特殊字符的编码版本 Active Directory使用以下示例格式返回字符串:用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-
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
列,则值将转换为Pythondatatime.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>)]