Pythonにおけるエンコーディングの扱いとエンコーディングの変換について
(2010/11/1)本記事の内容はバージョン2系のPythonについて書かれている。バージョン3系ではエンコーディングの扱いが変わっており、「バージョン3系のPythonにおける文字列とそのエンコーディングに関する覚え書き(文字列型とバイト列型)」で扱っている。
(2014/11/20)リファレンスのリンク先を修正した。
エンコーディングとエンコード/デコード操作
Pythonにおいて、UTF-8やCP932(WindowsのShift_JIS)などのそれぞれのエンコーディングの文字列はUnicodeの文字列と相互に変換することができる。各エンコーディングにエンコードされている文字列オブジェクトのメンバ関数decode()の引数にそのエンコーディング名を指定すると、それをデコードしてUnicode文字列のオブジェクトが得られる。逆に、Unicode文字列オブジェクトのメンバ関数encode()の引数にエンコーディング名を指定すると、それぞれのエンコーディングでエンコードされた文字列のオブジェクトが得られる。
[EUC-JP文字列] eucjpstr.decode('euc-jp') │ ↑ ucstr.encode('euc-jp') ↓ │ utf8str.decode('utf-8') ─→ ─→ ucstr.encode('cp932') [UTF-8文字列] [Unicode文字列] [CP932文字列] ucstr.encode('utf-8') ←─ ←─ cp932str.decode('cp932') │ ↑ ucstr.encode('iso-2022-jp') ↓ │ iso2022jpstr.decode('iso-2022-jp') [ISO-2022-JP文字列]
また、文字列定数(リテラル)の手前に「u」と付けたものは実行環境のエンコーディング*1からUnicode文字列にデコードされたものとなる。例えばUTF-8エンコーディングで「u'日本語'」としたものは「'日本語'.decode('utf-8')」の戻り値と同じになる。また、組み込み関数unicode()を用いた「unicode('日本語', 'utf-8')」の戻り値も同じものとなる。
(注意:UTF-8エンコーディングの端末におけるテスト) >>> u'日本語' == '日本語'.decode('utf-8') == unicode('日本語', 'utf-8') == u'\u65e5\u672c\u8a9e' True
エンコーディング名の一覧については
http://docs.python.jp/3/library/codecs.html#standard-encodings
にあり、あるエンコーディング名に対して別名も存在する。また、エンコーディング変換とは関係ないが、Base64やbzip2、hexといった特殊なものもコーデック名として指定して変換することができる。
エンコーディングの変換
エンコーディングの変換はUnicode文字列を中継してdecode()とencode()を組み合わせて行う。(注意:UTF-8エンコーディングの端末におけるテスト) (UTF-8 <==> EUC-JP) >>> '日本語'.decode('utf-8').encode('euc-jp') '\xc6\xfc\xcb\xdc\xb8\xec' >>> '\xc6\xfc\xcb\xdc\xb8\xec'.decode('euc-jp').encode('utf-8') == '日本語' True (UTF-8 <==> ISO-2022-JP) >>> '日本語'.decode('utf-8').encode('iso-2022-jp') '\x1b$BF|K\\8l\x1b(B' >>> '\x1b$BF|K\\8l\x1b(B'.decode('iso-2022-jp').encode('utf-8') == '日本語' True (UTF-8 <==> CP932) >>> '日本語'.decode('utf-8').encode('cp932') '\x93\xfa\x96{\x8c\xea' >>> '\x93\xfa\x96{\x8c\xea'.decode('cp932').encode('utf-8') == '日本語' True
encode()やdecode()が失敗する場合について
上のencode()やdecode()は、当然のことながら、(元の)文字列オブジェクトの実際のエンコーディングと引数のエンコーディング名との関係によっては失敗する。例えば、CP932エンコーディングの文字列からUnicode文字列を得るのに「decode('utf-8')」とすると処理は失敗する。このように、正しくないエンコーディングが指定されたときにはUnicodeDecodeErrorという例外が発生する。>>> '\x93\xfa\x96{\x8c\xea'.decode('utf-8') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib64/python2.6/encodings/utf_8.py", line 16, in decode return codecs.utf_8_decode(input, errors, True) UnicodeDecodeError: 'utf8' codec can't decode byte 0x93 in position 0: unexpected code byte
(2010/3/30)上の例はdecode()のものだが、Unicode文字列から特定のエンコーディングにエンコード済みの文字列に対して更にencode()しようとしても例外が発生する。
(注意:UTF-8エンコーディングの端末におけるテスト) >>> '日本語'.encode('utf-8') Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6 in position 0: ordinal not in range(128)
上の「'日本語'」はUTF-8にエンコードされているため、それをUTF-8にエンコードすることはできない。一方、「u'日本語'」はUnicode文字列にデコードされているので、UTF-8にエンコードすることができる。
(注意:UTF-8エンコーディングの端末におけるテスト) >>> '日本語' == u'日本語'.encode('utf-8') == '\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e' True
関連URL:
使用したバージョン:
- Python 2.6.4