我将外部程序的标准输出捕获到一个字节对象中:

>>> from subprocess import *
>>> command_stdout = Popen(['ls', '-l'], stdout=PIPE).communicate()[0]
>>>
>>> command_stdout
b'total 0\n-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file1\n-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file2\n'

我想把它转换成一个普通的Python字符串,这样我就可以这样打印了:

>>> print(command_stdout)
-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file1
-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file2

如何使用Python 3将字节对象转换为str?


当前回答

如果出现此错误:

utf-8编解码器无法解码字节0x8a,

那么最好使用以下代码将字节转换为字符串:

bytes = b"abcdefg"
string = bytes.decode("utf-8", "ignore") 

其他回答

由于这个问题实际上是关于子流程输出的,所以您可以使用更直接的方法。最现代的方法是使用subprocess.check_output并传递text=True(Python 3.7+),使用系统默认编码自动解码stdout:

text = subprocess.check_output(["ls", "-l"], text=True)

对于Python 3.6,Popen接受一个编码关键字:

>>> from subprocess import Popen, PIPE
>>> text = Popen(['ls', '-l'], stdout=PIPE, encoding='utf-8').communicate()[0]
>>> type(text)
str
>>> print(text)
total 0
-rw-r--r-- 1 wim badger 0 May 31 12:45 some_file.txt

如果您不处理子流程输出,标题中问题的一般答案是将字节解码为文本:

>>> b'abcde'.decode()
'abcde'

如果没有参数,将使用sys.getdefaultencoding()。如果数据不是sys.getdefaultencoding(),则必须在decode调用中显式指定编码:

>>> b'caf\xe9'.decode('cp1250')
'café'

使用Windows系统中的数据(以行结尾)时,我的答案是

String = Bytes.decode("utf-8").replace("\r\n", "\n")

为什么?尝试使用多行Input.txt:

Bytes = open("Input.txt", "rb").read()
String = Bytes.decode("utf-8")
open("Output.txt", "w").write(String)

所有的行尾都将加倍(到\r\n),导致多余的空行。Python的文本读取函数通常规范化行结尾,以便字符串只使用\n。如果您从Windows系统接收二进制数据,Python就没有机会这样做。因此

Bytes = open("Input.txt", "rb").read()
String = Bytes.decode("utf-8").replace("\r\n", "\n")
open("Output.txt", "w").write(String)

将复制原始文件。

我们可以使用bytes.decode(encoding='utf-8',errors='strict')对bytes对象进行解码以生成字符串。有关文档,请参阅bytes.decode。

Python 3示例:

byte_value = b"abcde"
print("Initial value = {}".format(byte_value))
print("Initial value type = {}".format(type(byte_value)))
string_value = byte_value.decode("utf-8")
# utf-8 is used here because it is a very common encoding, but you need to use the encoding your data is actually in.
print("------------")
print("Converted value = {}".format(string_value))
print("Converted value type = {}".format(type(string_value)))

输出:

Initial value = b'abcde'
Initial value type = <class 'bytes'>
------------
Converted value = abcde
Converted value type = <class 'str'>

注意:在Python 3中,默认情况下编码类型为UTF-8。因此,<byte_string>.decode(“utf-8”)也可以写成<byte-string>.decode()

如果要转换任何字节,而不仅仅是转换为字节的字符串:

with open("bytesfile", "rb") as infile:
    str = base64.b85encode(imageFile.read())

with open("bytesfile", "rb") as infile:
    str2 = json.dumps(list(infile.read()))

然而,这并不是很有效。它会将2 MB的图片转换为9 MB。

在Python 3中,默认编码为“utf-8”,因此可以直接使用:

b'hello'.decode()

相当于

b'hello'.decode(encoding="utf-8")

另一方面,在Python 2中,编码默认为默认字符串编码。因此,您应该使用:

b'hello'.decode(encoding)

其中编码是所需的编码。

注意:Python 2.7中添加了对关键字参数的支持。