tobytes - python字节比较




将字节转换为字符串? (10)

我正在使用此代码从外部程序获取标准输出:

>>> 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

我认为这就是binascii.b2a_qp()方法的binascii.b2a_qp() ,但是当我尝试它时,我又得到了相同的字节数组:

>>> binascii.b2a_qp(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 3一致。


http://docs.python.org/3/library/sys.html

要向标准流写入或读取二进制数据,请使用基础二进制缓冲区。 例如,要将字节写入标准输出,请使用sys.stdout.buffer.write(b'abc')。


你需要解码bytes对象来产生一个字符串:

>>> b"abcde"
b'abcde'

# utf-8 is used here because it is a very common encoding, but you
# need to use the encoding your data is actually in.
>>> b"abcde".decode("utf-8") 
'abcde'

在处理来自Windows系统的数据时(使用\r\n行尾),我的答案是

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\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)

将复制您的原始文件。


如果你应该通过尝试decode()来获得以下内容:

AttributeError: 'str' object has no attribute 'decode'

您还可以在演员中直接指定编码类型:

>>> my_byte_str
b'Hello World'

>>> str(my_byte_str, 'utf-8')
'Hello World'

对于Python 3,这是一个更安全的Pythonic方法来从byte转换为string

def byte_to_str(bytes_or_str):
    if isinstance(bytes_or_str, bytes): #check if its in bytes
        print(bytes_or_str.decode('utf-8'))
    else:
        print("Object not of byte type")

byte_to_str(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')

输出:

total 0
-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file1
-rw-rw-r-- 1 thomas thomas 0 Mar  3 07:03 file2

将universal_newlines设置为True,即

command_stdout = Popen(['ls', '-l'], stdout=PIPE, universal_newlines=True).communicate()[0]

您需要解码字节字符串并将其转换为字符(unicode)字符串。

b'hello'.decode(encoding)

要么

str(b'hello', encoding)

我做了一个清理列表的函数

def cleanLists(self, lista):
    lista = [x.strip() for x in lista]
    lista = [x.replace('\n', '') for x in lista]
    lista = [x.replace('\b', '') for x in lista]
    lista = [x.encode('utf8') for x in lista]
    lista = [x.decode('utf8') for x in lista]

    return lista

我认为这种方式很简单:

bytes = [112, 52, 52]
"".join(map(chr, bytes))
>> p44

要将字节序列解释为文本,您必须知道相应的字符编码:

unicode_text = bytestring.decode(character_encoding)

例:

>>> b'\xc2\xb5'.decode('utf-8')
'µ'

ls命令可能会产生不能被解释为文本的输出。 Unix上的文件名可以是除斜杠b'/'和零b'\0'外的任何字节序列:

>>> open(bytes(range(0x100)).translate(None, b'\0/'), 'w').close()

尝试使用utf-8编码解码这种字节汤会引发UnicodeDecodeError

它可能会更糟。 如果您使用错误的不兼容编码,解码可能会失败并产生mojibake

>>> '—'.encode('utf-8').decode('cp1252')
'—'

数据已损坏,但您的程序仍不知道发生了故障。

通常,使用什么字符编码并不嵌入字节序列本身。 您必须在带外传达此信息。 一些结果比其他结果更可能存在,因此chardet模块存在,可以猜测字符编码。 一个Python脚本可能在不同的地方使用多个字符编码。

使用os.fsdecode()函数可以将ls输出转换为Python字符串,即使对于不可解码的文件名也是如此 (它在Unix上使用sys.getfilesystemencoding()surrogateescape错误处理程序):

import os
import subprocess

output = os.fsdecode(subprocess.check_output('ls'))

要获得原始字节,可以使用os.fsencode()

如果您传递了universal_newlines=True参数,则subprocess locale.getpreferredencoding(False)使用locale.getpreferredencoding(False)来解码字节,例如,它可以是Windows上的cp1252

要实时解码字节流,可以使用io.TextIOWrapper() : example 。

不同的命令可能会为其输出使用不同的字符编码,例如, dir内部命令( cmd )可能使用cp437。 要解码它的输出,你可以显式地传递编码(Python 3.6+):

output = subprocess.check_output('dir', shell=True, encoding='cp437')

文件名可能与os.listdir() (它使用Windows Unicode API)不同,例如, '\xb6'可以用'\x14'替代--Python的cp437编解码器映射b'\x14'来控制字符U + 0014而不是U + 00B6(¶)。 要支持具有任意Unicode字符的文件名,请参阅将可能包含非ASCII字符 Unicode字符的poweshell输出解码为python字符串







python-3.x