Mazn.net

やってみて 調べてみて 苦労しなけりゃ 箱は動かじ

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

      2013/07/15

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は必要なくなるようです。 自分で書くちょっとしたプログラムなら、この方法が一番楽ちんそうですね。

 

 - IT技術, プログラミング

336px

Message

メールアドレスが公開されることはありません。

  関連記事

no image
PS3 Media Server で自動起動できない@Windows 7 64bit

PS3 Media Player へ、DLNA環境をWindows Media …

no image
JBossのHypersonicSQL(hsql)管理ツール起動方法

JBossには気軽に使用できるHSQLが組み込まれています。ちょっとしたDBを使 …

no image
インストールしているThunderbird 2の拡張機能と不足機能

Thunderbirdに以下のアドオンをインストールしてみました。 Auto A …

no image
sshのちょっと高度な使い方

めっきり使う機会が減ってしまったtelnetの代わりによく使うssh。最近はmo …

no image
シェルで2進数、8進数、10進数、16進数変換@bash

シェルスクリプトで2進数や16進数を扱う方法です。 まずは、bc コマンドを使っ …

no image
rdesktopの改造@Debian etch

LinuxからWindowsのリモートデスクトップに接続するコマンドです。 De …

no image
manをmoreではなくlessで見る@FreeBSD 7.1

さくらインターネットでsshでログインし、manを打つとmoreを使用してページ …

no image
MP3のジャケット自動取得と埋め込み

今までアルバムのジャケットにそれほど興味はなく、MP3プレーヤにその機能があって …

no image
サーバが落ちてsshが応答しない@CentOS 5

ssh でサーバにログインしていて、サーバが落ちた時に反応がなくなってイライラし …

no image
gmailでフィルタリング転送した時メールは受信トレイに残るの?

gmailの基本転送機能は全てのメールをあるアドレスに転送しますが、フィルタを用 …