2012-03-07 21 views
10

Estoy tratando de convertir una cadena de bytes entrantes que contiene caracteres no ascii en una cadena utf-8 válida, de modo que pueda volcar como json.cadena de bytes python codificar y decodificar

b = '\x80' 
u8 = b.encode('utf-8') 
j = json.dumps(u8) 

que esperaba j sea '\ xc2 \ x80' pero en cambio me sale:

UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0: ordinal not in range(128) 

En mi situación, 'b' viene de MySQL a través de Google búferes de protocolo y se rellena con algunos datos de blobs.

¿Alguna idea?

EDIT: Tengo marcos de ethernet que están almacenados en una tabla mysql como blob (por favor, todos, quédense en el tema y eviten discutir por qué hay paquetes en una tabla). La intercalación de tablas es utf-8 y la capa db (sqlalchemy, non-orm) está tomando los datos y creando estructuras (búferes de protocolo de Google) que almacenan el blob como un 'str' de python. En algunos casos, uso los búferes de protocolo directamente sin ningún problema. En otros casos, necesito exponer los mismos datos a través de json. Lo que noté es que cuando json.dumps() hace lo suyo, '\ x80' puede reemplazarse con el carácter no gráfico no válido (\ ufffd iirc)

+0

Necesita dar un fragmento de código que muestre lo que significa "usar los búferes de protocolo directamente sin ningún problema". Necesita mostrar con un fragmento de código lo que hace con el búfer de protocolo para hacer que 'json.dumps' produzca \ ufffd. Necesita decir exactamente qué se espera que haga el consumidor de este paquete JSONised para recuperar el paquete original. –

Respuesta

6

Use b.decode('name of source encoding') para obtener una versión Unicode. Esto fue sorprendente para mí cuando lo aprendí. por ejemplo:

In [123]: 'foo'.decode('latin-1') 
Out[123]: u'foo' 
+9

Recuerde: 'decode' va de bytes a unicode. 'encode' va de unicode a bytes. –

+0

@DanielRoseman Sí, es por eso que esta es una respuesta a la pregunta. – Marcin

+0

Claro, no estaba discutiendo, simplemente brindando una explicación adicional para el PO. –

9

Necesita examinar la documentación de la API de software que está utilizando. BLOB es un acrónimo: BINARY Large Object.

Si sus datos son de hecho binarios, la idea de decodificarlos en Unicode es por supuesto una tontería.

Si de hecho es texto, necesita saber qué codificación usar para decodificarlo en Unicode.

continuación, utiliza json.dumps(a_Python_object) ... si codifica a UTF-8 a sí mismo, json decodificará nuevo otra vez:

>>> import json 
>>> json.dumps(u"\u0100\u0404") 
'"\\u0100\\u0404"' 
>>> json.dumps(u"\u0100\u0404".encode('utf8')) 
'"\\u0100\\u0404"' 
>>> 

Actualizar la información de latin1:

u'\x80' es un control C1 sentido inútil carácter: la codificación es extremadamente improbable que sea Latin-1. Latin-1 es "una trampa y una ilusión": todos los bytes de 8 bits se decodifican en Unicode sin generar una excepción. No confunda "trabajos" y "no genera una excepción".

+0

interesante. Supongo que puedo mantenerlo simple: print json.dumps ('\ x80'.decode (' latin1 ')) –

+1

@ kung-foo: No hay evidencia de que' latin1' sea la codificación correcta. –

+0

Entonces, ¿cuál es el método para codificar una cadena de bytes en utf-8? –

2

Creo que lo que estás tratando de hacer es decodificar el objeto de cadena de alguna codificación. ¿Sabes qué es esa codificación? Para obtener el objeto Unicode.

unicode_b = b.decode('some_encoding') 

y luego volver a codificar el objeto Unicode utilizando la codificación utf_8 de nuevo a un objeto de cadena.

b = unicode_b.encode('utf_8') 

Utilizando el objeto Unicode como traductor, sin saber cuál es la codificación original de la serie es que no puedo saber con certeza, pero existe la posibilidad de que la conversión no irá como se esperaba. El objeto Unicode no está destinado a convertir cadenas de una codificación a otra.Trabajaría con el objeto Unicode suponiendo que sabes cuál es la codificación, si no sabes cuál es la codificación, entonces realmente no hay forma de averiguarlo sin prueba y error, y luego vuelve a convertir a la cadena codificada cuando quieres un objeto de cadena de vuelta.

Cuestiones relacionadas