Pythonでは、print文を使わないと日本語を正しく出力されない。print文を使うと、あらかじめ設定されているエンコードにしたがって適切に出力される。
1 2 3 4 | >>> "あいうえお" '\x82\xa0\x82\xa2\x82\xa4\x82\xa6\x82\xa8' >>> print "あいうえお" あいうえお |
デフォルトの言語を確認。
1 2 3 | >>> import sys >>> sys.stdout.encoding 'cp932' |
cp932は、Windowsで標準的に使われているエンコードだ。
エンコードを確認するには、想定しうる文字コードで、デコードしてみればよい。
cp932、ms932、shift-jisでデコードできた。cp932とms932は同じエンコードなので、当然の結果だ。shift-jisも特殊文字を除くと、cp932、ms932と同じなので、これだけの文字列では区別のできないのは当然だ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | >>> print "あいうえお".decode("cp932") あいうえお >>> print "あいうえお".decode("ms932") あいうえお >>> print "あいうえお".decode("shift-jis") あいうえお >>> print "あいうえお".decode("utf-8") Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\Python25\lib\encodings\utf_8.py", line 16, in decode return codecs.utf_8_decode(input, errors, True) UnicodeDecodeError: 'utf8' codec can't decode byte 0x82 in position 0: unexpecte d code byte >>> print "あいうえお".decode("utf-16") Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeEncodeError: 'cp932' codec can't encode character u'\ua082' in position 0 : illegal multibyte sequence |
文字コード判定関数
間違った文字コードでデコードすると例外が発生することを利用して文字コードを求める関数を作成してみた。
短い文字列の場合には誤判定が発生するようだ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | >>> def getEncoding(str): ... for encoding in ['utf-8', 'shift-jis', 'euc-jp']: ... try: ... str.decode(encoding) ... return encoding ... except: ... pass ... return None ... >>> getEncoding("あああ") 'shift-jis' >>> getEncoding(u"あああ".encode('utf-8')) #正しい 'utf-8' >>> getEncoding(u"あああ".encode('euc-jp')) #誤判定 'shift-jis' >>> getEncoding(u"あいうえお".encode('euc-jp')) #誤判定 'shift-jis' >>> getEncoding(u"東京特許許可局".encode('euc-jp')) #正しい 'euc-jp' |
もしかして、「あいうえお」は、euc-jpでもshift-jisでもエンコード結果が全く同じになるのではと思い試してみたが、そんなことは無かった。
1 2 | >>> print u"あいうえお".encode('euc-jp').decode('shift-jis') 、「、、、ヲ、ィ、ェ |
まとめ
いまどきのPC向けWebサイトを作るのであれば、「UTF-8」意外の文字コードを意識することはないと思うが、携帯電話対応やE-mailの送受信では未だに文字コードを意識しなければならない。試しにDecodeして成功すればその文字コードに違いないという楽観的な方法は、文字列が短い場合にはかなりの頻度で誤判定を引き起こすので注意が必要だ。文字コード判定ライブラリなども基本的にはこれと同じことをしているはずなので、出来る限り、文字コード判定に依存したコードは書きたくないものだ。