web-dev-qa-db-ja.com

python)のurlencodeでエラーが発生しました

私はこれを持っています:

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)

そしてそれは例外を引き起こします:

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)

および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)

どうすれば修正できますか?

28
diegueus9

urlencodeライブラリはstr形式のデータを想定しており、エンコーディングを指定する方法を提供しないため、Unicodeデータを適切に処理しません。代わりにこれを試してください:

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)

私がしたことは、辞書をstr関数に渡す前に、UTF-8を使用してすべてのデータがurlencodeにエンコードされていることを確認することでした。

58
Walter Mundt

Djangoを使用している場合は、DjangoのQueryDictクラスを見てください。このクラスにはurlencode()メソッドがあります。

または、ヘルパー関数自体に urlencode を使用できます。基本的に、他の回答で説明されていることを、元のurllib.encodeのラッパーとして実行します。

問題は、mp3_data dictの値の一部が、urlencode()で使用されるデフォルトのエンコーディングでは表現できないユニコード文字列であるということです(他の値はASCIIであり、それでもその他は整数です)。これらの値をurlencode()に渡す前にエンコードすることで、これを修正できます。/home/diegueus9/workspace/playku/src/client/playkud/service.pyの14行目、make_request()、これを変更してみてください:

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

これに:

data = urllib.urlencode(dict([k.encode('utf-8'),unicode(v).encode('utf-8')] for k,v in mp3_data.items()))
4
ʇsәɹoɈ

問題は、Unicode文字列を文字列にキャストしたいのですが、最初にASCII)に変換する必要のある文字がいくつかあるため、次のような文字列を検索することをお勧めします。 ASCIIではないので、次のようにエンコードします。

を変更してみてください。たとえばここで、vは次のようなUnicode文字列です。

quote_plus(str(v))

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

それは役立つはずです


Python 2.xを使用する必要がない場合は、Python 3.xに切り替えることができます。ここで、すべての文字列はデフォルトでユニコードです。いくつかのものを変換します(このパーティーを自動化するか、 2to でいっぱいにすることができます)。

3
Joschua