Pythonと日本語文字
Python2.x系で文字列を使おうとする場合、実は二つの型があります。str型とunicode型です。3.xでは文字列はunicode型になるということで、混乱を避けるために、先日出させていただいた本にはunicode型についてまったく触れていません。どうしようか悩んだ末にばっさりシンプルにしてみたのですが、本格的にプログラミングをしようと思ったら、2.x系を使っている段階ではunicode型とstr型の違いを把握しておく必要はあります。以下は、2.x系のための文字列型のお話です。
まずは、簡単なところから。文字列は普通に定義するとstr型になります。

>>> test_str = 'abcd_1234'
>>> type(test_str)
<type 'str'>
>>> test_kanji = 'ごり押し'
>>> type(test_kanji)
<type 'str'>

しかし、じつはこれでは困ったことがおきます。文字列の長さがちゃんとわかりません。

>>> len(test_str)
9
>>> len(test_kanji)
12

'abcd_1234'は9文字でOKですが、'ごり押し'はどう見ても4文字ですが12文字とか言われてしまいます。インタラクティブシェルでそのまま中身を表示すると理由がわかります。ちなみに、これはMacOSXでの実行例です。Windowsの場合は「ごり押し」は8文字だと言われるでしょう。

>>> test_kanji
'\xe3\x81\x94\xe3\x82\x8a\xe6\x8a\xbc\xe3\x81\x97'

日本語にはいくつか文字コードがありますが、MacOSXのデフォルトはUTF-8です。これは日本語の一文字分で3バイト必要になるので、4文字の日本語で12バイト分となりlen関数の戻り値が12となったわけです。つまり、str型は文字列というよりバイト列という感じになります。Windowsでは文字コードが違うのでlen関数の戻り値が変わるわけですが、それでは困ります。そこで出てくるのがunicode型です。リテラル表現は、頭にuをつけます。

>>> test_unicode = u'ごり押し'
>>> test_unicode
u'\u3054\u308a\u62bc\u3057'
>>> len(test_unicode)
4
>>> print(test_unicode)
ごり押し

という感じになって、よい具合です。
じゃあ、いつもunicodeだけでいいんじゃね?という話になりそうで、実際3.x系からそうなるわけですが、2.x系でよく嵌まるのが次のエラーです。

>>> f = open('gorigori.txt','w')
>>> f.write(test_unicode)
Traceback (most recent call last):
File "", line 1, in
UnicodeEncodeError: 'ascii' codec can't encode characters
           in position 0-3: ordinal not in range(128)

ただ、ファイルに書き出そうとしただけなのに、なんかひどいことになってしまいました。
これは、「unicode型の文字列をasciiコーデックを使ってエンコードしようとしたら出来ませんでしたすいません」という意味なんですが、和訳できても意味がわからないことにかわりはありません。そもそもなんで、ごりごりの日本語である「ごり押し」をasciiコーデックでエンコードしようとしているのでしょうか?それは簡単で、そう設定されているからです。次のコマンドで確認できます。

>>> import sys
>>> sys.getdefaultencoding()
'ascii'

なるほど。しかし、そうは言われても、unicode文字列が何で書き出せないんだ?と思うところですが、Pythonのunicode型はその名前からイメージされる代物ではありません。なんとなく自動的にutf-8あたりになってくれそうですが、それは間違いでunicode型からどのエンコードで出力するかは別に指定する必要があります。逆に言うと、どんな環境にも対応できるということも出来ます。

>>> gori_utf = test_unicode.encode('utf-8')
>>> gori_sjis = test_unicode.encode('cp932')
>>> gori_utf
'\xe3\x81\x94\xe3\x82\x8a\xe6\x8a\xbc\xe3\x81\x97'
>>> gori_sjis
'\x82\xb2\x82\xe8\x89\x9f\x82\xb5'
>>> print(gori_utf)
ごり押し
>>> print(gori_sjis)
???艟??

最後の行は、このコードを実行したのがMacなので文字化けします。Windows環境ではちゃんと出るかわりにそのひとつ上が文字化けします。
unicode型が持っているencodeメソッドは、引数にコーデックをとって、unicode型をstr型に変換します。その逆のメソッド、つまりstr型のメソッドで引数にコーデックをとってunicode型を返すdecodeメソッドもあります。

>>> gori_utf.decode('utf-8')
u'\u3054\u308a\u62bc\u3057'

だんだん話がややこしくなってきましたので、まとめておきましょう。
Python2.x系では文字列には二つの種類がありますが、内部的にはunicode型を使って、入出力で適当な文字コードにしたがって変換するようにするというのが、基本的な方針になるかと思います。ファイルを読み込んでタブで区切って返すくらいのスクリプトであれば、あんまり気にすることもありませんが、XMLやデータベースをいじるアプリの場合は注意が必要かと思います。
スポンサーサイト

テーマ:プログラミング - ジャンル:コンピュータ

【2010/05/10 23:51】 | Python | トラックバック(0) | コメント(0) | page top↑
<<タプルのいろいろ | ホーム | Pythonスタートブック、その内容2>>
コメント
コメントの投稿














管理者にだけ表示を許可する

トラックバック
トラックバックURL
→http://tanopy.blog79.fc2.com/tb.php/53-5b0d3346
この記事にトラックバックする(FC2ブログユーザー)
| ホーム |