2010-08-25 17 views
45

Estoy tratando de codificar y almacenar, y decodificar argumentos en Python y perderme en algún lugar en el camino. Aquí están mis pasos:Codificación/decodificación URL con Python

1) Yo uso Google toolkit's gtm_stringByEscapingForURLArgument para convertir un NSString correctamente para pasar a los argumentos HTTP.

2) En mi servidor (python), guardo estos argumentos de cadena como algo como u'1234567890-/:;()$&@".,?!\'[]{}#%^*+=_\\|~<>\u20ac\xa3\xa5\u2022.,?!\'' (tenga en cuenta que estas son las teclas estándar de un teclado iphone en la vista "123" y "# + =", \u y \x caracteres de estar allí algunos prefijos monetarios como libra, yen, etc.)

3) Tiene la palabra urllib.quote(myString,'') en ese valor almacenado, presumiblemente para -escape% para su transporte al cliente para que el cliente puede unpercent escapar de ellos.

El resultado es que obtengo una excepción cuando intento registrar el resultado de% de escape. ¿Hay algún paso crucial que pase por alto que deba aplicarse al valor almacenado con el formato \ uy \ x para convertirlo correctamente para enviarlo a través de http?

Actualización: La sugerencia marcada como la siguiente respuesta funcionó para mí. Sin embargo, estoy proporcionando algunas actualizaciones para completar los comentarios a continuación.

La excepción que recibí citó un problema con \u20ac. No sé si fue un problema con eso específicamente, en lugar del hecho de que era el primer carácter Unicode en la cadena.

Ese \u20ac char es el unicode para el símbolo 'euro'. Básicamente encontré que tendría problemas con él a menos que use el método urllib2 quote.

+1

Proporcione los detalles de la excepción y un seguimiento si es posible. –

+0

Parece que su cadena no es una cadena Unicode válida. Intenté simplemente imprimirlo y me da error de codificación para el carácter \ u20ac. –

Respuesta

69

url que codifica un unicode "en bruto" realmente no tiene sentido. Lo que debe hacer es .encode("utf8") primero, de modo que tenga una codificación de bytes conocida y luego .quote() eso.

La salida no es muy bonita, pero debería ser una codificación uri correcta.

>>> s = u'1234567890-/:;()$&@".,?!\'[]{}#%^*+=_\|~<>\u20ac\xa3\xa5\u2022.,?!\'' 
>>> urllib2.quote(s.encode("utf8")) 
'1234567890-/%3A%3B%28%29%24%26%40%22.%2C%3F%21%27%5B%5D%7B%7D%23%25%5E%2A%2B%3D_%5C%7C%7E%3C%3E%E2%82%AC%C2%A3%C2%A5%E2%80%A2.%2C%3F%21%27' 

Recuerde que usted tendrá que tanto unquote() y decode() este imprimirlo correctamente si está depurando o lo que sea.

>>> print urllib2.unquote(urllib2.quote(s.encode("utf8"))) 
1234567890-/:;()$&@".,?!'[]{}#%^*+=_\|~<>€£¥•.,?!' 
>>> # oops, nasty  means we've got a utf8 byte stream being treated as an ascii stream 
>>> print urllib2.unquote(urllib2.quote(s.encode("utf8"))).decode("utf8") 
1234567890-/:;()$&@".,?!'[]{}#%^*+=_\|~<>€£¥•.,?!' 

Ésta es, de hecho, lo que el django functions mencionado en otra respuesta hacer.

El funciones django.utils.http.urlquote() y django.utils.http.urlquote_plus() son versiones de urllib.quote estándar de Python() y urllib.quote_plus() que trabajan con caracteres no ASCII. (Los datos se convierten en UTF-8 antes de codificación.)

tener cuidado si usted está solicitando cualquier cita o más codificaciones de no destrozar cosas.

+2

¡Acabas de salvar mi día con djang.utils.http.urlquote/unquote! Muchas gracias. –

2

Estás de suerte con stdlib, urllib.quote no funciona con Unicode. Si está utilizando django puede usar django.utils.http.urlquote que funciona correctamente con unicode

4

quiero hacer una segunda observación de pycruft. los protocolos web han evolucionado a lo largo de décadas, y tratar con los diversos conjuntos de convenciones puede ser engorroso. ahora las URL no están explícitamente definidas para los caracteres, sino solo para los bytes (octetos). como una coincidencia histórica, las URL son uno de los lugares donde solo se puede asumir, pero no hacer cumplir o esperar de forma segura una codificación. sin embargo, existe una convención para preferir latin-1 y utf-8 sobre otras codificaciones aquí. por un tiempo, parecía que 'unicode percent escapes' sería el futuro, pero nunca se entendieron.

es de suma importancia para ser pedante exigente en esta área sobre la diferencia entre unicode objetos y octeto str Ings (en Python < 3,0; eso es, confusamente, str objetos Unicode y bytes/bytearray objetos en Python> = 3.0) . desafortunadamente, en mi experiencia, es por una serie de razones bastante difíciles de separar los dos conceptos en Python 2.x.

aún más OT, cuando desee recibir solicitudes HTTP de terceros, no puede confiar absolutamente en que las URL se envíen en octetos con escapes porcentuales, con codificación utf-8: ambos pueden ser ocasionales %uxxxx escapar allí , y al menos Firefox 2.x solía codificar las URL como latin-1 siempre que fuera posible, y como utf-8 solo cuando era necesario.