Tom*_*vic 1968 python string python-3.x
我正在使用此代码从外部程序获取标准输出:
>>> from subprocess import *
>>> command_stdout = Popen(['ls', '-l'], stdout=PIPE).communicate()[0]
Run Code Online (Sandbox Code Playgroud)
communic()方法返回一个字节数组:
>>> 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'
Run Code Online (Sandbox Code Playgroud)
但是,我想将输出作为普通的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
Run Code Online (Sandbox Code Playgroud)
我认为这是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'
Run Code Online (Sandbox Code Playgroud)
有人知道如何将字节值转换回字符串吗?我的意思是,使用"电池"而不是手动操作.而且我希望它能用于Python 3.
Aar*_*paa 3195
您需要解码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'
Run Code Online (Sandbox Code Playgroud)
dF.*_*dF. 182
您需要解码字节字符串并将其转换为字符(unicode)字符串.
encoding = 'utf-8'
'hello'.decode(encoding)
Run Code Online (Sandbox Code Playgroud)
或者在Python 3上
unicode('hello', encoding)
Run Code Online (Sandbox Code Playgroud)
Sis*_*sso 164
我觉得这很简单:
bytes_data = [112, 52, 52]
"".join(map(chr, bytes_data))
>> p44
Run Code Online (Sandbox Code Playgroud)
ana*_*nik 80
如果您不知道编码,那么要以Python 3和Python 2兼容的方式将二进制输入读入字符串,请使用古老的MS-DOS cp437编码:
PY3K = sys.version_info >= (3, 0)
lines = []
for line in stream:
if not PY3K:
lines.append(line)
else:
lines.append(line.decode('cp437'))
Run Code Online (Sandbox Code Playgroud)
因为编码是未知的,所以期望非英语符号转换为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
Run Code Online (Sandbox Code Playgroud)
这同样适用latin-1
于Python 2的流行(默认?).请参阅代码页布局中的缺失点- 这是Python窒息臭名昭着的地方ordinal not in range
.
更新20150604:有传言称Python 3具有surrogateescape
将内容编码为二进制数据而没有数据丢失和崩溃的错误策略,但它需要转换测试[binary] -> [str] -> [binary]
来验证性能和可靠性.
更新20170116:感谢Nearoo的评论 - 还有可能使用backslashreplace
错误处理程序来减少所有未知字节的转义.这仅适用于Python 3,因此即使使用此解决方法,您仍将从不同的Python版本获得不一致的输出:
PY3K = sys.version_info >= (3, 0)
lines = []
for line in stream:
if not PY3K:
lines.append(line)
else:
lines.append(line.decode('utf-8', 'backslashreplace'))
Run Code Online (Sandbox Code Playgroud)
有关详细信息,请参阅https://docs.python.org/3/howto/unicode.html#python-s-unicode-support.
更新20170119:我决定实现适用于Python 2和Python 3的斜线转义解码.它应该比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'))
Run Code Online (Sandbox Code Playgroud)
lmi*_*asf 75
在Python 3中,默认编码是"utf-8"
,因此您可以直接使用:
b'hello'.decode()
Run Code Online (Sandbox Code Playgroud)
这相当于
b'hello'.decode(encoding="utf-8")
Run Code Online (Sandbox Code Playgroud)
另一方面,在Python 2中,编码默认为默认字符串编码.因此,你应该使用:
b'hello'.decode(encoding)
Run Code Online (Sandbox Code Playgroud)
encoding
你想要的编码在哪里.
注意: Python 2.7中添加了对关键字参数的支持.
mch*_*erm 38
我想你真正想要的是:
>>> from subprocess import *
>>> command_stdout = Popen(['ls', '-l'], stdout=PIPE).communicate()[0]
>>> command_text = command_stdout.decode(encoding='windows-1252')
Run Code Online (Sandbox Code Playgroud)
Aaron的回答是正确的,除了你需要知道要使用的WHICH编码.我相信Windows使用'windows-1252'.只有你的内容中有一些不寻常的(非ascii)字符才有意义,但它会产生影响.
顺便说一句,事实上它是重要的是Python转向使用两种不同类型的二进制和文本数据:它不能神奇地在它们之间转换,因为除非你告诉它,它不知道编码!您将知道的唯一方法是阅读Windows文档(或在此处阅读).
小智 29
将universal_newlines设置为True,即
command_stdout = Popen(['ls', '-l'], stdout=PIPE, universal_newlines=True).communicate()[0]
Run Code Online (Sandbox Code Playgroud)
Yas*_*r M 21
如果您遇到此错误:
utf-8编解码器无法解码字节0x8a,
那么最好使用以下代码将字节转换为字符串:
bytes = b"abcdefg"
string = bytes.decode("utf-8", "ignore")
Run Code Online (Sandbox Code Playgroud)
Sup*_*mer 20
m=b'This is bytes'
Run Code Online (Sandbox Code Playgroud)
m.decode("utf-8")
Run Code Online (Sandbox Code Playgroud)
或者
m.decode()
Run Code Online (Sandbox Code Playgroud)
import codecs
codecs.decode(m,encoding="utf-8")
Run Code Online (Sandbox Code Playgroud)
或者
import codecs
codecs.decode(m)
Run Code Online (Sandbox Code Playgroud)
str(m,encoding="utf-8")
Run Code Online (Sandbox Code Playgroud)
或者
str(m)[2:-1]
Run Code Online (Sandbox Code Playgroud)
'This is bytes'
Run Code Online (Sandbox Code Playgroud)
ser*_*inc 19
虽然@Aaron Maenpaa的答案正常,但是一位用户最近问道
还有更简单的方法吗?'fhand.read().decode("ASCII")'[...]它太长了!
您可以使用
command_stdout.decode()
Run Code Online (Sandbox Code Playgroud)
decode()
有一个标准的论点
codecs.decode(obj, encoding='utf-8', errors='strict')
Shu*_*pta 17
我们可以使用 解码 bytes 对象以生成字符串bytes.decode(encoding='utf-8', errors='strict')
。有关文档,请参阅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)))
Run Code Online (Sandbox Code Playgroud)
输出:
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)))
Run Code Online (Sandbox Code Playgroud)
注意:在Python 3中,默认编码类型为UTF-8。所以,<byte_string>.decode("utf-8")
也可以写成<byte_string>.decode()
wim*_*wim 15
由于这个问题实际上是在询问subprocess
输出,因此您可以使用更直接的方法,因为它Popen
接受了一个编码关键字(在Python 3.6+中):
>>> 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
Run Code Online (Sandbox Code Playgroud)
其他用户的一般答案是将字节解码为文本:
>>> b'abcde'.decode()
'abcde'
Run Code Online (Sandbox Code Playgroud)
没有参数,sys.getdefaultencoding()
将被使用.如果您的数据不是sys.getdefaultencoding()
,那么您必须在decode
调用中明确指定编码:
>>> b'caf\xe9'.decode('cp1250')
'café'
Run Code Online (Sandbox Code Playgroud)
jfs*_*jfs 14
要将字节序列解释为文本,您必须知道相应的字符编码:
unicode_text = bytestring.decode(character_encoding)
Run Code Online (Sandbox Code Playgroud)
例:
>>> b'\xc2\xb5'.decode('utf-8')
'µ'
Run Code Online (Sandbox Code Playgroud)
ls
命令可能会产生无法解释为文本的输出.Unix上的文件名可以是除斜杠b'/'
和零
之外的任何字节序列b'\0'
:
>>> open(bytes(range(0x100)).translate(None, b'\0/'), 'w').close()
Run Code Online (Sandbox Code Playgroud)
尝试使用utf-8编码解码这样的字节汤UnicodeDecodeError
.
可能会更糟. 如果使用错误的不兼容编码,解码可能会无声地失败并产生mojibake:
>>> '—'.encode('utf-8').decode('cp1252')
'—'
Run Code Online (Sandbox Code Playgroud)
数据已损坏,但您的程序仍未发现故障已发生.
通常,要使用的字符编码不嵌入字节序列本身.您必须在带外传达此信息.某些结果比其他结果更可能,因此chardet
存在可以猜测字符编码的模块.单个Python脚本可能在不同的位置使用多个字符编码.
ls
输出可以使用os.fsdecode()
即使对于不可解码的文件名也成功的函数转换为Python字符串(它在Unix上使用
sys.getfilesystemencoding()
和surrogateescape
错误处理程序):
import os
import subprocess
output = os.fsdecode(subprocess.check_output('ls'))
Run Code Online (Sandbox Code Playgroud)
要获得原始字节,您可以使用os.fsencode()
.
如果您传递universal_newlines=True
参数然后subprocess
用于
locale.getpreferredencoding(False)
解码字节,例如,它可以
cp1252
在Windows上.
要动态解码字节流,
io.TextIOWrapper()
可以使用:example.
不同的命令可以对其输出使用不同的字符编码,例如,dir
内部命令(cmd
)可以使用cp437.要解码其输出,您可以显式传递编码(Python 3.6+):
output = subprocess.check_output('dir', shell=True, encoding='cp437')
Run Code Online (Sandbox Code Playgroud)
文件名可能与os.listdir()
(使用Windows Unicode API)不同,例如,'\xb6'
可以用'\x14'
-Python的cp437编解码器映射b'\x14'
代替控制字符U + 0014而不是U + 00B6().要支持具有任意Unicode字符的文件名,请参阅将 可能包含非ascii unicode字符的powehell输出解码为python字符串
如果您通过尝试获得以下内容decode()
:
decode()
您还可以直接在强制转换中指定编码类型:
>>> my_byte_str
b'Hello World'
>>> str(my_byte_str, 'utf-8')
'Hello World'
Run Code Online (Sandbox Code Playgroud)
我做了一个功能来清理列表
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
Run Code Online (Sandbox Code Playgroud)
对于 Python 3,这是一种更安全和Pythonic 的从 转换byte
为 的方法string
:
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')
Run Code Online (Sandbox Code Playgroud)
输出:
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
Run Code Online (Sandbox Code Playgroud)
当使用Windows系统中的数据(以\r\n
行结尾)时,我的答案是
String = Bytes.decode("utf-8").replace("\r\n", "\n")
Run Code Online (Sandbox Code Playgroud)
为什么?尝试使用多行Input.txt:
Bytes = open("Input.txt", "rb").read()
String = Bytes.decode("utf-8")
open("Output.txt", "w").write(String)
Run Code Online (Sandbox Code Playgroud)
您所有的行尾都将加倍(到\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)
Run Code Online (Sandbox Code Playgroud)
将复制您的原始文件。
小智 5
对于“运行 shell 命令并以文本而不是字节形式获取其输出”的特定subprocess.run
情况,在 Python 3.7 上,您应该使用并传入text=True
(以及capture_output=True
捕获输出)
command_result = subprocess.run(["ls", "-l"], capture_output=True, text=True)
command_result.stdout # is a `str` containing your program's stdout
Run Code Online (Sandbox Code Playgroud)
text
曾经被称为universal_newlines
,并且在 Python 3.7 中被更改(好吧,别名)。如果要支持3.7之前的Python版本,则传入universal_newlines=True
而不是text=True
归档时间: |
|
查看次数: |
2025371 次 |
最近记录: |