【问题标题】:Bulletproof work with encoding in Python在 Python 中使用编码进行防弹工作
【发布时间】:2013-12-03 10:20:13
【问题描述】:

Python2中关于unicode的问题。

据我所知,我应该始终decode 从外部(文件、网络)读取的所有内容。 decode 使用参数中指定的字符集将外部字节转换为内部 Python 字符串。所以decode("utf8")表示外面的字节是unicode字符串,会被解码成python字符串。

此外,我应该始终encode 我在外面写的所有内容。我在 encode 函数的参数中指定编码,它会转换为正确的编码并写入。

这些说法是对的,不是吗?

但有时当我解析 html 文档时会出现解码错误。据我了解其他编码的文档(例如cp1252),当我尝试使用 utf8 编码对其进行解码时会发生错误。那么问题来了怎么写防弹应用呢?

我发现有一个很好的库来猜测编码是chardet,这是编写防弹应用程序的唯一方法。对吧?

【问题讨论】:

  • 该文档通常会在某处附带其编码声明。 See if the charset is specified. 如果您没有编码,或者声明的编码错误,您可能会遇到不可避免的错误。那么你能做的最好的事情就是用一些策略来处理错误,并产生一个可能看起来像你想要的结果。
  • 我发现 Python 中编码问题的最佳概述是以下页面:sebsauvage.net/python/snyppets/#unicode 此外,您的帖子中有一个小误解:«decode» 函数将始终为您提供 Unicode。我同意前面的评论,即:首先依赖字符集声明。确实没有一种“防弹”方法来处理错误编码的文档。
  • stackoverflow.com/questions/606191/… 也可以提供帮助。

标签: python unicode encoding


【解决方案1】:

...decode("utf8") 表示外部字节是unicode字符串,它们将被解码为python字符串。

...

这些说法是对的,不是吗?

不,外部字节是二进制数据,它们不是 unicode 字符串。所以<str>.decode("utf8") 将通过将<str> 中的字节解释为UTF-8 来生成Python unicode 对象;如果无法将字节解码为 UTF-8,则可能会引发错误。

确定任何给定文档的编码不一定是一项简单的任务。您要么需要一些外部信息源来告诉您编码,要么您需要了解文档中的内容。例如,如果您知道它是一个在内部指定其编码的 HTML 文档,那么您可以使用类似 the one outlined in the HTML Standard 的算法来解析文档以找到编码,然后使用该编码来解析文档(这是一个两遍手术)。但是,仅仅因为 HTML 文档指定了编码,并不意味着它可以使用该编码进行解码。如果数据损坏或文档一开始没有正确编码,您仍然可能会收到错误。

有诸如chardet 之类的库(我看到您已经提到过)会尝试为您猜测文档的编码(这只是猜测,不一定正确)。但是他们可能有自己的问题,例如性能,并且他们可能无法识别您文档的编码。

【讨论】:

  • 这个得到我的投票;但也许要强调chardet 是一种启发式猜测器,它不会尝试验证它报告的结果是否有效——您需要为解码错误做好准备,并且可能会退回到次优猜测,或者只是给出up(例如,配置错误的 Web 服务器可能会为您提供一堆 JPEG 字节,而这些字节根本就没有一种语言)。
【解决方案2】:

尝试将您的函数包装在 try:except: 调用中。

  • 尝试解码为 utf-8:
  • 如果不是 utf-8,则捕获异常:
  • 如果引发异常,请尝试下一个编码:
  • 等等等等……

使它成为一个函数,当它找到一个未被排除的编码时(如果)返回 str,当它用尽其编码列表并引发最后一个异常时返回 None 或空 str。

就像其他人说的,编码应该记录在某个地方,所以先检查一下。

效率不高,坦率地说,由于我的技能水平,可能还有很长的路要走,但对我的新手来说,它可能会缓解处理未知或无证编码时的一些问题。

【讨论】:

    【解决方案3】:

    cp437 转换为unicode。这样,您就可以将字节正确地转换为 unicode 并返回。

    【讨论】:

    • 如果您是-1,请说出您是否需要解释为什么cp437。如果你只是不喜欢cp437,因为unicode很时髦,那也没办法。
    猜你喜欢
    • 1970-01-01
    • 2011-05-12
    • 2011-04-03
    • 2020-07-16
    • 1970-01-01
    • 2021-03-18
    • 2020-07-22
    • 1970-01-01
    相关资源
    最近更新 更多