web-dev-qa-db-ja.com

pythonバイト文字列のエンコードとデコード

非ASCII文字を含む着信バイト文字列を有効なutf-8文字列に変換して、jsonのようにダンプできるようにしようとしています。

b = '\x80'
u8 = b.encode('utf-8')
j = json.dumps(u8)

Jは '\ xc2\x80'であると思っていましたが、代わりに次のようになります。

UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0: ordinal not in range(128)

私の状況では、「b」はmysqlからgoogleプロトコルバッファを介して取得され、いくつかのblobデータで埋められます。

何か案は?

編集:mysqlテーブルにblobとして格納されているイーサネットフレームがあります(皆さん、トピックにとどまり、テーブルにパケットがある理由について議論しないでください)。テーブルの照合はutf-8であり、dbレイヤー(sqlalchemy、non-orm)がデータを取得し、blobをpython 'str'として格納する構造体(googleプロトコルバッファー)を作成しています。プロトコルバッファを問題なく直接使用する場合もあれば、jsonを介して同じデータを公開する必要がある場合もあります。json.dumps()が処理を実行すると、「\ x80」を置き換えることができることに気付きました。無効なユニコード文字(\ ufffd iirc)

10
kung-foo

使用しているソフトウェアAPIのドキュメントを調べる必要があります。 BLOBは頭字語です:[〜#〜] binary [〜#〜]ラージオブジェクト。

データが実際にバイナリである場合、それをUnicodeにデコードするという考えはもちろんナンセンスです。

それが実際にテキストである場合は、Unicodeにデコードするために使用するエンコーディングを知る必要があります。

次に、json.dumps(a_Python_object)を使用します...自分でUTF-8にエンコードすると、jsonは再びデコードします。

>>> import json
>>> json.dumps(u"\u0100\u0404")
'"\\u0100\\u0404"'
>>> json.dumps(u"\u0100\u0404".encode('utf8'))
'"\\u0100\\u0404"'
>>>

latin1に関する更新:

u'\x80'は役に立たない無意味なC1制御文字です-エンコーディングがLatin-1である可能性は非常に低いです。 Latin-1は「スネアと妄想」です。8ビットバイトはすべて、例外を発生させることなくUnicodeにデコードされます。 「動作」と「例外を発生させない」を混同しないでください。

9
John Machin

b.decode('name of source encoding')を使用して、Unicodeバージョンを取得します。私がそれを学んだとき、これは私にとって驚きでした。例えば:

In [123]: 'foo'.decode('latin-1')
Out[123]: u'foo'
6
Marcin

あなたがやろうとしているのは、あるエンコーディングの文字列オブジェクトをデコードすることだと思います。そのエンコーディングが何であるか知っていますか? Unicodeオブジェクトを取得します。

unicode_b = b.decode('some_encoding')

次に、utf_8エンコーディングを使用してUnicodeオブジェクトを再エンコードし、文字列オブジェクトに戻します。

b = unicode_b.encode('utf_8')

文字列の元のエンコーディングが何であるかを知らずに、Unicodeオブジェクトをトランスレータとして使用することは確かにわかりませんが、変換が期待どおりに行われない可能性があります。 Unicodeオブジェクトは、あるエンコーディングの文字列を別のエンコーディングに変換するためのものではありません。エンコーディングが何であるかを知っていると仮定して、Unicodeオブジェクトを操作します。エンコーディングが何であるかがわからない場合は、試行錯誤せずに見つけて、エンコードされた文字列に変換し直す方法は実際にはありません。文字列オブジェクトを戻したい。

2
snarkyname77