2009年1月21日水曜日

Pythonで日本語文字列を扱う

Pythonで日本語文字列を置換しようとする度にググるのでいい加減まとめておく。
前提としてPython 2.6.1だと、文字列は全部Unicodeだと見なされる。で、Unicodeじゃない文字列は単なるバイト列として扱われる。
(Python 2.6.1対応。Python 3.0では未確認)

まず、日本語(たぶんマルチバイト文字全般)の処理方法。
# -*- coding: utf-8 -*-
先頭にこれを書いて、ソースはutf-8で保存する。

# -*- coding: utf-8 -*-
str = "こんにちは世界"
print str
strは当然utf-8で保存されてるし、出力もそう。
Windowsのコンソールなんかでやると文字化けする。

# -*- coding: utf-8 -*-
str = "こんにちは世界"
print str.decode('utf-8')
pythonはユニコードが標準らしい。utf-8をデコードして(ユニコードにして)やる。
Windowsのコンソールだとちゃんと表示する。

# -*- coding: utf-8 -*-
str = u"こんにちは世界"
print str
最初からハードコーディングするならこっちが簡単。uを付けるとユニコードになる。
やっぱりWindowsのコンソールだとちゃんと表示する。

# -*- coding: utf-8 -*-
str = u"こんにちは世界"
print str.encode('utf-8')
意味はないけど、ユニコードをutf-8にエンコードすることも出来る。
Windowsのコンソールだとちゃんと(?)文字化けする。(化け方はさっきと同じ)

# -*- coding: utf-8 -*-
str = "こんにちは世界"
print unicode(str, 'utf-8')
実は、ユニコードへの変換を受け持つ関数(constructor)もある。
encode, decodeよりも判りやすいかも。実は便利な機能付き。
# -*- coding: utf-8 -*-
import sys
str = "\x80こんにちは世界"
print unicode(str, 'utf-8', errors='ignore')

try:
  print unicode(str, 'utf-8', errors='replace')
except:
  print sys.exc_info()[:]

try:
  print unicode(str, 'utf-8', errors='strict')
except:
  print sys.exc_info()[:]

errorsにオプションが指定できる。
ignoreを設定すると、変なのが混じってたら無視してくれる。
replaceは、置き換え文字列(REPLACEMENT CHARACTER, U+FFFD)に置き換えてくれる。Windowsだとcp932でエンコードできねえって怒られる。
strictは、そのまんま処理する。当然デコードできねえって怒られる。(これがデフォルト値)

ファイルを読み込んだり書き出したりするときの文字コードで覚えておくのは次のくらいかな。
euc-jp, utf-8, cp932, shift-jis

個人的には、pythonの文字列に戻してやるdecodeと、書き出すときのencodeを使うのが判りやすいと思う。(変な制御コードが入ってるかもしれないから、エラー処理は必要になっちゃうけど)
文字コードの自動判別とか無理しないで、ちゃんと指定するのが良さそう。

参考:

1 件のコメント:

匿名 さんのコメント...

> Python 2.6.1だと、文字列は全部Unicodeだと見なされる

そんなことはありません。