2010-06-25 13 views
26

tengo esto:Error con urlencode en Python

a = {'album': u'Metamorphine', 'group': 'monoku', 'name': u'Son Of Venus (Danny\xb4s Song)', 'artist': u'Leandra', 'checksum': '2836e33d42baf947e8c8adef48921f2f76fcb37eea9c50b0b59d7651', 'track_number': 8, 'year': '2008', 'genre': 'Darkwave', 'path': u'/media/data/musik/Leandra/2008. Metamorphine/08. Son Of Venus (Danny\xb4s Song).mp3', 'user_email': '[email protected]', 'size': 6624104} 
data = urllib.urlencode(mp3_data) 

Y que lanzar una excepción:

Traceback (most recent call last): 
    File "playkud.py", line 44, in <module> 
    main() 
    File "playkud.py", line 29, in main 
    craw(args, options.user_email, options.group) 
    File "/home/diegueus9/workspace/playku/src/client/playkud/crawler/crawler.py", line 76, in craw 
    index(root, file, data, user_email, group) 
    File "/home/diegueus9/workspace/playku/src/client/playkud/crawler/crawler.py", line 58, in index 
    done = add_song(data[mp3file]) 
    File "/home/diegueus9/workspace/playku/src/client/playkud/service.py", line 32, in add_song 
    return make_request(URL+'add_song/', data) 
    File "/home/diegueus9/workspace/playku/src/client/playkud/service.py", line 14, in make_request 
    data = urllib.urlencode(dict([k.encode('utf-8'),v] for k,v in mp3_data.items())) 
    File "/usr/lib/python2.5/urllib.py", line 1250, in urlencode 
    v = quote_plus(str(v)) 
UnicodeEncodeError: 'ascii' codec can't encode character u'\xb4' in position 19: ordinal not in range(128) 

y con ipython (2.5):

In [7]: urllib.urlencode(a) 
UnicodeEncodeError      Traceback (most recent call last) 

/home/diegueus9/<ipython console> in <module>() 

/usr/lib/python2.5/urllib.pyc in urlencode(query, doseq) 
    1248   for k, v in query: 
    1249    k = quote_plus(str(k)) 
-> 1250    v = quote_plus(str(v)) 
    1251    l.append(k + '=' + v) 
    1252  else: 

UnicodeEncodeError: 'ascii' codec can't encode character u'\xb4' in position 19: ordinal not in range(128) 

cómo puedo solucionar ¿eso?

Respuesta

55

La biblioteca urlencode espera datos en formato str, y no trata bien con datos Unicode ya que no proporciona una manera de especificar una codificación. Tal vez puedas probar:

mp3_data = {'album': u'Metamorphine', 
    'group': 'monoku', 
    'name': u'Son Of Venus (Danny\xb4s Song)', 
    'artist': u'Leandra', 
    'checksum': '2836e33d42baf947e8c8adef48921f2f76fcb37eea9c50b0b59d7651', 
    'track_number': 8, 
    'year': '2008', 'genre': 'Darkwave', 
    'path': u'/media/data/musik/Leandra/2008. Metamorphine/08. Son Of Venus (Danny\xb4s Song).mp3', 
    'user_email': '[email protected]', 
    'size': 6624104} 

str_mp3_data = {} 
for k, v in mp3_data.iteritems(): 
    str_mp3_data[k] = unicode(v).encode('utf-8') 
data = urllib.urlencode(str_mp3_data) 

Lo que hice fue asegurarse de que todos los datos se codifica en str con UTF-8 antes de pasar el diccionario en la función urlencode.

+0

me salvó!: D – John

+0

Utilicé esto para el mensaje de error - codec unicodeencodeerror 'ascii' no puede codificar el carácter u '\ xb4'. Gracias –

+0

Esto es mal y da el mismo error ... – Cerin

3

el problema es que desea convertir una cadena de caracteres unicode a una cadena, pero primero hay algunos caracteres que deben convertirse a ASCII. Así que yo le asesoramiento para buscar cadenas que no son ASCII y luego codificarlos como sigue:

tratar de cambiar por ejemplo donde v es un Unicode-cadena para:

quote_plus(str(v)) 

a

quote_plus(str(v.encode("utf-8"))) 

que debería ayudar


Si no tiene que usar Python 2.x, puede cambiar a Python 3.x, donde todas las cadenas son unicode por defecto. Pero tiene que convertir algunas cosas para ello (puede automatizar esta fiesta o completarla con 2to3).

+0

Creo que, pero es un poco desagradable porque está en el núcleo de python:/ – diegueus9

+0

hmm .. No creo que sea culpa del urllib. maybie hay una cadena en cualquier lugar, que no está codificada en ASCII. ¿Puedes buscar eso o proporcionar más código? – Joschua

+0

si ve el rastreo, puede leer que la excepción se plantea en /usr/lib/python2.5/urllib.pyc – diegueus9

4

El problema es que algunos de los valores en su dict mp3_data son cadenas unicode que no se pueden representar en la codificación predeterminada utilizada por urlencode() (mientras que otros son ASCII y otros son enteros). Puede solucionar esto codificando esos valores antes de pasarlos al urlencode(). La línea 14 de /home/diegueus9/workspace/playku/src/client/playkud/service.py, en make_request(), trate de cambiar esto:

data = urllib.urlencode(dict([k.encode('utf-8'),v] for k,v in mp3_data.items())) 

a esto:

data = urllib.urlencode(dict([k.encode('utf-8'),unicode(v).encode('utf-8')] for k,v in mp3_data.items())) 
+0

no todos los valores son cadenas, esto no funciona – diegueus9

+0

No tienen que ser cadenas para que esto funcione. Tenga en cuenta mi uso de la llamada Unicode() para convertir cualquier número entero o cadenas simples para unicode antes de codificar como utf-8. Si realmente no funciona, me interesaría ver cómo se ve la falla (¿Estás seguro de que respondiste a la respuesta correcta?) –

8

Si está usando Django, eche un vistazo a la clase QueryDict de Django, tiene un método urlencode().

O, para la función auxiliar en sí, puede usar urlencode. Básicamente, hace lo que se describe en las otras respuestas como un contenedor alrededor del urllib.encode original.

+0

Aunque no me di cuenta es op usando django, yo era, y encontré esta respuesta muy útil! Déjame sugerir una edición para elaborar – tutuDajuju

+0

bien, vine aquí mientras buscaba el error django. Esa envoltura funciona. Gracias – chhantyal