2011-01-16 11 views
6

Estoy tratando de trabajar con los servicios web HORRIBLE en Commission Junction (CJ). Puedo hacer que el cliente se conecte y reciba información de CJ, pero su base de datos parece incluir un montón de caracteres incorrectos que causan UnicideDecodeError.Cómo solucionar un problema de Unicode cuando uso un servicio web con Python Suds

En este momento estoy haciendo:

from suds.client import Client 
wsdlLink = 'https://link-search.api.cj.com/wsdl/version2/linkSearchServiceV2.wsdl' 
client = Client(wsdlLink) 
result = client.service.searchLinks(developerKey='XXX', websiteId='XXX', promotionType='coupon') 

Esto funciona bien hasta que llegué a un registro que tiene algo así como 'CorpNet® 10% de descuento en cualquier servicio' entonces el ® hace que se rompa y consigo

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 758: ordinal not in range(128)" error. 

¿Hay alguna manera de codificar el ® en mi extremo para que no se rompa cuando SUDS lea el resultado?

ACTUALIZACIÓN: Para aclarar, el ® proviene de la base de datos CJ y está en su respuesta. ASÍ QUE de alguna manera necesito decodificar los caracteres no ASCII ANTES DE QUE SUDS se ocupe de la respuesta. No estoy seguro de cómo (o si) esto se hace en SUD.

+0

asegúrese de no mezclar objetos 'str' y' unicode', por ejemplo, 'u'a '+' ®'' causará el error. Decodifique la entrada a Unicode lo antes posible. – jfs

Respuesta

3

Implicit UnicodeDecodeErrors es algo que obtienes al intentar agregar objetos str y unicode. Python intentará decodificar el str en unicode, pero usando la codificación ASCII. Si tu str contiene algo que no es ascii, obtendrás este error.

Su solución es la decodificación de forma manual, así:

thestring = thestring.decode('utf8') 

intentar, en la medida de lo posible, para decodificar cualquier cadena que puede contienen caracteres no ASCII como soo, a medida que se entregan desde cualquier módulo de donde lo obtienes, en este caso espuma.

Luego, si la espuma no puede manejar Unicode (que puede ser el caso), asegúrese de codificarlo justo antes de devolver el texto a la espuma (o cualquier otra biblioteca que se rompa si le da unicode).

Eso debería resolver las cosas bien. Puede ser un gran cambio, ya que necesita mover todo su procesamiento interno de str a unicode, pero vale la pena. :)

+0

Lennart. El problema es que los caracteres no ascii están realmente en la base de datos CJ y en la respuesta que envían. Así que no estoy seguro de cómo puedo decodificar su respuesta antes de que SUDS intente analizarlo y arroje el error. Necesito de alguna manera enviar la solicitud, decodificar la respuesta y luego analizar la respuesta. Pero no veo una manera de hacer esto en SUD. – chris

+0

@chris: ¿Entonces el error ocurre en la espuma, incluso antes de que su código maneje los datos? En ese caso, es un error, ya sea en espuma o en el servidor. ¿Tal vez el servidor envía datos codificados en UTF cuando dice que es otra cosa? –

+0

Lennart - Correcto. Estoy bastante seguro de que está sucediendo en el servidor (que no puedo controlar). Commission Junction no parece ser compatible con los servicios web y esperaba que hubiera alguna manera de corregir los datos antes de que se vuelvan a incluir en los SUD. Pensaba que era una posibilidad remota, pero pensé que quizás me estaba perdiendo algo. – chris

1

El carácter "registrado" es U + 00AE y está codificado como "\xc2\xae" en UTF-8. Parece que tienes un objeto str codificado en UTF-8, pero algún código está funcionando (probablemente de manera predeterminada) your_str_object.decode("ascii"), que fallará con el mensaje de error que mostraste.

Lo que necesita hacer es mostrarnos un ejemplo completo (es decir, TODO el código necesario para obtener el error), más el mensaje de error completo y el rastreo, para que al menos podamos adivinar si el problema está en su código o en código importado.

+0

Para ser claro. Los datos que están causando el error se encuentran en la respuesta del servicio web. Entonces, envío una solicitud que funciona, pero el problema ocurre cuando CJ responde con un carácter "registrado" en la respuesta. Entonces, lo que tengo que hacer es limpiar de alguna manera al personaje ANTES de que SUDS intente analizarlo. En cuanto al código, lo que ve arriba es todo lo que necesita hacer con SUDS para obtener una respuesta del servicio web y un error de SUD. – chris

+0

@ chris: todo lo que ** debes ** hacer es lo que todo el mundo debería hacer al preguntar sobre un problema que genera una excepción: ejecutar el código mínimo necesario para causar el problema y copiar/pegar el mensaje de error completo y el rastreo en una edición de tu pregunta. Por cierto, ¿cómo sabes que es un personaje "registrado" en la respuesta? –

+0

John: el código que ejecuté es lo que puse en la pregunta, y el error es "UnicodeDecodeError: 'ascii' codec no puede decodificar el byte 0xc2 en la posición 759: ordinal no en el rango (128)". No estoy seguro de lo que está pidiendo más allá de eso. Sé que es el carácter "registrado" porque puedo usar otro cliente que no rompe con los caracteres ASCII y ver que en los resultados que rompen el carácter "registrado" está incluido en la respuesta. Cuando los resultados no incluyen el carácter "registrado", los resultados vuelven correctos. El problema terminó en SUD, hice un parche de ghetto. Gracias – chris

0

Estoy usando SUDS para interactuar con Salesforce a través de su API SOAP. Me encontré con la misma situación hasta que seguí el consejo de @ J.F.Sabastian al no mezclar los tipos de cadenas str y unicode. Por ejemplo, pasar una cadena SOQL como esto funciona con espuma de 0.3.9:

qstr = u"select Id, FirstName, LastName from Contact where FirstName='%s' and LastName='%s'" % (u'Jorge', u'López') 

no me parece que tenga que hacer str.decode ("UTF-8") tampoco.

Si está ejecutando su secuencia de comandos de PyDev en Eclipse, es posible que desee entrar en Proyecto => Propiedades y en Recurso, establezca "Codificación de archivo de texto" en UTF-8, en mi Mac, esto predeterminado es "MacRoman ". Supongo que en Windoze, el valor predeterminado es Cp1252 o ISO-8859-1 (en latín).También puede configurar esto en su espacio de trabajo de sus proyectos heredar esta configuración de su área de trabajo. Esto solo afecta el código fuente del programa.

Cuestiones relacionadas