2. 日本語処理

StringとUnicode文字列


一章で説明したように、Pythonの文字列は通常の文字列とUnicode文字列の二つの型があります(注1)。日本語などのマルチバイト文字列を扱う場合は、プログラムの内部表現はUnicode文字列を使うのがいいでしょう。

注1) Python 3.0ではUnicode文字列に統一されます。

Webアプリケーションなどの場合、ブラウザから送られてくるCGIパラメータは通常、UTF-8でエンコードされた文字列です。Pythonではこれらは通常の文字列として処理されます。複数の文字コードを扱うとバグの温床になりやすいので、プログラムと外界が接する境界線上でUnicode文字列と通常の文字列の変換をするのが好ましいです。

UTF-8の文字列をUnicode文字列に変換するには、decode関数を使います。図1は、「テスト」という文字列をUnicode文字列に変換してます。decode関数の引数には変換する文字列のエンコーディングを指定します。変換後の文字列を見るとu'¥u3066¥u3059¥u3068'のように先頭に「u」がついています。この「u」はUnicode文字列のマークです。

図1 
>>> s = '¥xe3¥x81¥xa6¥xe3¥x81¥x99¥xe3¥x81¥xa8'
>>> s
'¥xe3¥x81¥xa6¥xe3¥x81¥x99¥xe3¥x81¥xa8'
>>> print s
てすと
>>> us = s.decode("utf-8")
>>> us
u'¥u3066¥u3059¥u3068'
>>> print us
てすと
>>> 

次にUnicode文字列から通常の文字列に変換します。この処理はencode()関数を使います。図1のusをさらにUTF-8に変換したコードが図2です。encode()関数の引数には、変換後のエンコードを指定します。

図2 
>>> s2 = us.encode("utf-8")
>>> s2
'¥xe3¥x81¥xa6¥xe3¥x81¥x99¥xe3¥x81¥xa8'
>>> 

UnicodeとUTF-8間の変換はビット演算が行われるだけです。しかし、CP932とUnicodeとの変換などでは変換テーブルにマッチしない文字(機種依存文字)が存在します。これらの文字がある場合、変換途中で例外が発生して処理が中断されます。変換不可能な文字がある場合でも処理を続行したい場合は、encode、decode関数それぞれの第2引数に"ignore"を指定することで、変換できない文字は無視できます。特別な文字に置き換えたい場合は、"replace"を指定します。

暗黙の型変換

プログラムを実行しているとUnicodeDecodeErrorが発生することがあります。ファイルの入出力など、プログラムと外部の境界線上で発生することが多いです。これは、Unicode文字列を暗黙に通常の文字列に変換しようとするために発生します。暗黙に文字コード変換されるときに、通常はUS-ASCIIとして変換しようとするため、日本語が含まれているとエラーが発生します。

これを回避するには、二つの方法があります。一つは、「コラム: 対話モードでの日本語の文字化け」のように、sitecustomize.pyでデフォルトのエンコーディングを指定します。もう一つは、エラーが発生するたびに、Unicode文字列を適切なエンコーディングに置き換えて関数に渡します。一度書いたコードを変更せずに他の環境で動くようにしたい場合は、後者の方法をお薦めします。

Pythonコードのエンコーディング

筆者はコード中に日本語などのマルチバイト文字列を書くことはほとんどありません。しかし、日本語などASCII文字列以外の文字列をコードの中に書かなければならないことがあります。

その場合は、ソースコードの先頭(1行目か2行目)に次のように書いて、ファイルをUTF-8のエンコーディングで保存してください。

  # -*- coding: utf-8 -*-


コラム: 対話モードでの日本語の文字化け


対話モードでPythonを使っているときに、日本語が正しく表示されないという問題がよく聞かれます。その場合は、site-packagesディレクトリ(Windowsではデフォルトでは、C:¥Python2.5¥lib¥python2.5¥site-packages)にsitecustomize.pyファイルをおきます。sitecustomize.pyは次のように記述します。

import sys
sys.setdefaultencoding('cp932')

Pythonインタープリタを起動し直して実行してみてください。
Comments