Codificación / deencoding de URL con Python

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:

1) Uso gtm_stringByEscapingForURLArgument del kit de herramientas de gtm_stringByEscapingForURLArgument para convertir un NSString correctamente para pasar a argumentos HTTP.

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

3) Llamo a urllib.quote(myString,'') en ese valor almacenado, presumiblemente a% -escape para su transporte al cliente para que el cliente no pueda escapar de ellos.

El resultado es que recibo una excepción cuando bash registrar el resultado de% escape. ¿Hay algún paso crucial que esté pasando por alto que deba aplicarse al valor almacenado con el formato \ u y \ 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 abordar los comentarios a continuación para que estén completos.

    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 fue el primer carácter Unicode en la cadena.

    Ese carácter es el Unicode para el símbolo ‘euro’. Básicamente descubrí que tendría problemas con él a menos que usara el método de quote urllib2.

    la url que codifica un unicode “sin procesar” realmente no tiene sentido. Lo que debe hacer es .encode("utf8") primero, de modo que tenga una encoding de byte conocida y luego .quote() .

    La salida no es muy bonita pero debería ser una encoding 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 tendrá que unquote() tanto unquote() como decode() esto para imprimirlo correctamente si está haciendo una depuración 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-/:;()$&@".,?!'[]{}#%^*+=_\|~<>€£¥•.,?!' 

    Esto es, de hecho, lo que hacen las funciones django mencionadas en otra respuesta.

    Las funciones django.utils.http.urlquote () y django.utils.http.urlquote_plus () son versiones de urllib.quote () y urllib.quote_plus () estándar de Python que funcionan con caracteres que no son ASCII. (Los datos se convierten a UTF-8 antes de la encoding).

    Tenga cuidado si está aplicando más citas o codificaciones para no destrozar las cosas.

    Quiero segundo comentario 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 están explícitamente no definidas para caracteres, pero solo para bytes (octetos). como una coincidencia histórica, las URL son uno de los lugares donde solo puede asumir, pero no imponer o esperar que una encoding esté presente. sin embargo, hay una convención para preferir latin-1 y utf-8 sobre otras codificaciones aquí. por un tiempo, parecía que el ‘ porcentaje de escapes de Unicode ‘ sería el futuro, pero nunca lo lograron.

    es de sum importancia ser pediátricamente exigente en esta área acerca de la diferencia entre los objetos unicode y las str octetos (en Python <3.0; esto es, confusamente, objetos str Unicode y objetos bytes / bytearray en Python> = 3.0). desafortunadamente, en mi experiencia, por varias razones es bastante difícil separar limpiamente los dos conceptos en Python 2.x.

    aún más OT, cuando desea recibir solicitudes HTTP de terceros, no puede confiar absolutamente en que las direcciones URL se envíen en octetos con porcentaje de escape, codificados en utf-8: puede haber el %uxxxx escape ocasional %uxxxx allí, y Firefox 2.x se usa para codificar URL como latin-1 cuando sea posible, y como utf-8 solo cuando sea necesario.

    No tienes suerte con stdlib, urllib.quote no funciona con Unicode. Si está utilizando django, puede usar django.utils.http.urlquote que funciona correctamente con Unicode.