9

requestsモジュールを使用してWebサービスから取得したUnicode文字列があります。この文字列には、バイナリドキュメント(PCL)のバイトが含まれています。これらのバイトの1つは値248であり、base64エンコードしようとすると、次のエラーが発生します。

In [68]: base64.b64encode(response_dict['content']+'\n')
---------------------------------------------------------------------------
UnicodeEncodeError                        Traceback (most recent call last)
C:\...\<ipython-input-68-8c1f1913eb52> in <module>()
----> 1 base64.b64encode(response_dict['content']+'\n')

C:\Python27\Lib\base64.pyc in b64encode(s, altchars)
     51     """
     52     # Strip off the trailing newline
---> 53     encoded = binascii.b2a_base64(s)[:-1]
     54     if altchars is not None:
     55         return _translate(encoded, {'+': altchars[0], '/': altchars[1]})

UnicodeEncodeError: 'ascii' codec can't encode character u'\xf8' in position 272: ordinal not in range(128)

In [69]: response_dict['content'].encode('base64')
---------------------------------------------------------------------------
UnicodeEncodeError                        Traceback (most recent call last)
C:\...\<ipython-input-69-7fd349f35f04> in <module>()
----> 1 response_dict['content'].encode('base64')

C:\...\base64_codec.pyc in base64_encode(input, errors)
     22     """
     23     assert errors == 'strict'
---> 24     output = base64.encodestring(input)
     25     return (output, len(input))
     26

C:\Python27\Lib\base64.pyc in encodestring(s)
    313     for i in range(0, len(s), MAXBINSIZE):
    314         chunk = s[i : i + MAXBINSIZE]
--> 315         pieces.append(binascii.b2a_base64(chunk))
    316     return "".join(pieces)
    317

UnicodeEncodeError: 'ascii' codec can't encode character u'\xf8' in position 44: ordinal not in range(128)

248は符号なしバイトの範囲内にあるため(そしてバイト文字列に保持できるため)、これは少し驚くべきことですが、私の本当の質問は、この文字列をエンコードするための最良または正しい方法は何ですか?

私の現在の回避策はこれです:

In [74]: byte_string = ''.join(map(compose(chr, ord), response_dict['content']))

In [75]: byte_string[272]
Out[75]: '\xf8'

これは正しくbyte_string機能しているようで、結果はbase64でエンコードできますが、もっと良い方法があるはずです。ある?

4

5 に答える 5

18

base64でエンコードするunicode文字列があります。問題は、文字ではなくバイトb64encode()でのみ機能することです。したがって、文字列(抽象的なUnicodeコードポイントのシーケンス)をバイト文字列に変換する必要があります。unicode

抽象Unicode文字列を具体的な一連のバイトにマッピングすることをエンコーディングと呼びます。Pythonはいくつかのエンコーディングをサポートしています。広く使用されているUTF-8エンコーディングをお勧めします。

byte_string = response_dict['content'].encode('utf-8')

バイトをデコードしている人は誰でもunicode、補完decode()関数を介して文字列を取得するためにどのエンコーディングが使用されたかを知る必要があることに注意してください。

# Decode
decoded = byte_string.decode('utf-8')

Unicodeとエンコーディングについてさらに学ぶための良い出発点は、PythonのドキュメントとJoelSpolskyによるこの記事です。

于 2012-03-05T19:06:34.380 に答える
5

base64でエンコードする前に、まずUTF-8のようなものにエンコードすることをお勧めします。

In [12]: my_unicode = u'\xf8'

In [13]: my_utf8 = my_unicode.encode('utf-8')

In [15]: base64.b64encode(my_utf8)
Out[15]: 'w7g='
于 2012-03-05T19:06:16.630 に答える
3

バイナリ データを扱っているので、utf-8 エンコーディングを使用するのが良い考えかどうかはわかりません。base64 でエンコードされた表現をどのように使用するかによって異なると思います。Unicode 文字列ではなくバイト文字列としてデータを取得できれば、おそらくより良いと思います。requests ライブラリを使用したことはありませんが、ドキュメントを参照すると、それが可能であることが示唆されます。「バイナリ レスポンス コンテンツ」と「生のレスポンス コンテンツ」について説明しているセクションがあります。

于 2012-03-05T19:16:58.273 に答える
1

応答をバイナリ バイトとして取得し、デコードとエンコードの手順を完全にスキップできるはずです。requests往復で一部のデータやエラーが失われるエンコーディングを選択する可能性は常にあります。

「Binary Response Content」と呼ばれるドキュメントのこの部分は、問題に完全に適合しているようです。

于 2012-03-05T20:28:43.290 に答える
0

バイナリデータの場合...なぜエンコード/デコードするのですか? 特に「base64.encodestring」の部分。以下は、余分なファイルを用意する代わりに、Python コードに直接追加するために画像を base64 にエンコードする方法です。2.7.2ところで

import base64
iconfile = open("blah.icon","rb")
icondata = iconfile.read()
icondata = base64.b64encode(icondata)
于 2012-03-05T22:26:57.240 に答える