python输出到Windows控制台

时间:2016-02-04 14:35:01

标签: windows python-3.x

我有一个打印出直接结构的小程序。 除非目标名称包含德语变音字符,否则它可以正常工作。 在这种情况下,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)

将代码页设置为65001即可。如果我将代码页更改为例如850然后空行消失,但当然“Ü”打印不正确。

结构self.dirtree是列表的序列,用os.walk解析,看起来没问题。

Python还是Windows?有什么建议吗? 马文

1 个答案:

答案 0 :(得分:0)

使用代码页65001(UTF-8)时有几个错误 - 所有这些错误都归功于Windows控制台(即conhost.exe),而不是Python。最好的解决方案是避免这个错误的代码页,而是使用宽字符API,例如加载win_unicode_console

您遇到了在Windows 10之前使用的旧版控制台中存在的错误。(如果您选择“使用旧版控制台”选项,它仍可在Windows 10中使用。)控制台对UTF-8缓冲区进行解码到UTF-16并报告它将b'\xc3\x9c'(即"Ü"编码为UTF-8)写为一个字符,但它应该报告 bytes 的数量它写道,这是两个。 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一样退出。