コーデックmbcsでは例外が発生しない

_winreg の件を調べていて気付いたんだけど、コーデック mbcs は変換できない文字に出会っても例外を発生させないね。

# Python 2.7.1
# ↓ハングルと簡体字が含まれてます
data = u'\ud55c\uae00 and \u7b80\u4f53\u5b57'
print data.encode('mbcs')  # 出力: ?? and ?体字

上のコードを実行しても例外は発生しない。変換できない文字は自動で ? に置き換えられている。

何をやっているのか調べてみたら、 WideCharToMultiByte() を呼んでいる場所に行き着いた

static int encode_mbcs(PyObject **repr,
                       const Py_UNICODE *p, /* unicode */
                       int size) /* size of unicode */
{
    /* 省略 */
    if (0 == WideCharToMultiByte(CP_ACP, 0, p, size, s, mbcssize, NULL, NULL))
    /* 省略 */
}

変換できない文字があったことを知るためのフラグ lpUsedDefaultChar にNULLが指定されている。どうりで例外が発生しないわけだ。

Python 3.2 ではこの引数をチェックして例外を出すように変更されているので、以下の通りちゃんと例外が発生する。

# Python 3.2
data = '\ud55c\uae00 and \u7b80\u4f53\u5b57'
print(data.encode('mbcs'))
# UnicodeEncodeError: 'mbcs' codec can't encode characters in position 0--1: invalid character

Python でコードを書いていると時々、多言語の処理がいい加減な部分にぶつかって嫌になるけど、少しづつ良くなってはいるな。