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
グループへのユーザの追加@Linux

グループへユーザを追加する方法。 # gpasswd -a user group …

no image
ハードディスクへのアクセスが異常に遅い@Windows XP

Windowsの動作が異常に遅いPCがあって、調査していたらHDDへのアクセスが …

no image
RDO使ってOpenStack Pikeインストール@CentOS7

RDO を使ってOpenStack Pikeをallinoneでインストールした …

no image
DVD-Rに4倍速で書き込みできない@GSA-4040B

数年前に発売されたDVDマルチドライブ GSA-4040Bを持っているのですが、 …

no image
sphinxのPDF出力環境を構築する@Ubuntu 14.04

pythonはすでにインストールされているはずなので、pipをインストール # …

no image
ハイフンで始まるファイルを消す@Linux

ハイフンで始まる以下のようなファイル(-hoge)を作ったとします。 # ech …

no image
nForceのマザーM2NPV-VMでのRAID (NVRAID) の使用

数年前に買ったASUSのnForceのマザーボード M2NPV-VMで使っていた …

no image
表示言語を英語に変更@Windows 7 Ultimate RC

通常日本でPCを購入すると、日本語版のWindowsが付属してきます。 しかし、 …

no image
vimで検索語をハイライトする@さくらインターネット

普通vimで検索すると、検索語がハイライトされるのですが、さくらインターネットに …

no image
printfコマンドで数字を整形表示@Linux

echoコマンドはシステムによって挙動が異なる、特に改行関連を扱うオプションに差 …