简而言之,你应该改变:
Unicode(500)
到:
Unicode(500, unicode_errors='ignore', convert_unicode='force')
(Python 2 代码如下,但原理在 python 3 中适用;只有部分输出会有所不同。)
发生了什么是当你解码一个字节串时,它会抱怨如果字节串不能被解码,你会看到错误。
>>> u = u'ABCDEFGH\N{TRADE MARK SIGN}'
>>> u
u'ABCDEFGH\u2122'
>>> print(u)
ABCDEFGH™
>>> s = u.encode('utf-8')
>>> s
'ABCDEFGH\xe2\x84\xa2'
>>> truncated = s[:-1]
>>> truncated
'ABCDEFGH\xe2\x84'
>>> truncated.decode('utf-8')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/cliffdyer/.virtualenvs/edx-platform/lib/python2.7/encodings/utf_8.py",
line 16, in decode
return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 8-9: unexpected
end of data
不过,Python 提供了不同的可选模式来处理解码错误。引发异常是默认设置,但您也可以截断文本或将字符串的格式错误部分转换为官方的 unicode 替换字符。
>>> trunc.decode('utf-8', errors='replace')
u'ABCDEFGH\ufffd'
>>> trunc.decode('utf-8', errors='ignore')
u'ABCDEFGH'
这正是列处理中发生的事情。
查看sqlalchemy/sql/sqltypes.py 中的Unicode 和String 类,您可以将unicode_errors 参数传递给构造函数,该构造函数将其值传递给编码器的错误参数。还有一个注意事项,您需要设置convert_unicode='force' 才能使其工作。
因此,Unicode(500, unicode_errors='ignore', convert_unicode='force') 应该可以解决您的问题,前提是您可以截断数据的末端。
如果您对数据库有一定的控制权,您应该能够通过将数据库定义为使用utf8mb4 字符集来防止将来出现此问题。 (不要只使用utf8,否则它将在四字节 utf8 字符上失败,包括大多数表情符号)。然后,您将保证在您的数据库中存储并返回有效的 utf-8。