Windows控制台上Python中的UnicodeEncodeError

cpx*_*cpx 1 python unicode python-3.x

在递归目录中的文件并在控制台中打印文件名时,我遇到以下错误:

Traceback (most recent call last):
  File "C:\Program Files\Python33\lib\encodings\cp437.py", line 19, in encode
    return codecs.charmap_encode(input,self.errors,encoding_map)[0]
UnicodeEncodeError: 'charmap' codec can't encode character '\u2013' in position
53: character maps to <undefined>
Run Code Online (Sandbox Code Playgroud)

根据错误,文件名字符串\u2013中的一个字符是与常见的-减号字符不同的EN DASH 字符.

我检查了我设置的Windows编码437.现在,我看到有两个选项可以通过更改Windows控制台的编码或将文件名中的字符转换为适合控制台编码来解决此问题.我将如何在Python 3.3中做到这一点?

sud*_*dip 6

Windows控制台使用cp437编码,并且该编码不支持字符\ u2013.尝试将此添加到您的代码中:

sys.stdout = io.TextIOWrapper(sys.stdout.buffer,'cp437','backslashreplace')
Run Code Online (Sandbox Code Playgroud)


bob*_*nce 5

或者从文件名转换get中的字符以适应控制台编码

控制台编码可能已经是正确的(虽然无法从错误消息中分辨出来).代码页437根本不包含该字符,因此您将无法打印它.

您可以stdout使用具有回退编码的文本编码器重新打开,如iamsudip的回答所示,该回答使用backslashreplace至少可读(如果不是可靠的可恢复)输出而不是错误.

更改Windows控制台的编码

您可以通过chcp 1252在运行Python之前执行console命令来执行此操作,但这仍然只会为您提供不同的有限的可打印字符库 - 包括U + 2013,但不会有很多其他Unicode字符.

理论上你可以chcp65001来获得UTF-8,它允许你打印任何角色.遗憾的是,C运行时的标准IO实现存在严重缺陷,这通常会使其在实践中无法使用.

这种令人遗憾的事态会影响使用MS C运行时的stdio库调用的所有应用程序,包括Python和大多数其他语言,结果是Windows控制台上的Unicode在大多数情况下都不起作用.

如果你真的必须将Unicode输出到Windows控制台,你可以WriteConsoleW直接使用Win32 API ctypes,但它并不是很有趣.

  • @MarkRansom:这不符合我的经验.似乎问题是控制台句柄Windows内部将`WriteFile`路由到`WriteConsoleA`,它返回解码的Unicode字符数而不是写入的字节数.`WriteFile`很高兴地将这个错误的数字返回给CRT的`write`函数. (2认同)