web-dev-qa-db-ja.com

ユニコードをPythonレベルで文字列に変換するにはどうすればよいですか?

次のユニコードと文字列は、明示的に定義されている場合、単独で存在できます。

>>> value_str='Andr\xc3\xa9'
>>> value_uni=u'Andr\xc3\xa9'

上記のような変数にu'Andr\xc3\xa9'しか割り当てられていない場合、Python 2.5または2.6で'Andr\xc3\xa9'に変換するにはどうすればよいですか?

編集:

私は次のことをしました:

>>> value_uni.encode('latin-1')
'Andr\xc3\xa9'

これで問題が解決します。誰かが私に正確に何が起こっているのか説明できますか?

13
Thierry Lam

エンコーディングが混乱しているようです。本当に必要なのはu'Andr\xe9'である可能性があります。これは'André'と同等です。

しかし、あなたが持っているのは、誤ってデコードされたUTF-8エンコーディングのようです。 Unicode文字列を通常の文字列に変換することで修正できます。最善の方法はわかりませんが、これはうまくいくようです。

>>> ''.join(chr(ord(c)) for c in u'Andr\xc3\xa9')
'Andr\xc3\xa9'

次に、正しくデコードします。

>>> ''.join(chr(ord(c)) for c in u'Andr\xc3\xa9').decode('utf8')
u'Andr\xe9'    

これで正しい形式になりました。

ただし、これを行う代わりに、可能であれば、最初にデータが誤ってエンコードされた理由を解明し、そこでその問題を修正する必要があります。

15
Mark Byers

あなたは(コメントで)「」と尋ねました。「それは私を困惑させます。元のアクセントから現在のアクセントにどのように移行しましたか?utf8とlatin1を使用したダブルエンコーディングと言えば、合計3つのエンコーディング(2 utf8)です。 + 1 latin1)?元の状態から現在の状態へのエンコードの順序は何ですか? "" "

Mark Byersの回答の中で、彼は「あなたが持っているのは、誤ってデコードされたUTF-8エンコーディングのようです」と述べています。あなたは彼の答えを受け入れました。しかし、あなたはまだ困惑していますか? OK、これがブローバイブローの説明です:

注:すべての文字列は、(暗黙的に)repr()を使用して表示されます。 unicodedata.name()は内容を確認するために使用されます。そうすれば、コンソールエンコーディングのバリエーションによって、文字列の解釈が混乱することはありません。

初期状態:u1という名前のUnicodeオブジェクトがあります。 e-acuteが含まれています:

_>>> u1 = u'\xe9'
>>> import unicodedata as ucd
>>> ucd.name(u1)
'LATIN SMALL LETTER E WITH ACUTE'
_

U1をUTF-8としてエンコードし、結果に次の名前を付けます。

_>>> s = u1.encode('utf8')
>>> s
'\xc3\xa9'
_

Latin1-を使用してsをデコードします。 sは、latin1ではなくutf8を使用してエンコードされました。結果は無意味なゴミです。

_>>> u2 = s.decode('latin1')
>>> u2
u'\xc3\xa9'
>>> ucd.name(u2[0]); ucd.name(u2[1])
'LATIN CAPITAL LETTER A WITH TILDE'
'COPYRIGHT SIGN'
>>>
_

理解してください:unicode_object.encode('x').decode('y) x!= yが通常[下記の注を参照]ナンセンスである場合、運が良ければ例外が発生します。運が悪ければ、黙って意味不明になります。また、意味不明な言葉を黙って作成することはバグではないことを理解してください-Python(または他の言語)がナンセンスがコミットされたことを検出できる一般的な方法はありません。これは特にlatin1が256個のコードポイントすべてが最初の256個のUnicodeコードポイントと1対1でマップされるため、str_object.decode( 'latin1')からUnicodeDecodeErrorを取得することはできません。

もちろん、異常な場合(異常であることが望まれます)、質問に対するさまざまな回答で提案されているように、gibberish_unicode_object.encode('y').decode('x')を実行してそのようなナンセンスを元に戻す必要がある場合があります。

5
John Machin

value_uni.encode('utf8')または必要なエンコーディング。

http://docs.python.org/library/stdtypes.html#str.encode を参照してください

4
UncleZeiv

u'Andr\xc3\xa9'がある場合、それは間違ったエンコーディングのバイト文字列からデコードされたUnicode文字列です。正しいエンコーディングはUTF-8です。正しくデコードできるようにバイト文字列に変換し直すには、発見したトリックを使用できます。 Unicodeの最初の256コードポイントは、ISO-8859-1(エイリアスlatin1)エンコーディングを使用した1:1マッピングです。そう:

>>> u'Andr\xc3\xa9'.encode('latin1')
'Andr\xc3\xa9'

これで、utf8で正しくデコードできるバイト文字列になりました。

>>> 'Andr\xc3\xa9'.decode('utf8')
u'Andr\xe9'
>>> print 'Andr\xc3\xa9'.decode('utf8')
André

ワンステップで:

>>> print u'Andr\xc3\xa9'.encode('latin1').decode('utf8')
André
2
Mark Tolonen

OPはasciiまたはutf-8に変換されていません。そのため、提案されたencodeメソッドは機能しません。これを試して:

_v = u'Andr\xc3\xa9'
s = ''.join(map(lambda x: chr(ord(x)),v))
_

chr(ord(x))ビジネスはUnicode文字の数値(アプリケーションの1バイトに収まる)を取得し、_''.join_呼び出しはintのリストを通常の値に変換するイディオムです。ストリング。もっとエレガントな方法があることは間違いありません。

1
I. J. Kennedy

簡単な説明。 strタイプは、0〜255の範囲の文字のみを保持できます。ユニコード(はるかに広い範囲の文字を含むことができる)をstrに格納する場合は、最初にユニコードをstrに適した形式(UTF-8など)にエンコードする必要があります。

この呼び出しメソッドを実行するには、strオブジェクトでencodeを実行し、引数としてthis_is_str = value_uni.encode('utf-8')などの目的のエンコードを指定します。

ここでUnicode処理に関するより長くより詳細な(そして言語に依存しない)記事を読むことができます: 絶対最小すべてのソフトウェア開発者は絶対に、積極的にUnicodeと文字セットについて知っている必要があります(言い訳はありません!)

もう1つの優れた記事(今回はPython固有): nicode HOWTO

0
Bartosz