Python 将字节转换为字符串
我使用此代码从外部程序获取标准输出:Python 将字节转换为字符串,python,string,python-3.x,Python,String,Python 3.x,我使用此代码从外部程序获取标准输出: >>> from subprocess import * >>> command_stdout = Popen(['ls', '-l'], stdout=PIPE).communicate()[0] communicate()方法返回字节数组: >>> command_stdout b'total 0\n-rw-rw-r-- 1 thomas thomas 0 Mar 3 07:03 file1\n-
>>> from subprocess import *
>>> command_stdout = Popen(['ls', '-l'], stdout=PIPE).communicate()[0]
communicate()方法返回字节数组:
>>> 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(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'
如何将字节值转换回字符串?我的意思是,使用“电池”而不是手动操作。我希望Python3可以使用。您需要解码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'
您需要解码字节字符串并将其转换为字符(Unicode)字符串 关于Python 2
encoding = 'utf-8'
'hello'.decode(encoding)
或
关于Python 3
encoding = 'utf-8'
b'hello'.decode(encoding)
或
我想你真的想要这个:
>>> from subprocess import *
>>> command_stdout = Popen(['ls', '-l'], stdout=PIPE).communicate()[0]
>>> command_text = command_stdout.decode(encoding='windows-1252')
Aaron的回答是正确的,只是您需要知道使用哪种编码。我相信Windows使用的是“Windows-1252”。只有当你的内容中有一些不寻常的(非ASCII)字符时,这才有意义,但这样做会有所不同
顺便说一句,它确实很重要,这是Python开始使用两种不同类型的二进制和文本数据的原因:它无法在它们之间进行神奇的转换,因为除非您告诉它,否则它不知道编码!您知道的唯一方法是阅读Windows文档(或在此处阅读)。我认为这种方法很简单:
>>> bytes_data = [112, 52, 52]
>>> "".join(map(chr, bytes_data))
'p44'
发件人:
要从标准流写入或读取二进制数据,请使用底层二进制缓冲区。例如,要将字节写入标准输出,请使用
sys.stdout.buffer.write(b'abc')
将universal\u换行符设置为True,即
command_stdout = Popen(['ls', '-l'], stdout=PIPE, universal_newlines=True).communicate()[0]
如果您不知道编码,那么要以Python 3和Python 2兼容的方式将二进制输入读入字符串,请使用古老的MS-DOS编码:
PY3K = sys.version_info >= (3, 0)
lines = []
for line in stream:
if not PY3K:
lines.append(line)
else:
lines.append(line.decode('cp437'))
unicode_text = bytestring.decode(character_encoding)
>>> '—'.encode('utf-8').decode('cp1252')
'—'
由于编码未知,非英语符号应翻译为cp437
(英语字符不翻译,因为它们在大多数单字节编码和UTF-8中匹配)
将任意二进制输入解码到UTF-8是不安全的,因为您可能会遇到以下情况:
>>> b'\x00\x01\xffsd'.decode('utf-8')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 2: invalid
start byte
有关详细信息,请参阅
更新20170119:我决定实现对Python2和Python3都有效的斜杠转义解码。它应该比cp437
解决方案慢,但是它应该在每个Python版本上产生相同的结果
# --- preparation
import codecs
def slashescape(err):
""" codecs error handler. err is UnicodeDecode instance. return
a tuple with a replacement for the unencodable part of the input
and a position where encoding should continue"""
#print err, dir(err), err.start, err.end, err.object[:err.start]
thebyte = err.object[err.start:err.end]
repl = u'\\x'+hex(ord(thebyte))[2:]
return (repl, err.end)
codecs.register_error('slashescape', slashescape)
# --- processing
stream = [b'\x80abc']
lines = []
for line in stream:
lines.append(line.decode('utf-8', 'slashescape'))
在正常工作时,用户:
还有更简单的方法吗?”fhand.read().decode(“ASCII”)“[…]太长了
您可以使用:
command_stdout.decode()
decode()
具有:
codecs.decode(obj,encoding='utf-8',errors='strict')
我做了一个清理列表的函数
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
,默认编码为“utf-8”,因此您可以直接使用:
b'hello'.decode()
这相当于
b'hello'.decode(encoding="utf-8")
另一方面,编码默认为默认的字符串编码。因此,您应该使用:
b'hello'.decode(encoding)
其中encoding
是您想要的编码
Python2.7中添加了对关键字参数的支持。要将字节序列解释为文本,您必须知道 对应字符编码:
PY3K = sys.version_info >= (3, 0)
lines = []
for line in stream:
if not PY3K:
lines.append(line)
else:
lines.append(line.decode('cp437'))
unicode_text = bytestring.decode(character_encoding)
>>> '—'.encode('utf-8').decode('cp1252')
'—'
例如:
>>> b'\xc2\xb5'.decode('utf-8')
'µ'
ls
命令可能会产生无法解释为文本的输出。文件名
在Unix上,可以是除斜杠b'/'
和零之外的任何字节序列
b'\0'
:
>>> open(bytes(range(0x100)).translate(None, b'\0/'), 'w').close()
尝试使用utf-8编码来解码这样的字节汤会引发UnicodeDecodeError
情况可能更糟。解码可能会无声地失败并产生错误
如果使用了错误的不兼容编码:
PY3K = sys.version_info >= (3, 0)
lines = []
for line in stream:
if not PY3K:
lines.append(line)
else:
lines.append(line.decode('cp437'))
unicode_text = bytestring.decode(character_encoding)
>>> '—'.encode('utf-8').decode('cp1252')
'—'
数据已损坏,但您的程序仍不知道发生了故障
已经发生了
通常,要使用的字符编码不会嵌入到字节序列本身中。你必须在带外传达这些信息。某些结果比其他结果更可能出现,因此存在可以猜测字符编码的chardet
模块。单个Python脚本可以在不同的位置使用多个字符编码
ls
可以使用os.fsdecode()
即使在(它使用
上的错误处理程序
Unix):
要获取原始字节,可以使用os.fsencode()
如果传递universal\u newlines=True
参数,则子流程使用
locale.getpreferredencoding(False)
解码字节,例如,它可以
Windows上的cp1252
要动态解码字节流,
可以使用:
不同的命令可能使用不同的字符编码
例如,dir
内部命令(cmd
)的输出可以使用cp437。破译
输出时,可以显式传递编码(Python 3.6+):
文件名可能与使用Windows的os.listdir()不同
Unicode API),例如,'\xb6'
可以用'\x14'
-Python的
cp437编解码器将b'\x14'
映射到控制字符U+0014,而不是
U+00B6(¨)。要支持带有任意Unicode字符的文件名,请参见Python 3的,这是一种更安全的Python方法,可以将
字节
转换为字符串
:
def byte_to_str(bytes_or_str):
if isinstance(bytes_or_str, bytes): # Check if it's 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
如果您应该通过尝试
decode()
获得以下信息:
AttributeError:“str”对象没有属性“decode”
您还可以在强制转换中直接指定编码类型:
>>> my_byte_str
b'Hello World'
>>> str(my_byte_str, 'utf-8')
'Hello World'
当使用Windows系统中的数据时(使用
\r\n
行尾),我的答案是
String = Bytes.decode("utf-8").replace("\r\n", "\n")
为什么??使用multiline 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)
将复制您的原始文件。因为这个问题实际上是在问ab
>>> 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'
>>> b'caf\xe9'.decode('cp1250')
'café'
def toString(string):
try:
return v.decode("utf-8")
except ValueError:
return string
b = b'97.080.500'
s = '97.080.500'
print(toString(b))
print(toString(s))
with open("bytesfile", "rb") as infile:
str = base64.b85encode(imageFile.read())
with open("bytesfile", "rb") as infile:
str2 = json.dumps(list(infile.read()))
command_result = subprocess.run(["ls", "-l"], capture_output=True, text=True)
command_result.stdout # is a `str` containing your program's stdout
bytes.fromhex('c3a9').decode('utf-8')