【问题标题】:Utf-8 on windows pythonwindows python上的utf-8
【发布时间】:2015-12-18 03:21:17
【问题描述】:

我有 html 文件来读取解析等,它是在 unicode 上编码的(我用记事本看到的)但是当我尝试时

infile = open("path", "r") 
infile.read()

它失败了,我遇到了著名的错误:

UnicodeEncodeError:“charmap”编解码器无法编码位置 xx 中的字符:字符映射到未定义

所以为了测试,我尝试将文件的包含内容复制粘贴到一个新文件中并将其保存在 utf-8 中,然后尝试使用这样的编解码器打开它:

inFile = codecs.open("path", "r", encoding="utf-8")
outputStream = inFile.read()

但我收到此错误消息:

UnicodeEncodeError : 'charmap' 编解码器无法在位置 0 对字符 u'\ufeff' 进行编码:字符映射到未定义

我真的不明白,因为我是用utf8创建这个文件的。

【问题讨论】:

  • 那是unicode BOM 好像是utf-16,你能不能试试传encoding='utf-16'
  • @EdChum 我试过了,结果是:> UnicodeError: UTF-16 stream does not start with BOM
  • 您能否仅在前几行发布原始输入数据或文件链接,谢谢。另一种选择是跳过前几个字符,但实际上它应该能够毫无问题地打开它
  • 这是一个来自 Outlook 的 htm 文件,开头如下:"schemas.microsoft.com/office/2004/12/omml" xmlns="w3.org/TR/REC-html40">"
  • 您确定在.read()! 期间收到了该错误吗?读取期间的错误将是“无法解码”。听起来您在写入文件或打印到终端时遇到错误

标签: python python-3.x unicode utf-8


【解决方案1】:

UnicodeEncodeError 建议代码在 encoding Unicode 文本到字节时失败,即您的实际代码尝试打印到 Windows 控制台。见Python, Unicode, and the Windows console


上面的链接修复了UnicodeEncodeError。下一个问题是找出"path" 文件中的文本使用什么字符编码。如果notepad.exe 正确显示文本,则意味着它是使用locale.getprefferedencoding(False) 编码的(类似于Windows 上的cp1252)或文件具有BOM

如果您确定编码是 utf-8 则直接将其传递给open()。不要使用codecs.open()

with open('path', encoding='utf-8') as file:
    html = file.read()

有时,输入可能包含使用多个(不一致)编码编码的文本,例如,智能引号可能使用cp1252 编码,而 html 的其余部分是 utf-8 ——您可以使用 bs4.UnicodeDammit 修复它。另见A good way to get the charset/encoding of an HTTP response in Python

【讨论】:

  • 如果记事本说“Unicode”(正如 OP 所说),则表示 UTF-16。其他编码通常称为“ANSI”(cp1252 和朋友)和“UTF-8”(即带有 BOM 的 UTF-8)。
  • @roeland:是的。 “它是在 unicode 上编码(我用记事本看到的)” 可以这样解释问题。该理论的问题在于codecs.open("path", encoding='utf-8').read() 返回u'\ufeff',即utf-8-sig 更有可能。 'utf-8' 编码对于 BOM_UTF16_BEBOM_UTF16_LE 都失败。
  • 是的,这个问题有点混乱,因为它涉及两个文件,一个是“Unicode”的原始文件,另一个是他重新保存为“UTF-8”的文件。
  • @roeland:无论如何,问题是UnicodeEncodeError,即当 OP 尝试将 Unicode 文本打印到 Windows 控制台时。
  • 啊哈,我明白了。那是微妙的
【解决方案2】:

期待OP更新问题以反映实际问题,该问题是由于未定义终端编码引起的。

Windows 控制台在 Unicode 支持方面是出了名的差。如需终极支持,请参阅https://pypi.python.org/pypi/win_unicode_console。本质上,安装“win_unicode_console”(pip install win_unicode_console)。然后在代码的顶部:

import win_unicode_console
win_unicode_console.enable()

您可能还需要使用合适的字体 - 请参阅 https://stackoverflow.com/a/5750227/1554386

当您使用带有 UTF-8 BOM 的输入时,您应该使用 utf_8_sig 编解码器,以便在处理内容之前剥离 BOM。

由于这是 Python 3,所以在使用 open() 时无需使用 codecs 模块来设置编码。

把它放在一起看起来像:

import win_unicode_console
win_unicode_console.enable()

infile = open("path", "r", encoding="utf_8_sig")

【讨论】:

  • 最好避免修改脚本。您可以使用run 模块代替(win-unicode-console 的一部分)运行它:py -m run your-unicode-printing-script.py 或者如果适合您的情况,则将win_unicode_console.enable() 调用放入sitecustomizeusercustomize 模块中。
【解决方案3】:

原始文件可能使用utf-16(Windows 使用术语UNICODE 表示该编码)。

Windows 上的 UTF-8 编码文件通常以幻数 b"\xef\xbb\xbf"(U+FEFF 的 UTF-8 编码)开头,因此读取该文件的应用程序知道它被保存为 UTF-8 而不是某些 ANSI 代码页。 utf8-sig 将自动丢弃该字符。

【讨论】:

  • 附注:不要使用codecs.open。在 Py3 上,您可以将 encoding 参数传递给常规 open,在 Py2.7 上,您可以导入 io.open(与 Py3 的内置 open 相同)并执行相同操作。 codecs.open 有一些愚蠢的怪癖(例如,不进行通用换行处理)。
猜你喜欢
  • 2010-09-15
  • 1970-01-01
  • 2010-12-12
  • 2012-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-10
  • 2017-05-07
相关资源
最近更新 更多