Tomás Sedovic
Capturé la salida estándar de un programa externo en un bytes
objeto:
>>> 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'
Quiero convertir eso en una cadena normal de Python, para poder imprimirlo así:
>>> 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
¿Cómo convierto el bytes
objetar a un str
con pitón 3?
Consulte ¿La mejor manera de convertir cadenas en bytes en Python 3? por lo contrario.
Aarón Maenpaa
Decodificar el bytes
objeto para producir una cadena:
>>> b"abcde".decode("utf-8")
'abcde'
El ejemplo anterior asume que el bytes
El objeto está en UTF-8, porque es una codificación común. Sin embargo, ¡debe usar la codificación en la que están realmente sus datos!
-
Sí, pero dado que este es el resultado de un comando de Windows, ¿no debería usar “.decode(‘windows-1252’)” en su lugar?
– mcherm
18 de julio de 2011 a las 19:48
-
Usando
"windows-1252"
tampoco es confiable (por ejemplo, para otras versiones de idioma de Windows), ¿no sería mejor usarsys.stdout.encoding
?– Niko
3 de enero de 2012 a las 15:20
-
Tal vez esto ayude a alguien más: a veces usa una matriz de bytes para la comunicación ex TCP. Si desea convertir una matriz de bytes en una cadena que corta los caracteres finales ‘\ x00′, la siguiente respuesta no es suficiente. Use b’example\x00\x00’.decode(‘utf-8’).strip(‘\x00’) entonces.
– Wookie88
16 de abril de 2013 a las 13:27
-
Documentación oficial para esto: para todos
bytes
ybytearray
operaciones (métodos que se pueden llamar en estos objetos), ver aquí: docs.python.org/3/library/stdtypes.html#bytes-methods. Parabytes.decode()
en particular, ver aquí: docs.python.org/3/library/stdtypes.html#bytes.decode.– Gabriel grapas
25 de marzo de 2021 a las 4:12
dF.
Decodifique la cadena de bytes y conviértala en una cadena de caracteres (Unicode).
Pitón 3:
encoding = 'utf-8'
b'hello'.decode(encoding)
o
str(b'hello', encoding)
Pitón 2:
encoding = 'utf-8'
'hello'.decode(encoding)
o
unicode('hello', encoding)
Sisso
Esto une una lista de bytes en una cadena:
>>> bytes_data = [112, 52, 52]
>>> "".join(map(chr, bytes_data))
'p44'
-
@leetNightshade: sin embargo, es terriblemente ineficiente. Si tiene una matriz de bytes, solo necesita decodificar.
– Martijn Pieters
♦1 de septiembre de 2014 a las 16:25
-
@Sasszem: este método es una forma pervertida de expresar:
a.decode('latin-1')
dóndea = bytearray([112, 52, 52])
(“No existe tal cosa como texto sin formato”. Si logró convertir bytes en una cadena de texto, entonces usó alguna codificación:latin-1
en este caso)– jfs
16 de noviembre de 2016 a las 3:16
-
@leetNightshade: En aras de la exhaustividad:
bytes(list_of_integers).decode('ascii')
es aproximadamente 1/3 más rápido que''.join(map(chr, list_of_integers))
en Phyton 3.6.– Martijn Pieters
♦3 de julio de 2018 a las 12:01
anatoly techtonik
Si no conoce la codificación, entonces para leer la entrada binaria en una cadena en una forma compatible con Python 3 y Python 2, use el antiguo MS-DOS CP437 codificación:
PY3K = sys.version_info >= (3, 0)
lines = []
for line in stream:
if not PY3K:
lines.append(line)
else:
lines.append(line.decode('cp437'))
Debido a que se desconoce la codificación, espere que los símbolos que no están en inglés se traduzcan a caracteres de cp437
(Los caracteres en inglés no se traducen porque coinciden en la mayoría de las codificaciones de un solo byte y UTF-8).
La decodificación de una entrada binaria arbitraria a UTF-8 no es segura, porque puede obtener esto:
>>> 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
Lo mismo se aplica a latin-1
que era popular (¿el predeterminado?) para Python 2. Vea los puntos que faltan en Diseño de página de códigos – es donde Python se ahoga con infame ordinal not in range
.
ACTUALIZACIÓN 20150604: Hay rumores de que Python 3 tiene la surrogateescape
estrategia de error para codificar cosas en datos binarios sin pérdida de datos y fallas, pero necesita pruebas de conversión, [binary] -> [str] -> [binary]
para validar tanto el rendimiento como la fiabilidad.
ACTUALIZACIÓN 20170116: Gracias al comentario de Nearoo: también existe la posibilidad de recortar todos los bytes desconocidos con escape backslashreplace
controlador de errores Eso funciona solo para Python 3, por lo que, incluso con esta solución, seguirá obteniendo resultados inconsistentes de diferentes versiones de 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'))
Ver Compatibilidad con Unicode de Python para detalles.
ACTUALIZACIÓN 20170119: Decidí implementar la decodificación de escape de barra que funciona tanto para Python 2 como para Python 3. Debería ser más lento que el cp437
solución, pero debería producir resultados idénticos en cada versión de 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'))
miguelvargasf
en pitón 3la codificación predeterminada es "utf-8"
por lo que puede usar directamente:
b'hello'.decode()
que es equivalente a
b'hello'.decode(encoding="utf-8")
Por otro lado, en pitón 2, la codificación tiene como valor predeterminado la codificación de cadena predeterminada. Por lo tanto, debe utilizar:
b'hello'.decode(encoding)
dónde encoding
es la codificación que desea.
Nota: Se agregó soporte para argumentos de palabras clave en Python 2.7.
Pedro Mortensen
Creo que realmente quieres esto:
>>> from subprocess import *
>>> command_stdout = Popen(['ls', '-l'], stdout=PIPE).communicate()[0]
>>> command_text = command_stdout.decode(encoding='windows-1252')
La respuesta de Aaron fue correcta, excepto que necesitas saber cual codificación a utilizar. Y creo que Windows usa ‘windows-1252’. Solo importará si tiene algunos caracteres inusuales (no ASCII) en su contenido, pero luego marcará la diferencia.
Por cierto, el hecho de que hace La cuestión es la razón por la que Python pasó a usar dos tipos diferentes para datos binarios y de texto: no puede convertir mágicamente entre ellos, ¡porque no conoce la codificación a menos que usted se lo diga! La única manera de saberlo es leer la documentación de Windows (o leerla aquí).
Dado que esta pregunta en realidad se refiere a subprocess
salida, tiene enfoques más directos disponibles. Lo más moderno sería usar subprocess.check_output
y pasando text=True
(Python 3.7+) para decodificar automáticamente la salida estándar utilizando la codificación predeterminada del sistema:
text = subprocess.check_output(["ls", "-l"], text=True)
Para Python 3.6, Popen
acepta un codificación palabra clave:
>>> 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
La respuesta general a la pregunta del título, si no se trata de la salida de un subproceso, es descodificar bytes a texto:
>>> b'abcde'.decode()
'abcde'
Sin argumento, sys.getdefaultencoding()
se utilizará. Si sus datos no están sys.getdefaultencoding()
entonces debe especificar la codificación explícitamente en el decode
llamar:
>>> b'caf\xe9'.decode('cp1250')
'café'
por qué no
str(text_bytes)
¿trabajar? Esto me parece extraño.–Charlie Parker
14/03/2019 a las 22:25
@CharlieParker Porque
str(text_bytes)
no se puede especificar la codificación. Dependiendo de lo que haya en text_bytes,text_bytes.decode('cp1250
)` podría resultar en una cadena muy diferente atext_bytes.decode('utf-8')
.–Craig Anderson
31 de marzo de 2019 a las 17:32
entonces
str
la función ya no se convierte en una cadena real. Uno TIENE que decir una codificación explícitamente por alguna razón, soy demasiado perezoso para leer por qué. Solo conviértelo autf-8
y ver si su código funciona. p.ejvar = var.decode('utf-8')
–Charlie Parker
22 de abril de 2019 a las 23:32
@CraigAnderson:
unicode_text = str(bytestring, character_encoding)
funciona como se esperaba en Python 3. Aunqueunicode_text = bytestring.decode(character_encoding)
es preferible evitar confusiones con sólostr(bytes_obj)
que produce una representación de texto parabytes_obj
en lugar de decodificarlo a texto:str(b'\xb6', 'cp1252') == b'\xb6'.decode('cp1252') == '¶'
ystr(b'\xb6') == "b'\\xb6'" == repr(b'\xb6') != '¶'
– jfs
12 de abril de 2020 a las 5:11
Además, puedes pasar
text=True
asubprocess.run()
o.Popen()
y luego obtendrá una cadena de vuelta, sin necesidad de convertir bytes. O especificarencoding="utf-8"
a cualquiera de las dos funciones.–David Gilbertson
13 de septiembre de 2022 a las 5:46