【问题标题】:Python3 - ascii/utf-8/iso-8859-1 can't decode byte 0xe5 (Swedish characters)Python3 - ascii/utf-8/iso-8859-1 无法解码字节 0xe5(瑞典字符)
【发布时间】:2013-08-18 02:59:49
【问题描述】:

我试过iorepr() 等,它们都不起作用!

输入å时出现问题(\xe5)

(这些都不起作用)

import sys
print(sys.stdin.read(1))


sys.stdin = io.TextIOWrapper(sys.stdin.detach(), errors='replace', encoding='iso-8859-1', newline='\n')
print(sys.stdin.read(1))


x = sys.stdin.buffer.read(1)
print(x.decode('utf-8'))

他们都给我大致UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe5 in position 0: unexpected end of data

还尝试使用以下命令启动 Python:export PYTHONIOENCODING=utf-8 也不起作用。


现在,这就是我所在的位置:

import sys, codecs
sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach())
sys.stdin = codecs.getwriter("utf-8")(sys.stdin.detach())

x = sys.stdin.read(1)

print(x.decode('utf-8', 'replace'))

这给了我:�
近了……

如何在我的控制台中将\xe5 转换为å? 如果它不破坏input(),因为这个解决方案破坏了它。

注意:我知道以前有人问过这个问题,但没有人能解决它.. 尤其是 io


我的系统的一些信息

os.environ['LANG'] == 'C'
sys.getdefaultencoding() == 'utf-8'
sys.stdout.encoding == 'ANSI_X3.4-1968'
sys.stdin.encoding == 'ANSI_X3.4-1968'

我的操作系统:ArchLinux 运行 xterm
运行locale -a 给我:C | POSIX | sv_SE.utf8

我已经关注了这些:

(还有 50 多个)

解决方案(有点,仍然打破input()

sys.stdout = codecs.getwriter("latin-1")(sys.stdout.detach())
sys.stdin = codecs.getwriter("latin-1")(sys.stdin.detach())

x = sys.stdin.read(1)

print(x.decode('latin-1', 'replace'))

【问题讨论】:

  • 您没有输入 UTF-8 数据;看起来像 Latin-1。
  • print sys.stdin.encoding 告诉你 python 认为你的终端编解码器是什么?
  • 它是.. 我认为.. (iso-8859-1),但即使是“Latin-1”也给我带来了麻烦。那么如何解决呢?因为我整天都在为此烦恼,一整天都在文学上......(检查我的系统信息,在底部......它是ANSI_X3
  • ANSI_X3.4-1968 是 ASCII。基本上,请参阅en.wikipedia.org/wiki/ASCII#Aliases。这是相当古老的。这是什么平台?
  • ArchLinux 在 xorg 下运行 xterm。

标签: python unicode character-encoding stdout python-3.3


【解决方案1】:

你在xterm 中运行这个,不是support UTF-8 by default。以xterm -u8 运行它或使用uxterm 来修复它。

解决这个问题的另一种方法是使用不同的语言环境;例如,将您的语言环境设置为 Latin-1:

export LANG=sv_SE.ISO-8859-1

但是您被限制为 256 个代码点,而 Unicode 标准的全部范围(数百万)。

请注意,Python 2 从未解码输入;写出您从终端读取的内容看起来不错,因为您读取的原始字节由终端在相同的语言环境中解释;读取和写入 Latin-1 字节就可以了。然而,这与处理 Unicode 数据并不完全相同。

【讨论】:

  • 我正在接近它,而导出可能会做到这一点。但是啊,我仍然得到sys.stdout.write(c) -> 'ascii' codec can't encode character '\xe5' in position 0: ordinal not in range(128)
【解决方案2】:

在 Python3 中采用编程方法,而不是更改终端编解码器:

import sys, codecs
sys.stdout = codecs.getwriter("latin-1")(sys.stdout.detach())
sys.stdin = codecs.getwriter("latin-1")(sys.stdin.detach())
sys.stdout.write(sys.stdin.read(1).decode('latin-1', 'replace'))

这不仅让你选择/匹配你的终端“编码”,它实际上需要没有外部影响(例如export LANG=sv_SE.ISO-8859-1)。

唯一的缺点

input('something: ')

会破坏,修复它是:

# Since it's bad practice to name function the
# same as __builtins__, we'll go ahead and call it something
# we're used to but isn't in use any more.
def raw_input(txt):
    sys.stdout.write(txt)
    sys.stdout.flush()
    sys.stdin.flush()
    return sys.stdin.readline().strip()

非常感谢Martijn 提供了一个 说明原因,事实上数据是 latin-1!

【讨论】:

  • 但正如您所说,“我不知道我的客户将在他们的控制台上使用什么”。如果他们不使用“latin-1”,这也行不通。您正在强制 Python 假设终端是“latin-1”。为正在使用的终端正确设置环境变量。这也是您的客户必须做的事情。您还可以设置环境变量PYTHONIOENCODING 来强制Python 也使用特定的编码,但它更好地匹配终端。
  • @MarkTolonen 不,但现在我了解如何获取控制台编码并使用 writer 正确匹配我的主脚本顶部的内容。这让我的工作比以前轻松多了,至少我通过重写标准输出以匹配控制台,接近Python2.7 的易用性。
  • "...匹配我主脚本顶部的那个。"您是指#coding 行吗?如果这就是您所指的,那与控制台无关。这仅表示源文件编码。
  • “在我的主脚本的顶部”我放置了sys.stdout = ...sys.stdin = ...,这使我可以正常使用sys.stdout.write,而不会出现任何编码问题。这些 2-liner 一劳永逸地解决了编码问题。它简单、时尚、简单。我不是在谈论#Coding,如果我愿意的话,我会这样写的:) 我说的是整个沙班的两行解决方案,这让我头疼几天移植到Python3.X :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-15
  • 2014-08-29
  • 1970-01-01
  • 1970-01-01
  • 2011-07-26
  • 2011-04-07
相关资源
最近更新 更多