【问题标题】:Why is there a unicode error only when piping the output of a python script?为什么只有在管道 python 脚本的输出时才会出现 unicode 错误?
【发布时间】:2018-06-20 13:48:55
【问题描述】:

我使用 2.7 编写的 Python 脚本(seafile-cli,来自 Seafile,一个文件同步解决方案)。

我知道unicode is problematic in Python 2,但幸运的是在启动脚本时正确处理了带有变音符号的文件名:

$ # seaf-cli status
# Name  Status  Progress
photos  downloading     0/0, 0.0KB/s
Ma bibliothèque downloading     566/1770, 1745.7KB/s
videos  downloading     28/1203, 5088.0KB/s
dev-perso       downloading     0/0, 0.0KB/s
dev-pro downloading     0/0, 0.0KB/s

令我惊讶的是,当管道输出此输出时,Python 脚本崩溃并显示 UnicodeEncodeError

$ seaf-cli status | cat -
# Name  Status  Progress
photos  downloading     0/0, 0.0KB/s
Traceback (most recent call last):
  File "/usr/bin/seaf-cli", line 845, in <module>
    main()
  File "/usr/bin/seaf-cli", line 841, in main
    args.func(args)
  File "/usr/bin/seaf-cli", line 649, in seaf_status
    tx_task.rate/1024.0)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe8' in position 11: ordinal not in range(128)

虽然我知道它可能首先与 Ma bibliothèque 存在问题(它没有),但为什么管道它会触发 Traceback?

不应该是shell的问题吗? - 输出在那个时候已经“离开”了脚本。

编辑:answeranother question 中。标记为重复。

【问题讨论】:

标签: python shell unicode pipe python-unicode


【解决方案1】:

Python 知道如何处理程序内部的编码,因为它使用终端应用程序使用的任何编码。

当您发送(管道)输出时,它需要被编码。这是因为使用管道实际上在应用程序之间发送字节流。每个管道都是一个单向通道,一侧写入数据,另一侧读取数据。

使用管道或重定向,您将数据发送到 fd,由另一个应用程序读取。

因此,您需要确保 Python 在将数据发送出去之前对其进行正确编码,然后输入程序需要在处理之前对其进行解码

您也可能会发现这个question 很有用


更新:我将尝试详细说明编码。我的回答第一行的意思是,因为您的 Python 解释器使用特定的编码,它知道如何将十六进制值(实际字节)转换为符号。

我的翻译没有;如果我尝试从您的文本中创建一个字符串 - 我会收到一个错误:

>>> s = 'bibliothèque'
Unsupported characters in input

这是因为我在解释器上使用了不同的编码。

您的 shell 使用与 Python 解释器不同的编码。当 Python 从程序中发送数据时,它使用默认编码:ASCII。它无法使用 ASCII 翻译您的特殊字符(由十六进制值 \xe8 显示)。因此,您必须指定要使用的编码以便 Python 发送它。

如果你改变你的 shell 编码,你也许可以克服这个问题 - 检查这个question on SO

PS - Ned Batchelder 在youtube 上有一段很棒的关于 Unicode 的视频 - 也许这会对这个主题有更多的了解。

【讨论】:

  • 是的,我明白这一点 - 经历了在 Python 2 中处理 unicode 的痛苦。单独启动脚本时(没有管道),输出是正确的。这意味着脚本已正确编码。管道时由接收程序来处理它得到的东西(在我的例子中是cat)。但是 Python 脚本会崩溃吗?
  • 顺便说一句,这是否是管道无关紧要,重定向&gt; 也会使其崩溃。
  • 您的代码在脚本中运行时可以工作,因为 Python 编码 输出到您的终端应用程序使用的任何编码。如果您在其他地方使用管道或重定向它 - 那么您必须自己对其进行编码。
  • 对不起,我不明白。使用print 输出字符串。如果存在编码问题,它会在那个时候出现(python 2 脚本中的单行 print 'école' 崩溃 - 因为缺少输出字符串的编码)。由于它在独立运行时已经毫无问题地发出了这一行,因此在标准输出(发送流的位置)上发生的任何事情都由 shell 来管理。是否重定向此标准输出流如何影响脚本?
  • stackoverflow.com/a/4027726/903011 给出了确切的解决方案。我会接受你的,因为它让我理解了print 与管道 o 重定向中描述符的区别。谢谢。
猜你喜欢
  • 2012-04-18
  • 2022-01-18
  • 2022-01-19
  • 2022-06-20
  • 2021-05-21
  • 2018-05-27
  • 1970-01-01
  • 2020-10-18
  • 2019-04-22
相关资源
最近更新 更多