Python 如何确定在更改连接字符集时是否应编码?

Python 如何确定在更改连接字符集时是否应编码?,python,mysql,encoding,sqlalchemy,Python,Mysql,Encoding,Sqlalchemy,我有一个MySQL设置,其中所有的表/字段和字符集设置都是UTF-8,除了来自SqlAlchemy的连接 我最近将连接字符集更改为UTF-8,以便在任何地方使用UTF-8 更改此设置时,数据库中的旧值呈现错误,例如: Björn => Björn 这没有问题,我只是使用python中的encode方法收集值并对其进行编码,然后将它们重新放入 当我尝试转换设置更改后插入的、已经正确的值时,就会出现问题 有没有一个好方法来确定我是否应该对值进行编码?您以前的编码可能是拉丁语1 通过查看连续

我有一个MySQL设置,其中所有的表/字段和字符集设置都是
UTF-8
,除了来自SqlAlchemy的连接

我最近将连接字符集更改为
UTF-8
,以便在任何地方使用
UTF-8

更改此设置时,数据库中的旧值呈现错误,例如:

Björn => Björn
这没有问题,我只是使用python中的encode方法收集值并对其进行编码,然后将它们重新放入

当我尝试转换设置更改后插入的、已经正确的值时,就会出现问题


有没有一个好方法来确定我是否应该对值进行编码?

您以前的编码可能是拉丁语1

通过查看连续字节,您可能可以检测字符串何时使用拉丁语1而不是UTF-8编码。UTF-8标准有一个可用于检测一段文本是否用拉丁语1或UTF-8编码的标准:

  • 00-7F范围内的任何字节都是安全的,当然,这些是ASCII值,并且这些代码点在两种编码之间匹配。这里没有帮助,不需要帮助

  • 字节C0、C1和F5-FF在UTF-8编码中是非法的。任何包含这些的字符串都必须是拉丁-1编码的

  • C2-DF范围内的字节必须后跟80-BF范围内的字节。如果您有任何两个字节与此不匹配,那么您手上可能有一个拉丁-1编码字符串

如果所有的编码都是拉丁-1字符(直到Unicode代码点255),那么可以到此为止;任何包含E0-FF范围内字节的内容都将是旧拉丁语-1数据

如果切换后确实在UTF-8中添加了数据,这超出了拉丁语-1的范围,则还需要包括以下规则:

  • E0-EF范围内的字节标记为3字节UTF-8字符。接下来的两个字节必须再次落在80-BF范围内
3个UTF-8字节的数据覆盖了其余部分,您不太可能在此之外进行编码。但是,如果您在这之外进行编码,请查找:

  • F0-F4范围内的字节后面必须紧跟80-BF范围内的3个字节
如果所有这些条件都匹配,则可能有一个UTF-8字符串,但不能100%确定。如果其中任何一个不匹配,您肯定有一个拉丁-1字符串。但是,拉丁语-1代码点C2-DF后面不太可能跟80-BF,因为后者大多数是控制代码或更深奥的变音符号。也许您可以通过寻找多个2字节UTF-8序列来进一步缩小范围,以提高您的信心分数


总之(tl;dr):通过查看多字节序列,可以找到大多数拉丁1编码字符串。如果它们不在严格的UTF-8标准范围内,那么您手中就有一个拉丁-1字符串。

没有完全基于数据的防弹方法来猜测编码-编码检测非常棘手,根据您的语料库,您可能会得到误报。