如何在Python 3中在字节和字符串之间转换?


77

这是一个Python 101类型的问题,但是当我尝试使用一个似乎将我的字符串输入转换为字节的包时,让我感到困惑。

正如您将在下面看到的,我找到了适合自己的答案,但是我觉得这里值得记录,因为花了我很长时间才发掘出发生了什么事情。它似乎是Python 3的通用名称,因此我没有提到我正在使用的原始程序包。这似乎不是一个错误(只是特定的程序包具有.tostring()明显产生我理解为字符串的方法...)

我的测试程序是这样的:

import mangler                                 # spoof package

stringThing = """
<Doc>
    <Greeting>Hello World</Greeting>
    <Greeting>你好</Greeting>
</Doc>
"""

# print out the input
print('This is the string input:')
print(stringThing)

# now make the string into bytes
bytesThing = mangler.tostring(stringThing)    # pseudo-code again

# now print it out
print('\nThis is the bytes output:')
print(bytesThing)

此代码的输出给出了以下内容:

This is the string input:

<Doc>
    <Greeting>Hello World</Greeting>
    <Greeting>你好</Greeting>
</Doc>


This is the bytes output:
b'\n<Doc>\n    <Greeting>Hello World</Greeting>\n    <Greeting>\xe4\xbd\xa0\xe5\xa5\xbd</Greeting>\n</Doc>\n'

因此,需要能够在字节和字符串之间进行转换,以避免最终将非ascii字符转换为gobbledegook。


1
这个问题在答案中提供了更多详细信息,但是我认为下面的简短答案更加清晰。
Bobble

Answers:


116

上面的代码示例中的“ mangler”正在执行以下操作:

bytesThing = stringThing.encode(encoding='UTF-8')

还有其他方式可以编写此代码(特别是使用bytes(stringThing, encoding='UTF-8'),但是上面的语法可以使正在发生的事情以及恢复字符串的操作变得显而易见:

newStringThing = bytesThing.decode(encoding='UTF-8')

当我们这样做时,将恢复原始字符串。

请注意,str(bytesThing)除非您特别要求使用UTF-8,即,仅使用转录所有gobbledegook,而无需将其转换回Unicode str(bytesThing, encoding='UTF-8')。如果未指定编码,则不会报告错误。


如果你看一下实际的方法实现你会看到utf-8默认的编码方式,因此,你可以省略因为你知道编码的确utf-8,即stringThing.encode()bytesThing.decode()会做得很好。
ccpizza

@ccpizza在上面的示例中使编码明确可见,使事情变得更加清晰,恕我直言是一种好习惯。并非所有的unicode都是UTF-8。它还避免了上一段中提到的静默故障。
Bobble

完全同意; 显式比隐式好,但是imo最好知道什么隐式。是否使用它是另一个问题。仅仅因为您不能意味着您应该:)
ccpizza

在Python 3中,decode('utf-8', 'backslashreplace')如果编码未知,可以使用它来避免异常。一个人不应该总是假定UTF-8!
Nagev

15

在python3中,有一种bytes()格式与相同的方法encode()

str1 = b'hello world'
str2 = bytes("hello world", encoding="UTF-8")
print(str1 == str2) # Returns True

我没有在文档中阅读有关此内容的任何内容,但也许我没有找到正确的位置。这样,您可以将字符串显式地转换为字节流,并且比使用encode和更具可读性decode,而不必b在引号前进行预表达。


3

这是一个Python 101类型的问题,

这是一个简单的问题,但答案不是那么简单。


在python3中,“字节”对象代表字节序列,“字符串”对象代表Unicode代码点序列。

要在“字节”和“字符串”之间以及“字符串”和“字节”之间进行转换,可以使用bytes.encode和string.decode函数。这些函数采用两个参数,即编码和错误处理策略。

可悲的是,在很多情况下,字节序列用于表示文本,但是不一定要明确定义所使用的编码。以类Unix系统上的文件名为例,就内核而言,它们是一个字节序列,带有一些特殊值,在大多数现代发行版中,大多数文件名都是UTF-8,但没有保证所有文件名都会是。

如果要编写功能强大的软件,则需要仔细考虑这些参数。您需要仔细考虑字节应该采用的编码方式,以及如何处理原来认为不是编码形式的有效字节序列的情况。Python默认为UTF-8并在任何无效UTF-8的字节序列上出错。

打印(bytesThing)

Python使用“ repr”作为对字符串的后备转换。repr尝试生成将重新创建对象的python代码。对于字节对象,这意味着要转义可打印ascii范围之外的字节。


2

尝试这个:

StringVariable=ByteVariable.decode('UTF-8','ignore')

测试类型:

print(type(StringVariable))

这里的“ StringVariable”表示为字符串。“ ByteVariable”表示为字节。询问变量不是无关紧要的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.