2013-02-27 16 views
33

Per codificare l'URI, ho usato urllib.quote("schönefeld") ma quando alcuni caratteri non ASCII esiste in stringa, thorwsurllib.quote() genera KeyError

KeyError: u'\xe9' 
Code: return ''.join(map(quoter, s)) 

mie stringhe di input sono köln, brønshøj, schönefeld ecc

Quando Ho provato a stampare le istruzioni in Windows (usando python2.7, IDP di pyscripter). Ma in Linux solleva un'eccezione (suppongo che la piattaforma non abbia importanza).

Questo è quello che sto cercando:

from commands import getstatusoutput 
queryParams = "schönefeld"; 
cmdString = "http://baseurl" + quote(queryParams) 
print getstatusoutput(cmdString) 

Esplorando la ragione problema: in urllib.quote(), in realtà eccezion throwin a return ''.join(map(quoter, s)).

Il codice in urllib è:

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

La ragione di eccezione è in ''.join(map(quoter, s)), per ogni elemento in s, la funzione quoter sarà chiamata e, infine, la lista sarà affiancato da '' ed è tornato.

Per il carattere non ascii è, la chiave equivalente sarà %E8 che si presenta nella variabile _safe_map. Ma quando chiamo quotazione ('è'), cerca la chiave \xe8. In modo che la chiave non esiste e generata eccezione.

Quindi, ho appena modificato s = [el.upper().replace("\\X","%") for el in s] prima di chiamare ''.join(map(quoter, s)) all'interno del blocco try-except. Ora funziona bene.

Ma io sono fastidioso quello che ho fatto è l'approccio corretto o creerà qualsiasi altro problema? E ho anche più di 200 istanze di Linux, che è molto difficile da implementare questa correzione in tutte le istanze.

+2

È questo Python 2 con valori Unicode? Funziona bene per i dati già codificati. –

+1

Non * ottieni * un errore per 'urllib.quote ('sch \ xe9nefeld')'. Tu * solo * ottieni l'errore per 'urllib.quote (u'sch \ xe9nefeld ')' (nota il letterale 'u''' unicode). –

+1

@MartijnPieters quindi 'cmdString =" http: // baseurl "+ quota (" schönefeld ")' questo dovrebbe essere come 'cmdString = u" http: // baseurl "+ quote (u" schönefeld ")'? – Garfield

risposta

54

Si sta tentando di citare dati Unicode, quindi è necessario decidere come trasformarlo in byte sicuri per URL.

Codificare prima la stringa in byte. UTF-8 è usato spesso:

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

Tuttavia, la codifica dipende da ciò che il server accetterà. È meglio attenersi alla codifica con la quale è stato inviato il modulo originale.

+0

utf-8 ha una valenza più forte della tua risposta. [Tutti i principali browser utilizzano utf-8] (http://www.w3.org/International/articles/idn-and-iri/#iriworks) prima della codifica percentuale durante la costruzione degli URI. [IRI] (http://www.ietf.org/rfc/rfc3987) in [URI] (http://www.ietf.org/rfc/rfc3986) deve essere convertito usando utf-8. Altre codifiche vengono utilizzate su server legacy. – jfs

+0

@ J.F.Sebastian: certo, gli elementi di percorso degli URI utilizzano UTF-8. Ma questa è la parte della query. Ciò che un browser utilizza per la codifica nella stringa di query è meno ben definito ed è stato, in passato, basato sulla codifica della pagina HTML da cui proviene il modulo. –

0

Ho avuto lo stesso errore esatto come @underscore ma nel mio caso il problema era che mappa (quoter, s) ha provato a cercare la chiave u'\xe9' che non era nello _safe_map. Tuttavia, \xe9 era, quindi ho risolto il problema sostituendo u'\xe9' da \xe9 in s.

Inoltre, la dichiarazione return non deve essere compresa tra try/except? Ho anche dovuto cambiare questo per risolvere completamente il problema.

Problemi correlati