我有一个打印出一个方向结构的小程序。 除非直接名称包含德语变元字符,否则它工作正常。 在这种情况下,int在目录行之后打印一个空行。
我在Windows 7 64位上运行Python 3.50。
这个代码…
class dm(): ... def print(self, rootdir=None, depth=0): if rootdir is None: rootdir = self.initialdir if rootdir in self.dirtree: print('{}{} ({} files)'.format(' '*depth, rootdir, len(self.dirtree[rootdir]['files']))) for _dir in self.dirtree[rootdir]['dirs']: self.print(os.path.join(rootdir, _dir), depth+1) else: pass
…产生以下输出:
B:\scratch (11 files) B:\scratch\Test1 (3 files) B:\scratch\Test1 - Kopie (0 files) B:\scratch\Test1 - Übel (0 files) B:\scratch\Test2 (3 files) B:\scratch\Test2\Test21 (0 files)
这是如此Codepage设置为65001.如果我将代码页更改为例如850空白行消失,但当然“Ü”打印不正确。
结构self.dirtree是一个列表字典的字典,用os.walkparsing,似乎没问题。
Python还是Windows? 有什么build议么?
马文
当使用代码页65001(UTF-8)时有几个错误 – 所有这些都是由于Windows控制台(即conhost.exe)造成的,而不是Python造成的。 最好的解决方案是避免这个错误的代码页,而是使用宽字符API,比如通过加载win_unicode_console 。
您遇到了在Windows 10之前使用的旧版控制台中存在的错误(如果您选择“使用旧版控制台”选项,则在Windows 10中仍然可用)。控制台将UTF-8缓冲区解码为UTF- 16并报告它将b'\xc3\x9c'
(即"Ü"
编码为UTF-8)写为一个字符,但是应该报告它写入的字节数,即两个字节 。 Python的缓冲sys.stdout
看到,显然一个字节没有写,所以它忠实地写行的最后一个字节,这是b'\n'
。 这就是为什么你得到一个额外的换行符。 如果写缓冲区有很多非ASCII字符,特别是U + 07FF以上的编码为三个UTF-8字节的代码,结果可能会更糟糕。
如果您尝试将"Ü"
粘贴到交互式REPL中,则会出现更糟糕的错误。 即使在Windows 10中,该错误仍然存在。在这种情况下,进程正在读取编码为UTF-8的控制台的宽字符(UTF-16)输入缓冲区。 控制台通过WideCharToMultiByte
进行转换,缓冲区假定一个Unicode字符是目标代码页中的单个字节。 但是对于UTF-8来说,这是完全错误的,其中一个UTF-16代码可能映射多达三个字节。 在这种情况下,它是两个字节,控制台只在转换缓冲区中分配一个字节。 所以WideCharToMultiByte
失败,但控制台是否尝试增加翻译缓冲区大小? 号码是否失败了? 不。它实际上返回它'成功'读取0字节。 对于发出EOF
(文件结束)的Python REPL,所以解释器就会退出,就像在提示符下输入Ctrl+Z
。