2013-02-27 8 views
33

を投げる私はurllib.quote("schönefeld")を使用しますが、いくつかの非ASCII文字が文字列に存在する場合、それは私の入力文字列があるurllib.quote()は、URIをエンコードするにはKeyError例外

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

thorwsなどköln, brønshøj, schönefeld

とき私はWindowsで文章を印刷しようとしました(python2.7、pyscripter IDEを使用)。しかし、Linuxでは、例外が発生します(プラットフォームは関係ないと思います)。

これは私がしようとしていますものです:

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

を発行理由を探る: urllib.quote()で、実際に例外がreturn ''.join(map(quoter, s))でthrowinされています。

urllibは内のコードは次のとおりです。例外の理由が''.join(map(quoter, s))である

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

、s内のすべての要素のために、クォータ機能が呼び出され、最終的にはリストは「で参加しました」と返されます。

非ASCII文字の場合èの場合、同等のキーは%E8で、_safe_mapという変数になります。しかし、引用符( 'è')を呼び出すと、キー\xe8が検索されます。キーが存在せず、例外がスローされるようにします。

したがって、try-exceptブロック内で''.join(map(quoter, s))を呼び出す前にs = [el.upper().replace("\\X","%") for el in s]を変更したばかりです。今それは正常に動作します。

しかし、私が行ったことは正しいアプローチですか、それとも他の問題を引き起こすでしょうか? また、すべてのインスタンスでこの修正プログラムを展開するのが非常に難しい200以上のLinuxインスタンスがあります。

+2

このPython 2はユニコード値ですか?既にエンコードされたデータに対しては正常に動作します。 –

+1

あなたは 'urllib.quote( 'sch \ xe9nefeld')'に対してエラーを出さず*しません。あなたは 'urllib.quote(u'sch \ xe9nefeld ')'(unicodeリテラルに注意してください)のエラーだけを取得します。 –

+1

@MartijnPietersだから 'cmdString =" http:// baseurl "+ quote("schönefeld ")' cmdString = u "http:// baseurl" + quote(u "schönefeld") 'のようになりますか? – Garfield

答えて

54

あなたはUnicodeデータを引用しようとしています。そのため、URLセーフバイトに変換する方法を決定する必要があります。

文字列を最初にバイトにエンコードします。 UTF-8が用いられることが多い。

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

しかし、エンコーディングは、サーバがを受け入れるかに依存します。元のフォームが送信されたエンコーディングに固執するのが最善です。

+0

utf-8はあなたの答えが示唆しているよりも強い場合があります。 [すべての主要なブラウザは、URIを構築する際に、パーセントエンコーディングの前にutf-8(http://www.w3.org/International/articles/idn-and-iri/#iriworks)を使用します。 [IRI](http://www.ietf.org/rfc/rfc3987)から[URI](http://www.ietf.org/rfc/rfc3986)はutf-8を使用して変換する必要があります。他のエンコーディングは、従来のサーバーで使用されます。 – jfs

+0

@ J.F.Sebastian:もちろん、URIのパス要素はUTF-8を使用します。しかし、これは代わりにクエリ部分です。ブラウザがクエリ文字列のエンコーディングに使用するものはあまり定義されておらず、かつてはフォームが由来するHTMLページのエンコーディングに基づいていました。 –

0

で発見することができます私は@underscoreとまったく同じエラーが発生しましたが、私の場合には問題はそのマップ(クォータ、でしたs)は_safe_mapにないキーu'\xe9'を探しました。しかし\xe9だったので、私はのu'\xe9'\xe9に置き換えて問題を解決しました。

また、returnステートメントはtry/except内にあるべきではありませんか?私はこの問題を完全に解決するためにこれを変更しなければなりませんでした。

関連する問題