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
rubyのirbで補完@cygwin

cygwin上でrubyのirbを動かしている時に、ふと補完ができたら便利だと思 …

no image
スペースの入ったディレクトリ名やファイル名をスクリプトで処理する@Linux

findコマンドでスペース入ったディレクトリやファイルを検索し、その結果をfor …

no image
tarファイルを解凍せずに中身をみる@Linux

tarファイルの中身を見るのに、小さなファイルなら解凍して中身を展開すればよいで …

no image
Linuxコンテナ(LXC)内からNFSマウント@Ubuntu 14.04

Ubuntu 14.04 上で作成したLinuxコンテナ内からNFSマウントでき …

no image
WordPress プラグイン - Stat Traq導入

アクセス統計をとってくれるプラグインStat TraqをWordPressに導入 …

no image
Apache 2.0 + OpenSSL

OpenSSLは SSLv2/SSLv3/TLSv1 をサポートしているオープン …

no image
perlのCPANでモジュールをインストール@Debian Etch

CPANにはperlのモジュールが多数登録されています。これをインストールする方 …

no image
sshの公開鍵・秘密鍵

公開鍵・秘密鍵をたまにしか作成しないのでメモ # ssh-keygen -t d …

no image
Search Everything 日本語版

WordPressのページ機能でページを作成しても、検索窓の検索対象になりません …

no image
NEC Aterm 8300N DHCPの固定割り当てIPが割り当てられない

NEC Aterm 8300N の設定でDHCPの固定割り当てを設定しても、なぜ …