当bytes对象显然只包含字符时,将Python 3字节对象转换为字符串

时间:2017-01-04 22:18:25

标签: python string python-3.x character-encoding

我是Python 3的新手,似乎我无法完全掌握unicode和字符编码。

我正在处理另一个工具的输出,该工具将html页面的内容作为字节对象返回。我们使用的其他工具需要此输出为字节类型,但是,我希望将字节输出转换为字符串,以便进行一些解析并与其他字符串进行比较。对于我感兴趣的情况,打印输出字节对象仅显示字符,而不显示\ x或\ u二进制。我对如何最好地做到这一点以及为什么创建所需输出的方法实际上起作用感到有些困惑。

我在别处读到过.decode()应该在这个上下文中使用,这确实有用,但我不明白为什么我要解码一个已经是字符的对象。据我所知,解码用于二进制数,例如:

>>> b'\x41'.decode('utf-8')
'A'

在我的理解中,我真正想做的就是告诉Python一个被标记为字节类型对象的对象实际上是一个str对象。简单地在bytes对象上使用str()函数也可以实现这个目标,但是添加了" b"在字符串周围添加前缀并添加引号。

以下是我与之合作的两个解决方案:

>>> str(b'htmltext')
"b'htmltext'"

>>> b'htmltext'.decode('utf-8')
'htmltext'

基本上,这些解决方案中的任何一个似乎都能实现我所寻求的目标,但解码()显然看起来更清晰,而且从我所读过的,推荐的方法。我想知道为什么decode()有效,因为显然,我没有将二进制数转换为字符。此外,除了没有吸引力的" b"和输出中的引号str()在这里不是一个有效的解决方案?

1 个答案:

答案 0 :(得分:4)

不要将bytes对象的开发人员友好型表示与其中包含的数据混淆。无论哪种方式都有二进制数据。

通过开发人员表示,您可以通过显示发生的任何内容作为ASCII字符的有效ASCII代码点而不是\xhh转义码来轻松查看所包含的内容。通过这种方式读取以ASCII编码的文本更容易,并且许多世界的文本恰好是ASCII编码的。

但是,当数据不在ASCII范围内时,您会遇到更难的时间:

>>> 'Åæøéï'.encode('utf8')
b'\xc3\x85\xc3\xa6\xc3\xb8\xc3\xa9\xc3\xaf'

这是一个UTF-8字节序列,用于编码带重音的文本。以上可能有点人为,但大多数非英文文本将包括一些非ASCII文本。即使是英文文本也可以包含em-dashes或花哨的引号,而b'...'字节版本的文本几乎不像正确解码的文本版本那样可读:

>>> '“Kragerø” is a town in Norway – in the province of Vestfold'.encode('utf8')
b'\xe2\x80\x9cKrager\xc3\xb8\xe2\x80\x9d is a town in Norway \xe2\x80\x93 in the province of Vestfold'

请注意,b'....'输出是在bytes对象上使用repr() function的结果;调用object.__repr__() method,它具有为您生成开发人员友好字符串的显式功能。 bytes对象上没有专用的object.__str__() method,即使您使用__repr__函数,也会调用str()方法。将bytes 转换为字符串的正确方法是解码(使用正确的数据编解码器)。

当然,如果您有表示其他的二进制数据,例如图像数据,则将其保留为bytes。那里没有要解码的文字。