python - 将 Python 设置为 stdout 以匹配终端的编码

标签 python linux bash shell ubuntu

关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。












想改进这个问题?将问题更新为 on-topic对于堆栈溢出。

6年前关闭。




Improve this question




我有一个 python 项目,我必须在其中显示从另一台机器以未知编码传输给我的数据。我在 Ubuntu VM 上运行 python 3。我得到的是字节流(可能是命令输出或 cat'd 文件或类似文件)。我只需要尽可能地显示数据,无论来源如何。

作为测试,我正在尝试 猫/dev/urandom 并让它通过 python 以与我自己键入命令相同的方式显示。为了使其可重现,我使用了 头 -n 2/dev/urandom 而不是你用 cat 得到的源源不断的流。

在 bash 中,当我对文件进行分类时,我得到了标准的随机垃圾。我有 LANG=en_US.ETF-8。很多字符并没有真正呈现(有点像带有问号的菱形)或只是空白(因为它显然不是 UTF-8,它只是原始数据的随机字节)

eJ̘��}��jf��)���N�n��t��8=����X-�L�^t�M����Z���g�8#K T��c��z�ZO+�ϩD1{|EX
��)'���ei۝{W�r��畴��Ii�Y���
                        �}���+��;-�i-
                                     S��Az
                                          uV�1XBxFZ3+4��G�*��Q�+!  

但是,如果我在 python 中读取文件并打印到标准输出,则会出现编码错误,除非我使用“latin-1”。我什至尝试使用默认流中的编码,假设它是从终端继承的。这显然是不对的,因为我需要管道远程端的流中的编码(我没有)。
>>> f = open("foo.txt", "rb")
>>> data = f.read(530)
>>> import sys
>>> sys.stdout.write(data.decode(sys.stdout.encoding))

正如预期的那样,产生的错误是基于不遵循 UTF8 编码标准的随机数据:
>>> sys.stdout.write(data.decode(sys.stdout.encoding))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb1 in position 0: invalid start byte

因此,它从 LANG(?) 中获取 UTF-8 并应用它,但它只是存在编码问题并且失败了。如果我明确使用“latin-1”,我会得到类似的东西,但它也与终端不同。
sys.stdout.write(data.decode('latin-1'))

产量(名义示例 - 不是实际文本):
©7yIº*ø^Mÿ*Ig«áEIt±.Q   ÈyT?æsÎ_%v1DÎú¹×,sÛÐûóÜun¢$&6YuApÁ¼­pnòàJð

所以,问题是......我如何阅读终端设置,以便我可以使用它们来解码和重现终端上会出现的内容?

我已经检查了这些其他问题:Why does Python print unicode characters when the default encoding is ASCII?Convert bytes to a Python string它们涵盖了一些部分,但我不理解与 shell/bash/etc 的交互。

编辑(答案评估):

使用 errors="replace"让我很接近。 os.write 复制了 cat 的输出。差异似乎是基于错误字符是如何聚集在一起的,因此差异并不重要。

编辑编辑(实际解决方案):最后,我显然需要从原始机器读取语言环境/远程编码,以便我可以将其发送,然后将字节解释为该编码,然后转码为本地机器编码,然后显示.从这个意义上说,这个项目没有经过深思熟虑,因为我没有收到远程信息,我显然需要它。我最终使用了这个(对于当前的构建,因为它消除了错误):
sys.stdout.write(data.decode('utf-8', errors='replace'))
sys.stdout.flush()

编辑(清除问题文本以关注实际主题)

最佳答案

解决问题而不是给出的问题(https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)

I have a python project which is getting sent to various users on various linux flavors (vms, real machines, etc) all with python 3. As part of this program, the python may display one of their local files to the terminal screen. I'm looking for a way to read the settings of the terminal to use them for displaying the data. In this way, it will be up to user to set their terminal to handle extended character sets or whatever if that is what they want.



您已经发现 Python 使用 locale解决终端的可能编码 - 如果您编写 Python 3 str到标准输出,使用 write()print() ,你会发现它是为终端自动编码的。这意味着您的代码不需要(也不应该必须)检测其环境。

我说的是“可能的编码”,因为字符的解码不是shell的责任,而是终端(Terminal/iTerm/Putty等)的责任,终端可能远程运行在用户的桌面上。您将不得不希望大多数人会离开 locale和终端编码作为默认值,现在幸运的是通常是 UTF-8。

如果您要在他们的本地机器上打开一个文本文件,您还应该在读取该文件时应用编码(您可以直接使用解码/编码将其写出来,但您将无法干净地操作它)。谢天谢地,open()还将使用 locale.getpreferredencoding() ,源自用户的语言环境,用于设置编码以解码文件。

这意味着,如果用户的 LANG='en_GB.UTF-8' ,然后 locale.getpreferredencoding() == "UTF-8" .如果你用 open('file.txt', 'r') 打开一个文件,该文件将作为 UTF-8 解码为 Python str。

您将能够将此数据写入/打印到控制台,确信您已尽您所能来解决我们必须忍受的编码遗留问题。

关于python - 将 Python 设置为 stdout 以匹配终端的编码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36164586/

相关文章:

python - Mysql连接,一个还是多个?

python - 在 Python 程序中处理大量对象

linux - Arch Linux - apt-get update 等效命令?

php - Amazon Scraper 脚本适用于 XAMPP Windows,但不适用于 Linux 上的 PHP5 Cli

linux - 在bash shell脚本中,在文件的最后10行中搜索单词。如果找到,则执行一个操作,否则执行另一个操作

linux - 如何在 bash 中抓取币安价格

python - 在 kivy lang 和 python 中访问子部件属性的值

python - 如何从多维(深度未知)python 字典中递归删除某些键?

linux - 当我尝试gcc make linux-headers -`uname -r`时遇到错误

http - 远程(Http)文件更改时如何执行操作?