Python 3.x str.encode()更改UTF-8字符

Python 3.x str.encode()更改UTF-8字符,python-3.x,utf-8,character-encoding,Python 3.x,Utf 8,Character Encoding,有人提出,这个问题是重复的。我在原始代码或最小值中都没有使用任何b''文本。请参见下面的嵌入编辑: 我已经将我今天遇到的一个问题简化为以下最小的Python 3代码: x='\xc3\xb3' print(''.join([hex(ord(c))[2:] for c in x])) print(''.join([hex(c)[2:] for c in x.encode()])) 当我运行此代码时,我得到: c3b3 c383c2b3 str.encode()真的应该将UTF-8字符ó(带锐音

有人提出,这个问题是重复的。我在原始代码或最小值中都没有使用任何b''文本。请参见下面的嵌入编辑:

我已经将我今天遇到的一个问题简化为以下最小的Python 3代码:

x='\xc3\xb3'
print(''.join([hex(ord(c))[2:] for c in x]))
print(''.join([hex(c)[2:] for c in x.encode()]))
当我运行此代码时,我得到:

c3b3
c383c2b3
str.encode()真的应该将UTF-8字符ó(带锐音符的拉丁文小写字母O)更改为两个字符ó(带扬抑符和上标三的拉丁文大写字母A)


编辑:

根据一位评论员的建议,未输入任何内容。在某些情况下只输入ó,在另一些情况下从文本文件中读取。涉及的文本文件与原始问题有关。它是当前版本Ubuntu的系统字典文件。该文件的日期为2011年10月23日,文件系统路径如原始问题的命令示例所示

最初的问题涉及在该文件的第1053行遇到亚松森一词。Asunción中的ó字符具有字节序列C3B3,在拉丁语中用带锐音符的小写字母O描述(此处为无法正确阅读Unicode文本的读者描述)

任何代码中都没有使用b“”文本,既不是原始文本,也不是最小文本

问题的本质被发现为UTF字符从ó字符更改为ó。这涉及到将c3b3更改为c383c2b3。字典文件字面上包含两个字节c3b3,按照预期和UTF-8表中的描述显示ó。最初的问题是由于长度

使用
str.encode()

最初显示此问题的最低代码是:

x='Asunción'
print(' '.join([hex(ord(c))[2:] for c in x]))
print(' '.join([hex(c)[2:] for c in x.encode()]))
但是我发现很多人看不到小写的acute o,所以我把它改为十六进制代码(\x),它在
str.encode()
之前和之后都有相同的十六进制验证输出,这是上面第一个最小的例子,带有字面完整的单词
Asunción

然后我决定只使用受影响的字符,并且在十六进制输出中不使用空格,这样会更简单

编辑结束,返回原始帖子:


此UTF-8字符出现在最新的美式英语Ubuntu版本
/usr/share/dict/American English
上的美式英语词典文件中。您可以通过以下命令查看该文件中的第一个单词:

head -1053 /usr/share/dict/american-english|tail -1
head -1053 /usr/share/dict/american-english|tail -1|od -Ad -tx1
您可以使用以下命令以十六进制显示:

head -1053 /usr/share/dict/american-english|tail -1
head -1053 /usr/share/dict/american-english|tail -1|od -Ad -tx1
字符描述是从中获得的。我正在运行Python 3.5.2,它是在2天前更新的Ubuntu 16.04.1 LTS上的GCC 5.4.0上编译的

编辑:


这里的正确答案是完全避免字节,而不使用
str.encode()
?还是有更好的答案?

从非常大的q问题中摘取小q问题:

当我运行此代码时,我得到:

c3b3
c383c2b3
c3b3

c383c2b3

str.encode()真的应该更改UTF-8字符ó(拉丁语)吗 小写字母O(带锐音符)至两个字符(拉丁文大写字母) A带扬抑符和上标3)

没有所谓的“UTF-8字符”。
带锐音符的拉丁文小写字母O
是一个Unicode字符(python:str对象)。其Unicode代码点是U+00F3

>>> import unicodedata as ucd
>>> smalloacute = u"\u00f3"
>>> ucd.name(smalloacute)
'LATIN SMALL LETTER O WITH ACUTE'
现在,您可以将其编码为
字节
对象:

>>> smalloacute.encode('utf8')
b'\xc3\xb3'
并将字节对象写入文件或任何您想执行的操作。 请注意,
b'\xc3'
是一个字节对象,与带扬抑符的
拉丁文大写字母a没有任何有用的关系。同样地,
b'\xb3'
上标三

您当然不想再次旋转utf8控制盘;结果不是很有用:

>>> `smalloacute.encode('utf8').decode('latin1').encode('utf8')
b'\xc3\x83\xc2\xb3'`
注意:
decode('latin1')
只是将类型从
bytes
更改为
str


回到原始问题/语句“str.encode()更改UTF-8字符”。简短回答:不是!从文件中可以得到一个表示Unicode o-acute字符的2字节序列。您可能希望直接使用该序列。或者,您可能希望执行bytes.decode()并在
str
对象中工作。您绝对不应该使用
字节.kludge().encode()
您甚至不必调用encode()来查看字符串中的内容。Python将以交互模式向您显示:

>>> '\xc3\xb3'
'ó'
这是一个长度为2的unicode字符串,其字符与您看到的完全相同。除了在边界处将其发送到您的终端或从源文件中读取外,根本不涉及字节或UTF-8。如果您希望字符串中包含unicode字符,可以直接插入它,或使用\x(如果FF或更少)对其进行转义,\u(如果FFFF或更少),或\U(对于所有字符)

如果出于某种原因确实需要UTF-8文本,那么这将是字节文本:

>>> b'\xc3\xb3'
b'\xc3\xb3'
这是一个字节字符串,长度为2。当您要求Python向您显示它时,它会以书面形式显示它,因为Python不知道您的字节中有什么

>>> b'\xc3\xb3'.decode()
'ó'

输入是字节字符串(长度为2,包含UTF-8数据),输出是unicode字符串(长度为1).

您输入了字符,Python将其返回给您。您期望的是什么?我认为您简化事情的努力可能会重复,这使事情变得更糟。字符串
“\xc3\xb3”
“ó”
不是同一个字符串,因此您的两个示例显示了不同的问题。因为这导致了转移,所以它不是非常清楚您真正的问题是什么。您似乎试图从文件中读取
“Asunción”
,但是您没有显示任何用于读取的Python代码,并且根本不清楚您希望代码执行什么操作。但是值得注意的是,Unix