online convertir convert bytes python string python-3.x

python - online - Convertir bytes a una cadena?



python decode (16)

Creo que esta manera es fácil:

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

Estoy usando este código para obtener una salida estándar de un programa externo:

>>> from subprocess import * >>> command_stdout = Popen([''ls'', ''-l''], stdout=PIPE).communicate()[0]

El método comunicar () devuelve una matriz de bytes:

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

Sin embargo, me gustaría trabajar con la salida como una cadena de Python normal. 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

Pensé que para eso es el método binascii.b2a_qp() , pero cuando lo probé, obtuve la misma matriz de bytes nuevamente:

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

¿Alguien sabe cómo convertir el valor de los bytes de nuevo a la cadena? Quiero decir, usar las "baterías" en lugar de hacerlo manualmente. Y me gustaría que estuviera bien con Python 3.


Creo que lo que realmente quieres es 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 QUÉ codificación usar. 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 SÍ sea importante es la razón por la que Python se movió para usar dos tipos diferentes para datos binarios y de texto: ¡no se puede convertir mágicamente entre ellos porque no conoce la codificación a menos que se lo digas! La única forma que USTED sabría es leer la documentación de Windows (o leerla aquí).


Cuando trabajo con datos de sistemas Windows (con /r/n finales de línea), mi respuesta es

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

¿Por qué? Intente esto con un Input.txt multilínea:

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

Todas sus terminaciones de línea se duplicarán (a /r/r/n ), lo que dará lugar a líneas vacías adicionales. Las funciones de lectura de texto de Python normalmente normalizan los finales de línea para que las cadenas solo usen /n . Si recibe datos binarios de un sistema Windows, Python no tiene la oportunidad de hacerlo. Así,

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

replicará su archivo original.


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

Para escribir o leer datos binarios de / a las secuencias estándar, use el búfer binario subyacente. Por ejemplo, para escribir bytes en stdout, use sys.stdout.buffer.write (b''abc '').


Debe decodificar la cadena de bytes y convertirla en una cadena de caracteres (Unicode).

b''hello''.decode(encoding)

o

str(b''hello'', encoding)


Establecer universal_newlines en True, es decir

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


Hice una función para limpiar una lista

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


Necesitas decodificar el objeto bytes para producir una cadena:

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


Para Python 3, este es un enfoque mucho más seguro y Pythonic para convertir de byte a 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'')

Salida:

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


Para interpretar una secuencia de bytes como un texto, debe conocer la codificación de caracteres correspondiente:

unicode_text = bytestring.decode(character_encoding)

Ejemplo:

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

ls comando ls puede producir una salida que no se puede interpretar como texto. Los nombres de archivos en Unix pueden ser cualquier secuencia de bytes excepto la barra diagonal b''/'' y cero b''/0'' :

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

Intentar descodificar dicha sopa de bytes con la codificación utf-8 genera UnicodeDecodeError .

Puede ser peor La decodificación puede fallar de forma silenciosa y producir un mojibake si utiliza una codificación incompatible incorrecta:

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

Los datos están dañados, pero su programa sigue sin saber que se ha producido un error.

En general, la codificación de caracteres que se debe utilizar no está incorporada en la secuencia de bytes en sí. Tienes que comunicar esta información fuera de banda. Algunos resultados son más probables que otros y, por chardet tanto, existe un módulo chardet que puede adivinar la codificación de caracteres. Un solo script de Python puede usar múltiples codificaciones de caracteres en diferentes lugares.

ls salida de ls se puede convertir en una cadena Python usando la función os.fsdecode() que tiene éxito incluso para nombres de archivo no sys.getfilesystemencoding() usa sys.getfilesystemencoding() y el controlador de errores surrogateescape en Unix):

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

Para obtener los bytes originales, puede usar os.fsencode() .

Si pasa universal_newlines=True parámetro universal_newlines=True , el subprocess usa locale.getpreferredencoding(False) para decodificar bytes, por ejemplo, puede ser cp1252 en Windows.

Para decodificar el flujo de bytes sobre la marcha, se puede usar io.TextIOWrapper() : example .

Diferentes comandos pueden usar diferentes codificaciones de caracteres para su salida, por ejemplo, dir comando interno ( cmd ) puede usar cp437. Para decodificar su salida, podría pasar la codificación explícitamente (Python 3.6+):

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

Los nombres de archivo pueden diferir de os.listdir() (que usa la API Unicode de Windows), por ejemplo, ''/xb6'' puede sustituirse por ''/x14'' : el códec cp437 de Python asigna b''/x14'' para controlar el carácter U + 0014 en lugar de U + 00B6 (¶). Para admitir nombres de archivos con caracteres Unicode arbitrarios, vea Descodificar la salida de poweshell que posiblemente contenga caracteres Unicode que no sean ascii en una cadena de python


Si bien la respuesta de @Aaron Maenpaa simplemente funciona, un usuario preguntó recientemente

¿Hay alguna manera más simple? ''fhand.read (). decode ("ASCII")'' [...] ¡Es tan largo!

Puedes usar

command_stdout.decode()

decode() tiene un argumento estándar

codecs.decode(obj, encoding=''utf-8'', errors=''strict'')


Si no conoce la codificación, para leer la entrada binaria en la cadena de Python 3 y Python 2, use la antigua codificación cp437 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''))

Debido a que la codificación es desconocida, 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 byte único y UTF-8).

La descodificación de entradas binarias arbitrarias en UTF-8 no es segura, ya que 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 fue popular (¿predeterminado?) Para Python 2. Vea los puntos que faltan en el diseño de la página de códigos : es donde Python se ahoga con ordinal not in range infames que ordinal not in range .

ACTUALIZACIÓN 20150604 : hay rumores de que Python 3 tiene una estrategia de error de surrogateescape para la codificación de cosas en datos binarios sin pérdida de datos y fallas, pero necesita pruebas de conversión [binary] -> [str] -> [binary] para validar el rendimiento y la confiabilidad.

ACTUALIZACIÓN 20170116 : Gracias al comentario de Nearoo, también existe la posibilidad de eliminar de forma brusca todos los bytes desconocidos con el controlador de errores backslashreplace . Eso solo funciona para Python 3, por lo que incluso con esta solución, aún obtendrás 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''))

Consulte https://docs.python.org/3/howto/unicode.html#python-s-unicode-support para obtener más información.

ACTUALIZACIÓN 20170119 : Decidí implementar una decodificación de barra diagonal que funcione tanto para Python 2 como para Python 3. Debería ser más lenta que la solución cp437 , 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''))


Si obtienes lo siguiente intentando decode() :

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

También puede especificar el tipo de codificación directamente en una conversión:

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


Ya que esta pregunta es realmente acerca de la salida de subprocess , tiene un enfoque más directo disponible ya que Popen acepta una palabra clave de encoding (en 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

La respuesta general para otros usuarios es decodificar bytes a texto:

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

Sin argumento, se sys.getdefaultencoding() . Si sus datos no son sys.getdefaultencoding() , debe especificar la codificación explícitamente en la llamada de decode :

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


En Python 3 , la 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 Python 2 , la codificación predeterminada es la codificación de cadena predeterminada. Por lo tanto, debe utilizar:

b''hello''.decode(encoding)

donde la encoding es la codificación que desea.

Nota: el soporte para argumentos de palabras clave se agregó en Python 2.7.


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