ejemplos - urllib2 python 3
urllib.quote() arroja KeyError (3)
Para codificar el URI, utilicé urllib.quote("schönefeld")
pero cuando existen algunos caracteres no ascii en cadena,
KeyError: u''/xe9''
Code: return ''''.join(map(quoter, s))
Mis cadenas de entrada son köln, brønshøj, schönefeld
etc.
Cuando intenté imprimir sentencias en Windows (usando python2.7, pyscripter IDE). Pero en Linux se produce una excepción (supongo que la plataforma no importa).
Esto es lo que estoy intentando:
from commands import getstatusoutput
queryParams = "schönefeld";
cmdString = "http://baseurl" + quote(queryParams)
print getstatusoutput(cmdString)
Explorando el motivo del problema: en urllib.quote()
, en realidad la excepción es throwin en return ''''.join(map(quoter, s))
.
El código en urllib es:
def quote(s, safe=''/''):
if not s:
if s is None:
raise TypeError(''None object cannot be quoted'')
return s
cachekey = (safe, always_safe)
try:
(quoter, safe) = _safe_quoters[cachekey]
except KeyError:
safe_map = _safe_map.copy()
safe_map.update([(c, c) for c in safe])
quoter = safe_map.__getitem__
safe = always_safe + safe
_safe_quoters[cachekey] = (quoter, safe)
if not s.rstrip(safe):
return s
return ''''.join(map(quoter, s))
El motivo de la excepción está en ''''.join(map(quoter, s))
, para cada elemento en s, se llamará a la función quoter y finalmente la lista se unirá por '''' y se devolverá.
Para caracteres que no sean ascii, la clave equivalente será %E8
que se presenta en la variable _safe_map
. Pero cuando estoy llamando a quote (''è''), busca la clave /xe8
. De modo que la clave no existe y se lanza la excepción.
Entonces, modifiqué s = [el.upper().replace("//X","%") for el in s]
antes de llamar a ''''.join(map(quoter, s))
dentro del bloque try-except . Ahora funciona bien.
Pero estoy molesto por lo que he hecho, ¿es el enfoque correcto o creará algún otro problema? Y también tengo más de 200 instancias de Linux que es muy difícil de implementar esta solución en todas las instancias.
Con solo convertir la cadena en unicode, resolví el problema.
aquí está el fragmento:
try:
unicode(mystring, "ascii")
except UnicodeError:
mystring = unicode(mystring, "utf-8")
else:
pass
La descripción detallada de la solución se puede encontrar en http://effbot.org/pyfaq/what-does-unicodeerror-ascii-decoding-encoding-error-ordinal-not-in-range-128-mean.htm
Está intentando citar datos Unicode, por lo que debe decidir cómo convertirlos en bytes seguros para URL.
Primero codifica la cadena en bytes. UTF-8 se usa a menudo:
>>> import urllib
>>> urllib.quote(u''sch/xe9nefeld'')
/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib.py:1268: UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal
return ''''.join(map(quoter, s))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib.py", line 1268, in quote
return ''''.join(map(quoter, s))
KeyError: u''/xe9''
>>> urllib.quote(u''sch/xe9nefeld''.encode(''utf8''))
''sch%C3%A9nefeld''
Sin embargo, la codificación depende de lo que el servidor acepte . Lo mejor es atenerse a la codificación con la que se envió el formulario original.
Tenía exactamente el mismo error que @underscore, pero en mi caso el problema era que el mapa (quoter, s) intentaba buscar la clave u''/xe9''
que no estaba en _safe_map
. Sin embargo, /xe9
fue así que resolví el problema reemplazando u''/xe9''
por /xe9
en s
.
Además, ¿no debería la declaración de return
estar dentro del try/except
? También tuve que cambiar esto para resolver completamente el problema.