40

URIをエンコードするために使用urllib.quote("schönefeld")しましたが、ASCII以外の文字が文字列に存在する場合、thorwsします

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

私の入力文字列はköln, brønshøj, schönefeldetc.

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))ます。

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

例外の理由は です''.join(map(quoter, s))。s のすべての要素に対して、quoter 関数が呼び出され、最後にリストが '' で結合されて返されます。

非 ascii charèの場合、同等のキーは%E8which presents in _safe_mapvariable になります。しかし、quote('è') を呼び出すと、 key が検索されます\xe8。キーが存在せず、例外がスローされるようにします。

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

しかし、私がやったことは正しいアプローチですか、それとも他の問題が発生しますか? また、Linux のインスタンスが 200 以上あるため、すべてのインスタンスにこの修正を展開するのは非常に困難です。

4

3 に答える 3

63

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'

ただし、エンコーディングはサーバーが受け入れるものによって異なります。元のフォームが送信されたときのエンコーディングに固執することをお勧めします。

于 2013-02-27T15:19:23.247 に答える
2

文字列をユニコードに変換するだけで、問題は解決しました。

ここにスニペットがあります:

try:
    unicode(mystring, "ascii")
except UnicodeError:
    mystring = unicode(mystring, "utf-8")
else:
    pass

ソリューションの詳細な説明はhttp://effbot.org/pyfaq/what-does-unicodeerror-ascii-decoding-encoding-error-ordinal-not-in-range-128-mean.htmにあります。

于 2013-12-17T11:42:26.807 に答える
1

@underscore とまったく同じエラーが発生しましたが、私の場合、問題は map(quoter,s)u'\xe9'が にないキーを探しようとしたことでした_safe_map。しかし、だったので、 in に\xe9置き換えることで問題を解決しu'\xe9'ました。\xe9s

さらに、returnステートメントはtry/except?内にあるべきではありません。問題を完全に解決するには、これを変更する必要もありました。

于 2015-07-28T14:51:35.060 に答える