pythonで日本語処理めとめ@python 2.6

python で文字列を扱う場合、unicode型と、str型というのがありますが、これらの扱いが正直大変。初心者が何かとつまずく所だと思いますし、私自身もつまづきましたので、まとめてみました。(間違いあったらご指摘ください)

unicode型とはpythonが独自に扱う文字列型で、str型は通常はutf-8やshift-jisといったある文字コードでエンコードされた文字列型です。文字列を変数に代入する時、普通に代入するとstr型になるが、”u” を文字列の前に付けるとunicode型になります。

(ファイル名study.pyとします)
#! /bin/python
u1=u"これはunicode型です"
print u1

ソースコードをpython独自のunicode型で書くことはできないので、実行時に上記のu1はソースコードの文字コードをunicodeに変換する必要があります。この時、pythonはデフォルトでasciiしか扱えないため、以下のように実行するとエラーになります。

# ./study.py
SyntaxError: Non-ASCII character '\xe3' in file ./study.py on line 6, but no encoding declared; see http://www.python.org/peps/pep-0263.html for detail

これを避けるために用いられるのが、ソースコードの文字コード指定です。これはpythonとしては結構常識ですよね。

#! /bin/python
# -*- coding: utf8 -*-
u1=u"これはunicode型です"
print u1
# ./study.py
これはunicode型です

unicode をutf-8やshifit-jisなどに変換することをエンコード、逆をデコードと呼びます。今自分がどちらの型を扱っているか分からない場合はtype関数で見てみましょう。(ここからは、上記ソースの1,2行目は省略します)

u1=u"これはUnicode型です"
s1="これはstr型です"
print type(u1)
print u1
print type(s1)
print s1
# ./study.py
<type 'unicode'>
これはUnicode型です
<type 'str'>
これはstr型です

このようなソースの書き方をした場合、print u1 は、unicode から端末の標準出力の文字コード(私の場合はutf-8)に自動で変換されて表示され、print s1 は、s1 の中に入っている文字コードがそのまま出力されます。なので、s1にshift-jisの文字が入っていて、端末の文字コードがutf-8だと文字化けします。

次に、u1とs1と結合してprintしてみます。

u1=u"これはUnicode型です"
s1="これはstr型です"
print u1 + s1

実行すると、

# ./study.py
Traceback (most recent call last):
  File "./study2.py", line 6, in <module>
    print u1 + s1
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe3 in position 0: ordinal not in range(128)

はい。エラーになります。これは、ptyhonは結合時に一端s1をunicodeにデコードしようとするのですが、デフォルトではascii文字列しかデコードできないため、エラーになるのです。これがめちゃくちゃ分かりづらい。ソースコードや標準出力の文字コードは自動で変換してくれるのに、内部の文字コード変換は自動でやってくれないのです。よって、以下のように手動でs1の中身はutf-8ですよとpythonに教えて、デコード(unicodeに変換)する必要があります。

u1=u"これはUnicode型です"
s1="これはstr型です"
print u1 + s1.decode('utf-8')
# ./study.py
これはUnicode型ですこれはstr型です

無事表示されました。もしくは、結合する文字列を全てstr型にそろえれば、unicode への変換が必要ないので、u1を予め手動でエンコード(utf-8に変換)しても正常に処理できます。

u1=u"これはUnicode型です"
s1="これはstr型です"
print u1.encode('utf-8') + s1
# ./study.py
これはUnicode型ですこれはstr型です

エンコードの文字コードを間違えてもpythonはstr型をそのまま出力するだけなので、文字化けします。

u1=u"これはUnicode型です"
s1="これはstr型です"
print u1.encode('shift-jis') + s1
# ./study.py
?????Unicode?^???これはstr型です

いちいち面倒だなと思う場合は、pythonのデフォルトエンコーディングをutf-8にしてしまう方法もありです。ただ、デフォルトを変えてしまうので、システムが大きいと思わぬ所で不具合が出る可能性があるので注意が必要です。

import sys
reload (sys)
sys.setdefaultencoding('utf-8')

u1=u"これはUnicode型です"
s1="これはstr型です"
print u1 + s1
# ./study.py
これはUnicode型ですこれはstr型です

ちなみに、setdefaultencoding()は、実行準備完了時に削除される関数らしいので、再度呼び出したい場合はreloadをする必要があります。 もしくは、行頭の #! /bin/python を #! /bin/python -S に変更すれば、reloadは必要なくなるようです。 自分で書くちょっとしたプログラムなら、この方法が一番楽ちんそうですね。

 

タイトルとURLをコピーしました