試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

バージョン3系のPythonにおける文字列とそのエンコーディングに関する覚え書き(文字列型とバイト列型)

バージョン3系のPythonでは文字列(としての意味を持つ)データと特定のエンコーディングエンコードされたバイトの並びとを明確に区別しており、前者をstr型,後者をbytes型のオブジェクトとして用いることになる。
バージョン2系では「Pythonにおけるエンコーディングの扱いとエンコーディングの変換について」で書いたように

                                 [EUC-JP文字列]
         eucjpstr.decode('euc-jp')  │     ↑ eucjpstr = ucstr.encode('euc-jp')
                                    ↓     │
    utf8str.decode('utf-8')     ─→          ─→   cp932str = ucstr.encode('cp932')
     [UTF-8文字列]                [Unicode文字列]               [CP932文字列]
utf8str = ucstr.encode('utf-8') ←─   ucstr  ←─   cp932str.decode('cp932')
                                    │     ↑
iso2022jpstr                        ↓     │ iso2022jpstr.decode('iso-2022-jp')
 = ucstr.encode('iso-2022-jp')
                               [ISO-2022-JP文字列]

Unicode文字列を中心として各エンコーディングの文字列とこれを変換するという形となっていたが、バージョン3系では

                                       [EUC-JPバイト列]
                  b_eucjp.decode('euc-jp') │       ↑ b_eucjp = bytes(strobj, 'euc-jp')
                                           |       | b_eucjp = strobj.encode('euc-jp')
                                           ↓       │
                                    ─→                  ─→ b_cp932 = bytes(strobj, 'cp932')
    b_utf8.decode('utf-8')                                 b_cp932 = strobj.encode('cp932')
        [UTF-8バイト列]                      [文字列]                   [CP932バイト列]
 b_utf8 = bytes(strobj, 'utf-8')    ←─      strobj      ←─ b_cp932.decode('cp932')
 b_utf8 = strobj.encode('utf-8')           |       ↑
                                           |       |
b_iso2022jp = bytes('iso-2022-jp')         |       │
b_iso2022jp = strobj.encode('iso-2022-jp') ↓       | b_iso2022jp.decode('iso-2022-jp')
                                     [ISO-2022-JPバイト列]

文字列オブジェクトを中心として各エンコーディングのバイト列とこれを変換するという形に変わっている。
文字列からバイト列への変換は

[バイト列オブジェクト] = bytes([strオブジェクト], encoding='[エンコーディング名]')

のような形のbytes型オブジェクトの生成もしくは

[バイト列オブジェクト] = [strオブジェクト].encode('[エンコーディング名]')

によって行い、逆にバイト列をデコードして文字列オブジェクトを得るには

[バイト列オブジェクト].decode('[エンコーディング名]')

とする。
上の図の通りになっていることをシェル上で確認してみると下のようになる。

(文字列型オブジェクトの生成)
>>> strobj = 'テスト'
>>> strobj.__class__
<class 'str'>

(文字列型からEUC-JPのバイト列型オブジェクトを生成)
>>> b_eucjp = bytes (strobj, 'eucjp')
>>> b_eucjp.__class__
<class 'bytes'>
(EUC-JPにエンコードされた内容を確認)
>>> b_eucjp
b'\xa5\xc6\xa5\xb9\xa5\xc8'
(デコードすると元の文字列型と同じ内容のものが得られる)
>>> b_eucjp.decode ('eucjp')
'テスト'
>>> b_eucjp.decode ('eucjp').__class__
<class 'str'>

(CP932のエンコーディングで同様のテストを行う)
>>> b_cp932 = bytes (strobj, 'cp932')
>>> b_cp932.__class__
<class 'bytes'>
>>> b_cp932
b'\x83e\x83X\x83g'
>>> b_cp932.decode ('cp932')
'テスト'
>>> b_cp932.decode ('cp932').__class__
<class 'str'>

(ISO-2022-JPのエンコーディングで同様のテストを行う・encode()を用いている)
>>> b_iso2022jp = strobj.encode ('iso-2022-jp')
>>> b_iso2022jp.__class__
<class 'bytes'>
>>> b_iso2022jp
b'\x1b$B%F%9%H\x1b(B'
>>> b_iso2022jp.decode ('iso-2022-jp')
'テスト'
>>> b_iso2022jp.decode ('iso-2022-jp').__class__
<class 'str'>

(UTF-8のエンコーディングで同様のテストを行う・encode()を用いている)
>>> b_utf8 = strobj.encode ('utf8')
>>> b_utf8.__class__
<class 'bytes'>
>>> b_utf8
b'\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88'
>>> b_utf8.decode ('utf8')
'テスト'
>>> b_utf8.decode ('utf8').__class__
<class 'str'>

(「バージョン3系のPythonにおける文字列とそのエンコーディングに関する覚え書き(ファイル入出力とエンコーディング)」に続く)

関連記事:

使用したバージョン: