23

我有一个使用 SQLAlchemy 引擎执行的 SQL 查询:

result = engine.execute('SELECT utf_8_field FROM table')

数据库是 MySQL,列类型是 UTF-8 编码的 TEXT。返回的 utf_8_field 的类型是“str”,即使我在创建引擎时设置了选项 convert_unicode=True。现在发生的情况是,如果我的字符串中有一个像“é”这样的字符(它不是 7 位 ASCII,而是在扩展的 ASCII 集中),我在尝试执行此操作时会收到 UnicodeDecodeError:

utf_8_field.encode("utf-8")

确切的错误是:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xe9 in position 1: ordinal not in range(128)

在研究这个时,我发现 str.encode 不支持扩展的 ASCII 字符集!我觉得这很奇怪,但这是另一个问题。

我不明白为什么 SQLAlchemy 没有给我一个 unicode 字符串。我以前使用 DB-API,效果很好。我的表还没有 SQLAlchemy 表对象,这就是我使用执行命令的原因。

任何的想法?

4

2 回答 2

48

如果要自动转换数据,则应在创建引擎时指定字符集:

create_engine('mysql+mysqldb:///mydb?charset=utf8')

单独设置use_unicode不会告诉 sqlalchemy 使用哪个字符集。

于 2012-05-30T15:24:24.707 回答
3

要将 UTF-8 字节串转换为 unicode 对象,您需要解码

utf_8_field.decode('utf8')

此外,在执行 raw SELECTthrough时.execute,SQLAlchemy 没有元数据可以确定您的查询正在返回 utf-8 数据,因此它不会为您将此信息转换为 unicode。

换句话说,convert_unicode仅当您使用 SQLAlchemy SQL 表达式 API 或 ORM 功能时才有效。

编辑:正如所指出的,您的数据甚至不是 UTF-8 编码的;0xe9在 UTF-8 中表示介于\u9000和之间的字符\u9fff,它们是 CJK 统一表意文字,而您说它是 latin-1 字符,其 UTF-8 代码将以 . 开头0xc3。这可能是ISO-8859-1(latin-1) 或类似的:

>>> u'é'.encode('ISO-8859-1')
'\xe9'

然后结论是告诉 SQLAlchemy 使用charset=utf8参数连接到不同的字符集,正如@mata 所指出的那样。

于 2012-05-30T15:18:55.400 回答