gpt4 book ai didi

python - 为什么这种到 utf8 的转换不起作用?

转载 作者:太空狗 更新时间:2023-10-29 17:31:17 26 4
gpt4 key购买 nike

我有一个输出一些字符的子进程命令,例如'\xf1'。我试图将其解码为 utf8,但出现错误。

s = '\xf1'
s.decode('utf-8')

上面的抛出:

UnicodeDecodeError: 'utf8' codec can't decode byte 0xf1 in position 0: unexpected end of data

当我使用“latin-1”时它可以工作,但 utf8 不应该也能工作吗?我的理解是 latin1 是 utf8 的一个子集。

我是不是漏掉了什么?

编辑:

print s # ñ
repr(s) # returns "'\\xa9'"

最佳答案

您混淆了 Unicode 和 UTF-8。 Latin-1 是 Unicode 的一个子集,但它不是 UTF-8 的一个子集。 避免像瘟疫一样思考单个代码单元。只需使用代码点。不要考虑UTF-8。想想 Unicode。这就是您感到困惑的地方。

演示程序的源代码

在 Python 中使用 Unicode 非常容易。它尤其适用于 Python 3 和宽构建,这是我使用 Python 的唯一方式,但如果你小心坚持使用 UTF-8,你仍然可以在窄构建下使用遗留的 Python 2。

为此,始终将您的源代码编码和输出编码正确地转换为 UTF-8。现在停止考虑 UTF-anything 并在整个 Python 程序中仅使用 UTF-8 文字、逻辑代码点数字或符号字符名称。

这是带有行号的源代码:

% cat -n /tmp/py
1 #!/usr/bin/env python3.2
2 # -*- coding: UTF-8 -*-
3
4 from __future__ import unicode_literals
5 from __future__ import print_function
6
7 import sys
8 import os
9 import re
10
11 if not (("PYTHONIOENCODING" in os.environ)
12 and
13 re.search("^utf-?8$", os.environ["PYTHONIOENCODING"], re.I)):
14 sys.stderr.write(sys.argv[0] + ": Please set your PYTHONIOENCODING envariable to utf8\n")
15 sys.exit(1)
16
17 print('1a: el ni\xF1o')
18 print('2a: el nin\u0303o')
19
20 print('1a: el niño')
21 print('2b: el niño')
22
23 print('1c: el ni\N{LATIN SMALL LETTER N WITH TILDE}o')
24 print('2c: el nin\N{COMBINING TILDE}o')

这里是带有非 ASCII 字符的打印函数 uniquoted使用 \x{⋯} 符号:

% grep -n ^print /tmp/py | uniquote -x
17:print('1a: el ni\xF1o')
18:print('2a: el nin\u0303o')
20:print('1b: el ni\x{F1}o')
21:print('2b: el nin\x{303}o')
23:print('1c: el ni\N{LATIN SMALL LETTER N WITH TILDE}o')
24:print('2c: el nin\N{COMBINING TILDE}o')

演示程序的示例运行

下面是该程序的示例运行,显示了三种不同的执行方式(a、b 和 c):第一个设置为源代码中的文字(将受 StackOverflow 的 NFC 转换影响,因此不能trusted!!!) 和第二组分别带有数字 Unicode 代码点符号 Unicode 字符名称,再次 uniquoted这样您就可以看到真正的东西:

% python /tmp/py
1a: el niño
2a: el niño
1b: el niño
2b: el niño
1c: el niño
2c: el niño

% python /tmp/py | uniquote -x
1a: el ni\x{F1}o
2a: el nin\x{303}o
1b: el ni\x{F1}o
2b: el nin\x{303}o
1c: el ni\x{F1}o
2c: el nin\x{303}o

% python /tmp/py | uniquote -v
1a: el ni\N{LATIN SMALL LETTER N WITH TILDE}o
2a: el nin\N{COMBINING TILDE}o
1b: el ni\N{LATIN SMALL LETTER N WITH TILDE}o
2b: el nin\N{COMBINING TILDE}o
1c: el ni\N{LATIN SMALL LETTER N WITH TILDE}o
2c: el nin\N{COMBINING TILDE}o

我真的不喜欢看二进制,但这是二进制字节的样子:

% python /tmp/py | uniquote -b
1a: el ni\xC3\xB1o
2a: el nin\xCC\x83o
1b: el ni\xC3\xB1o
2b: el nin\xCC\x83o
1c: el ni\xC3\xB1o
2c: el nin\xCC\x83o

故事的寓意

即使您使用 UTF-8 源代码,您也应该只考虑和使用逻辑 Unicode 代码点编号(或符号命名字符),而不是 UTF-8 序列表示(或用于UTF-16 的问题)。需要代码单元而不是代码点的情况极为罕见,这只会让您感到困惑。

如果您使用广泛构建的 Python3,您将获得比使用这些选择的替代方案更可靠的行为,但这是 UTF-32 问题,而不是 UTF-8 问题。如果您顺其自然,UTF-32 和 UTF-8 都很容易使用。

关于python - 为什么这种到 utf8 的转换不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7163485/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com