当通过管道将包含 Unicode 的输出从 Python 2 传输到 grep 时,为什么会出现 Unicode 错误?

当通过管道将包含 Unicode 的输出从 Python 2 传输到 grep 时,为什么会出现 Unicode 错误?

我有一个 python 脚本,用于将有用字符集合的 unicode 代码点和字符名称输出到终端(xfce4-terminal)。它变得有点大,所以我尝试通过 grep 管道输出,并惊讶地得到了Python错误。 grep 错误不会让我感到惊讶;我会假设 grep 没有为 unicode 输入设置。

错误的简单单行演示:

python -c 'print "diameter "+ unichr(0x2300)'|grep 'd'

回报

UnicodeEncodeError: 'ascii' codec can't encode character u'\u2300' in position 9: 
ordinal not in range(128)`

我的默认 python 是 Python 2(Xubuntu 18.04 和许多旧版 python 2 代码)。添加

# -*- coding: utf-8 -*- 

到脚本没有区别(不应该,因为脚本都是 ASCII 格式的)。

如果我将脚本更新为 Python 3 并像 python3 -c 'print ("diameter "+ unichr(0x2300))'|grep 'd'正常运行一样运行它。这意味着 shebang 显式调用 python3 并使脚本可执行,也可以工作。尽管能够解决这个问题,但我很好奇发生了什么:

python 2 如何以及为什么知道它正在输出到 grep 的管道,而不是直接输出到终端,并继续以不同的方式运行?

答案1

程序检测其标准输出是否连接到终端或其他设备的情况并不罕见。功能isatty() 是 posix 的一部分并且使用得相当多。

一个非常常见的示例是,以下两个命令之间的输出显着不同:

ls
ls | cat

在 python2 的情况下,它看起来随着 python 使用的默认编码而改变: https://stackoverflow.com/questions/2276200/changing-default-encoding-of-python/7892892#7892892

这显然是一个有意识的设计决定,但尚不清楚它的优点是什么。

参考答案中的建议是设置:PYTHONIOENCODING


Python2 已贬值。无论如何,你应该尝试切换到 python 3。

这并没有回答为什么它们不同的问题,但是谷歌上的一些简单搜索显示了它失败的原因。 这个堆栈溢出答案指向本文档的第一个示例:

https://docs.python.org/2/library/functions.html#unichr

简而言之,在将 unicode 字符串添加到 Askii 字符串之前,您不会将其转换为字节。

相关内容