我有这个问题,我无法弄清楚如何解决它。我有这个字符串:
data = '\xc4\xb7\x86\x17\xcd'
当我尝试编码时:
data.encode()
我得到了这个结果:
b'\xc3\x84\xc2\xb7\xc2\x86\x17\xc3\x8d'
我只想要:
b'\xc4\xb7\x86\x17\xcd'
任何人都知道原因以及如何解决这个问题。该字符串已存储在变量中,因此我无法在其前面添加文字b。
答案 0 :(得分:8)
如果没有考虑编码,则无法将字符串转换为字节或字节为字符串。关于bytes
类型的整点是与编码无关的字节序列,而str
是Unicode code points的序列,其中按设计没有唯一的字节表示
因此,当您想要将一个转换为另一个时,必须明确 要使用哪种编码来执行此转换。转换为字节时,您必须说明如何将每个字符表示为字节序列;当你从字节转换时,你必须说出用什么方法将这些字节映射成字符。
如果你没有指定编码,那么UTF-8是默认值,这是一个理智的默认值,因为UTF-8无处不在,但它也只是一个许多有效的编码。
如果您使用原始字符串'\xc4\xb7\x86\x17\xcd'
,请查看这些字符代表的Unicode代码点。 \xc4
例如LATIN CAPITAL LETTER A WITH DIAERESIS
,即Ä
。该字符碰巧以UTF-8编码为0xC3 0x84
,这解释了为什么这是你将其编码为字节时得到的。但它的UTF-16编码也为0x00C4
。
至于如何正确解决 以便获得所需的输出,没有明确的正确答案。 Kasramvd提到的解决方案也有些不完美。如果您阅读了raw_unicode_escape
编解码器in the documentation:
raw_unicode_escape
其他代码点使用
\uXXXX
和\UXXXXXXXX
进行Latin-1编码。现有的反斜杠不会以任何方式转义。它用于Python pickle协议。
所以这只是一个Latin-1 encoding,它有一个内置的回退字符。我认为这种后备对你的目的有些害。对于无法表示为\xXX
序列的Unicode字符,这可能会有问题:
>>> chr(256).encode('raw_unicode_escape')
b'\\u0100'
因此,代码点256 显式位于Latin-1的之外,导致raw_unicode_escape
编码返回字符串'\\u0100'
的编码字节,从而转换为一个字符到6个字节,与原始字符几乎没有关系(因为它是一个转义序列)。
所以如果你想在这里使用Latin-1,我建议你明确地使用它,而不要让raw_unicode_escape
的转义序列回退。当尝试将代码点转换为Latin-1区域之外时,这只会导致异常:
>>> '\xc4\xb7\x86\x17\xcd'.encode('latin1')
b'\xc4\xb7\x86\x17\xcd'
>>> chr(256).encode('latin1')
Traceback (most recent call last):
File "<pyshell#28>", line 1, in <module>
chr(256).encode('latin1')
UnicodeEncodeError: 'latin-1' codec can't encode character '\u0100' in position 0: ordinal not in range(256)
当然,Latin-1区域之外的代码点是否会导致问题取决于该字符串的实际来源。但是如果你能保证输入只包含有效的Latin-1字符,那么你很可能不需要首先使用字符串。由于您实际上正在处理某种字节,因此您应该首先查看是否不能简单地将这些值作为字节检索。这样你就不会引入两个级别的编码,你可以通过误解输入来破坏数据。
答案 1 :(得分:2)
您可以使用'raw_unicode_escape'
作为编码:
In [14]: bytes(data, 'raw_unicode_escape')
Out[14]: b'\xc4\xb7\x86\x17\xcd'
如评论中所述,您还可以将编码直接传递给字符串的encode
方法。
In [15]: data.encode("raw_unicode_escape")
Out[15]: b'\xc4\xb7\x86\x17\xcd'