为什么Python unicode字符串需要特殊处理UTF-8 BOM?

时间:2011-09-01 18:02:10

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

出于某种原因,从 UTF-8 文件中读取unicode字符串时,Python似乎遇到了 BOM 的问题。请考虑以下事项:

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

似乎很简单,不是吗?

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

  

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

对谷歌的简短访问显示,BOM必须手动清除

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

这个运行正常。但是我很难看到这方面的任何优点。

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

2 个答案:

答案 0 :(得分:28)

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

答案 1 :(得分:13)

您写道:

 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。现在看看为什么BOMs在UTF-8中如此愚蠢/糟糕/有害?他们实际上是在破坏事物。

BOM是元数据,而不是数据,UTF-8编码规范不像UTF-16和UTF-32规范那样允许它们。所以Python带你到你的话,遵循规范。很难为此负责。

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

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