2010-08-25 5 views
45

J'essaye d'encoder, de stocker et de décoder des arguments en Python et de me perdre quelque part sur le chemin. Voici mes étapes:Encodage/décodage d'URL avec Python

1) J'utilise le gtm_stringByEscapingForURLArgument de google toolkit pour convertir correctement un NSString afin de le transmettre dans des arguments HTTP. 2) Sur mon serveur (python), je stocke ces arguments sous la forme u'1234567890-/:;()$&@".,?!\'[]{}#%^*+=_\\|~<>\u20ac\xa3\xa5\u2022.,?!\'' (notez que ce sont les touches standard sur un clavier iphone dans la vue "123" et la vue "# + =", la \u et \x caractères dans la présence de quelques préfixes monétaires comme livre, yen, etc.)

3) J'appelle urllib.quote(myString,'') sur cette valeur stockée, probablement à% pour le transport les caractères d'échappement au client afin que le client peut unpercent leur échapper.

Le résultat est que j'obtiens une exception lorsque j'essaie de consigner le résultat de% d'échappement. Y at-il une étape cruciale que je néglige qui doit être appliquée à la valeur stockée avec le format \ u et \ x afin de le convertir correctement pour l'envoi sur http?

Mise à jour: La suggestion marquée comme la réponse ci-dessous a fonctionné pour moi. Je fournis quelques mises à jour pour répondre aux commentaires ci-dessous pour être complet, cependant.

L'exception que j'ai reçue a signalé un problème avec \u20ac. Je ne sais pas si c'était un problème spécifique, plutôt que le fait que c'était le premier caractère Unicode dans la chaîne.

Ce \u20ac char est l'unicode pour le symbole 'euro'. J'ai essentiellement trouvé que j'aurais des problèmes à moins que j'utilise la méthode urllib2 quote.

+1

Veuillez fournir les détails de l'exception et une trace si possible. –

+0

Il semble que votre chaîne n'est pas une chaîne Unicode valide. J'ai essayé de l'imprimer simplement et il me donne l'erreur d'encodage pour le caractère de \ u20ac. –

Répondre

69

url encoder un "brut" unicode n'a pas vraiment de sens. Qu'est-ce que vous devez faire est .encode("utf8") d'abord de sorte que vous avez un codage byte connu, puis .quote() que.

La sortie n'est pas très jolie mais devrait être un encodage uri correct.

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

Rappelez-vous que vous aurez besoin à la fois unquote() et decode() cela pour l'imprimer correctement si vous le débogage ou autre.

>>> 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-/:;()$&@".,?!'[]{}#%^*+=_\|~<>€£¥•.,?!' 

Ceci est, en fait, ce que l'django functions mentionné dans une autre réponse.

Les fonctions django.utils.http.urlquote() et django.utils.http.urlquote_plus() sont versions standard de Python urllib.quote() et urllib.quote_plus() qui travaillent avec des caractères non-ASCII. (Les données sont converties en UTF-8 avant à l'encodage.)

Soyez prudent si vous faites une demande de devis ou d'autres encodages ne pas mutiler les choses.

+2

Vous venez de sauvegarder ma journée avec djang.utils.http.urlquote/unquote! Merci beaucoup. –

2

Vous êtes hors de votre chance avec stdlib, urllib.quote ne fonctionne pas avec unicode. Si vous utilisez django, vous pouvez utiliser django.utils.http.urlquote qui fonctionne correctement avec unicode

4

Je tiens à souligner la remarque de pycruft. Les protocoles Web ont évolué au fil des décennies et la gestion des divers ensembles de conventions peut être fastidieuse. maintenant, les URL ne sont pas explicitement définies pour les caractères, mais uniquement pour les octets (octets). comme une coïncidence historique, les URL sont l'un des endroits où vous pouvez seulement supposer, mais ne pas imposer ou attendre en toute sécurité un encodage d'être présent. cependant, il y a une convention pour préférer latin-1 et utf-8 par rapport aux autres encodages ici. pendant un moment, il ressemblait à «unicode percent escapes» serait l'avenir, mais ils n'ont jamais compris.

il est d'une importance capitale pour être pédante pointilleux dans ce domaine sur la différence entre unicode objets et octet str Ings (en Python < 3.0, c'est, prêter à confusion, str objets unicode et bytes/bytearray objets en Python> = 3.0) . Malheureusement, dans mon expérience, il est assez difficile de séparer proprement les deux concepts de Python 2.x pour un certain nombre de raisons. OT plus, quand vous voulez recevoir des requêtes HTTP tierces, vous ne pouvez pas absolument compter sur les URL envoyées dans les octets à octets UF-8 à échappement en pourcentage: il peut y avoir occasionnellement une évasion %uxxxx , et au moins firefox 2.x utilisé pour coder les URL comme latin-1 lorsque cela est possible, et comme utf-8 seulement lorsque cela est nécessaire.