エンコード/デコードの違いは何ですか?


180

str / unicodeのデコードとエンコードの違いを理解していることを確信できませんでした。

私はそれstr().decode()が特定の文字エンコーディングを持っていることがわかっているバイトの文字列を持っているときに、そのエンコーディング名がUnicode文字列を返すことを知っています。

unicode().encode()与えられたエンコーディング名に従ってユニコード文字をバイトの文字列に変換することを知っています。

しかし、私は何str().encode()を理解していないのかunicode().decode()。誰かが説明できますか、そしておそらく私が上で間違っている他の何かを修正することもできますか?

編集:

いくつかの答え.encodeは文字列で何が行われるかについての情報を提供しますが、誰.decodeもがユニコードで何が行われるのかを知りません。


このページの 2番目の答えは十分明確で簡潔だと思います。
2016

回答:


106

decodeユニコード文字列のメソッドには、実際にはアプリケーションがまったくありません(何らかの理由でユニコード文字列にテキスト以外のデータが含まれている場合を除いて、以下を参照してください)。それは歴史的な理由で主にそこにあると思います。Python 3では完全になくなりました。

unicode().decode()デフォルト(ASCII)コーデックを使用する暗黙のエンコーディングを実行sします。これを次のように確認します。

>>> s = u'ö'
>>> s.decode()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf6' in position 0:
ordinal not in range(128)

>>> s.encode('ascii')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf6' in position 0:
ordinal not in range(128)

エラーメッセージはまったく同じです。

str().encode()それが他の方法で回避だ-それは暗黙の試みデコードsデフォルトのエンコーディングとの:

>>> s = 'ö'
>>> s.decode('utf-8')
u'\xf6'
>>> s.encode()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0:
ordinal not in range(128)

このように使用すると、str().encode()余計にもなります。

しかし、後者の方法にはもう1つの便利なアプリケーションがあります。文字セットとは何の関係もないエンコーディングがあり、意味のある方法で8ビット文字列に適用できます。

>>> s.encode('zip')
'x\x9c;\xbc\r\x00\x02>\x01z'

しかし、あなたは正しいです。これらのアプリケーションの両方で「エンコーディング」のあいまいな使用法は...おかしいです。繰り返しにbyteなりstringますが、Python 3では型と型が分離されているため、これは問題ではなくなりました。


4
.decode()Unicode文字列の場合は便利かもしれません。たとえば、print u'\\u0203'.decode('unicode-escape')
jfs

python3での@JFSebastianの良い例私はあなたがそうするだろうと思います:print u'\\u0203'.encode('utf8').decode('unicode-escape')
AJP

1
@AJP:Python 3の場合codecs.decode(u'\\u0203', 'unicode-escape')
jfs 2014年

@ホップ:はい。無効な入力を検出し、Pythonの2/3の互換性のために、文字列が使用して明示的に符号化することができるascii符号化:\\u0203\u00e4'.encode('ascii').decode('unicode-escape')
JFSを

@hop:あなたの最初のコメント(なぜそれを削除したのですか?返信されたコメントは削除しないでください)はすでに言っています。私の返信(.encode('ascii').decode('unicode-escape'))は依存しませんsys.getdefaultencoding()
jfs 2015年

71

Unicode文字列をバイトの文字列として表すことは、エンコーディングと呼ばれます。を使用しu'...'.encode(encoding)ます。

例:

    >>>u'æøå'.encode( 'utf8')
    '\ xc3 \ x83 \ xc2 \ xa6 \ xc3 \ x83 \ xc2 \ xb8 \ xc3 \ x83 \ xc2 \ xa5'
    >>>u'æøå'.encode( 'latin1')
    '\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5'
    >>>u'æøå'.encode( 'ascii')
    UnicodeEncodeError: 'ascii'コーデックは位置0-5の文字をエンコードできません: 
    序数が範囲外です(128)

通常、Unicode文字列は、IOに使用する必要がある場合は常にエンコードします。たとえば、ネットワーク経由で転送したり、ディスクファイルに保存したりします。

バイトの文字列をUnicode文字列に変換することは、デコードと呼ばれます。使用unicode('...', encoding)または'...'。デコード(符号化)。

例:

   >>>u'æøå '
   u '\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5'#インタプリタは、Unicodeオブジェクトを次のように出力します
   >>> unicode( '\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5'、 'latin1')
   u '\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5'
   >>> '\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5'.decode(' latin1 ')
   u '\ xc3 \ xa6 \ xc3 \ xb8 \ xc3 \ xa5'

通常、ネットワークまたはディスクファイルから文字列データを受信するたびに、バイト文字列をデコードします。

私はpython 3のユニコード処理にいくつかの変更があると思いますので、上記はおそらくpython 3では正しくありません。

いくつかの良いリンク:


6
OPの質問に答えませんでした。OPはstr.encode()とunicode.decode()が何をするか知りたいです。元の質問で述べられていることを繰り返しました。
stuckintheshuck 2013

実際にあなたが今までにデコードとエンコーディングをいじくり回した理由についての素晴らしい答え。すべてのマシンが同じ文字セットを理解するわけではありませんが、それらはすべてバイトを理解します。コンピューターが普遍的に理解している(およびディスクに転送または保存できる)言語にバイトにエンコードしますが、人間が実際にそれらのバイトを読み取る必要があるときにデコードします(クライアント側など)。
Alex Petralia 2017

素晴らしい答え!これは上がるはずです!
Sandyp、

16

anUnicode。エンコード(「エンコード」)すると文字列オブジェクトが生成され、Unicodeオブジェクトで呼び出すことができます

文字列。decode( 'encoding')は、Unicodeオブジェクトを生成し、指定されたエンコーディングでエンコードされた文字列で呼び出すことができます。


さらにいくつかの説明:

エンコードが設定されていないUnicodeオブジェクトを作成できます。Pythonによってメモリに格納される方法は、問題ではありません。あなたはそれを検索して分割し、好きな文字列操作関数を呼び出すことができます。

しかし、ユニコードオブジェクトをコンソールまたはテキストファイルに出力するときが来ます。したがって、エンコードする必要があります(たとえば、UTF-8の場合)、encode( 'utf-8')を呼び出して、内部に '\ u <someNumber>'を含む文字列を取得します。これは完全に印刷可能です。

次に、もう一度-反対を行いたい-UTF-8でエンコードされた文字列を読み取り、それをUnicodeとして扱うため、\ u360は5ではなく1文字になります。次に、(選択したエンコードで)文字列をデコードし、 Unicodeタイプの新しいオブジェクトを取得します。

副次的注意として-「zip」、「base64」、「rot」などの変なエンコーディングを選択でき、それらの一部は文字列から文字列に変換されますが、最も一般的なケースはUTF-8が関係するものだと思います/ UTF-16および文字列。


12

mybytestring.encode(somecodec)は、次の値に対して意味がありますsomecodec

  • base64
  • bz2
  • zlib
  • ヘックス
  • クオプリ
  • 腐敗13
  • string_escape
  • うう

すでにデコードされたユニコードテキストのデコードが何に適しているのかわかりません。任意のエンコーディングでそれを試すと、常にシステムのデフォルトのエンコーディングで最初にエンコーディングしようとするようです。


5

strからstrへ、またはunicodeからunicodeへのデコード/エンコードに使用できるエンコードがいくつかあります。たとえば、base64、hex、またはrot13です。それらはコーデックモジュールにリストされています

編集:

Unicode文字列のデコードメッセージは、対応するエンコード操作を元に戻すことができます。

In [1]: u'0a'.decode('hex')
Out[1]: '\n'

返されるタイプは、私の意見では残念ですが、Unicodeではなくstrです。しかし、strとunicodeの間で適切なエンコード/デコードを実行していない場合、これはとにかく混乱のように見えます。


1
-1:デコードメソッドがUnicodeオブジェクトに適用されていません。代わりに、デコード操作が開始される前に、Unicodeオブジェクトが「ascii」バイト文字列としてエンコードされます。そのアサーションの証拠として、u'ã'.decode( 'hex')を試してみてください-UnicodeEncodeError
nosklo

2
@nosklo:その通りです。私が本当に意味しているのは、Unicodeオブジェクトにはdecode()メソッドがあり、非文字エンコーディングコーデックもそれらに適用できるということです。この全体の非文字エンコード・ビジネスは、Pythonで、このインタフェースが混乱<3作る

1

簡単な答えは、それらは互いに正反対であるということです。

コンピュータは非常に基本的なバイト単位を使用して情報を保存および処理します。人間の目には意味がありません。

たとえば、 '\ xe4 \ xb8 \ xad \ xe6 \ x96 \ x87'は2つの漢字の表現ですが、コンピュータはそれを検索するための辞書が与えられたときにそれが漢字であることのみを認識(印刷または保存)します。この場合、中国語の単語は「utf-8」辞書であり、別のまたは間違った辞書を(別のデコード方法を使用して)調べると、意図した中国語の単語を正しく表示できません。

上記の場合、コンピュータが中国語の単語を探すプロセスはdecode()です。

そして、コンピュータが中国語をコンピュータのメモリに書き込むプロセスは次のとおりですencode()

したがって、エンコードされた情報は生のバイトであり、デコードされた情報は生のバイトと参照するディクショナリの名前です(ディクショナリ自体ではありません)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.