【问题标题】:Why do Python unicode strings require special treatment for UTF-8 BOM?为什么 Python unicode 字符串需要对 UTF-8 BOM 进行特殊处理?
【发布时间】:2011-11-08 14:57:26
【问题描述】:

由于某种原因,Python 在从 UTF-8 文件中读取 unicode 字符串时似乎遇到了 BOM 问题。考虑以下几点:

with open('test.py') as f:
   for line in f:
      print unicode(line, 'utf-8')

看起来很简单,不是吗?

这就是我的想法,直到我从命令行运行它并得到:

UnicodeEncodeError: 'charmap' 编解码器无法编码字符 u'\ufeff' 在位置 0:字符映射到 <undefined>

对 Google 的简短访问表明,必须手动清除 BOM

import codecs
with open('test.py') as f:
   for line in f:
      print unicode(line.replace(codecs.BOM_UTF8, ''), 'utf-8')

这个运行良好。但是我很难看到这有什么好处。

上述行为背后是否有理由?相比之下,UTF-16 可以无缝运行。

【问题讨论】:

  • 它无法对其进行编码,因为 U+FEFF 是无效的非字符。这是因为 UTF-8 文件不应该包含 BOM!它们既不是必需的,也不是推荐的。字节顺序对 8 位代码单元没有意义。他们也把事情搞砸了,因为如果这些文件中有无关的(阅读:any)BOM,你不能再只做cat a b c > abc。 UTF-8 流不应包含 BOM。如果你需要指定文件的内容,你应该使用更高级别的prototocl。这只是一个 Windows 错误。
  • @tchrist - 你知道,这个解释结合 Josh Lee 的建议将成为一个完美的答案。
  • 你的错误信息是否碰巧提到了文件名cp437.py

标签: python unicode utf-8 io character-encoding


【解决方案1】:

'utf-8-sig' 编码将代表您使用 BOM 签名。

【讨论】:

  • 是的,这是解决办法,但我更感兴趣的是为什么。
  • @Gringo Suave:有趣的是,Unicode 标准确实允许 UTF-8 中的 BOM。请参阅unicode.org/versions/Unicode5.0.0/ch02.pdf 第 36 页,表 2-4。
  • 有谁知道如果 BOM 不存在这是否仍然有效?
【解决方案2】:

你写道:

 UnicodeEncodeError: 'charmap' codec can't encode character u'\ufeff' in position 0: character maps to <undefined>

当您在 Python 中指定 "utf-8" 编码时,它会让您信服。 UTF-8 文件不应该包含 BOM。它们既不是必需的,也不是推荐的。字节顺序对 8 位代码单元没有意义。

BOM 也搞砸了,因为你不能再只是这样做:

$ cat a b c > abc 

如果这些 UTF-8 文件中包含无关的(读取:任何)BOM。现在看看为什么 BOM 在 UTF-8 中如此愚蠢/糟糕/有害?他们实际上破坏了东西。

BOM 是元数据,而不是数据,UTF-8 编码规范不像 UTF-16 和 UTF-32 规范那样允许它们。所以 Python 相信你的话并遵循规范。很难怪它。

如果您尝试使用 BOM 作为文件类型幻数来指定文件的内容,那么您真的不应该这样做。您确实应该为这些元数据目的使用更高级别的 prototocl,就像使用 MIME 类型一样。

这只是另一个蹩脚的 Windows 错误,解决方法是使用备用编码 "utf-8-sig" 传递给 Python。

【讨论】:

猜你喜欢
  • 2019-03-08
  • 1970-01-01
  • 1970-01-01
  • 2013-09-30
  • 1970-01-01
  • 1970-01-01
  • 2010-11-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多