UserPreferences

PythonEncode


こんなエラーがおきたとき

>>> print hoge
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-7: ordinal not in range(128)

デフォルトで設定されてる文字コードを変えると解決します。 で、その設定のしかたですが、

1. 環境変数LANG に端末が扱うエンコードを設定する。(たぶん LANG=ja_JP.utf-8 か、 ja_JP.eucJP のどちらかでいけるとおもいます)

2. 1は端末に出力(ただprintする時)するときだけに対応するので、

3. (ファイルによってどのエンコードを使うべきかはケースバイケースでかわってしまうので)2へのシンプルで自信をもっておすすめできる対応はいまのところありません。

4. そこで、プログラマが明示的にエンコードを指定する方法を紹介します。

5. print でユニコードオブジェクトを出力するときは自動的に変換がはいりますが、文字列オブジェクトを出力するときは変換されません。

6. というわけで4の方法で好きなエンコードに変換して、printするとうまくいきます。

7. これでも化ける場合があります。それは1の設定をせずに、対話モードで入力している場合です。端末で入力された文字がどんなエンコードかも、 デフォルトの文字コード設定から推定しているので、入力を漢字として処理できていない場合、文字化けしてしまいます。

ちょっとながく&ややこしくなってしまいました。。 ようは1と4を両方やればたぶんなんとかなるとおもいますっ(ぉ

対話セッションの例

この例はdebian GNU/Linuxでやっています。実際に端末が扱う漢字コードはEUC-JPです。

LANG=Cの場合

$ LANG=C python
Python 2.4.4c0 (#2, Jul 30 2006, 15:43:58)
[GCC 4.1.2 20060715 (prerelease) (Debian 4.1.1-9)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> hoge = u"生徒会長"
>>> hoge
u'\xc0\xb8\xc5\xcc\xb2\xf1\xc4\xb9'
ユニコード8文字になっていて、漢字が文字として認識されて*いない*ことがわかります。
>>> print hoge
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-7: ordinal not in range(128)
ASCIIにエンコードできません。。
>>> hoge.encode('euc-jp')
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
UnicodeEncodeError: 'euc_jp' codec can't encode character u'\xb2' in position 4: illegal multibyte sequence
変な文字が入ってるのでEUCにも変換できません。。
>>> hoge.encode('sjis')
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
UnicodeEncodeError: 'shift_jis' codec can't encode character u'\xc0' in position 0: illegal multibyte sequence
SJISにも変換できません。
>>> hoge.encode('utf-8')
'\xc3\x80\xc2\xb8\xc3\x85\xc3\x8c\xc2\xb2\xc3\xb1\xc3\x84\xc2\xb9'
>>> print hoge.encode('utf-8')
!モジバケ!
UTF-8には変換はできますが実際にほしいものとはちがいます。
>>> print hoge.encode('iso-8859-1')
生徒会長
実はiso-8859-1 としてエンコードすると、ほぼ入力そのまま(途中で変わる場合があります)の文字列が帰ってきます。 でもこれはうまくいくとは限りませんしかなり微妙なので緊急避難で使えるかな、という程度のものです。

LANG=ja_JP.eucJPの場合

$ LANG=ja_JP.eucJP python
Python 2.4.4c0 (#2, Jul 30 2006, 15:43:58)
[GCC 4.1.2 20060715 (prerelease) (Debian 4.1.1-9)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> hoge = u"生徒会長"
>>> hoge
u'\u751f\u5f92\u4f1a\u9577'
ユニコード4文字になっていて、漢字が文字として認識されていることがわかります。
>>> print hoge
生徒会長
ちゃんと端末用にEUC-JPに変換されて出力されてるので、読めます :)
>>> hoge.encode('euc-jp')
'\xc0\xb8\xc5\xcc\xb2\xf1\xc4\xb9'
euc-jpに変換しました。
>>> print hoge.encode('euc-jp')
生徒会長
そのまま出力したら、よめました。
>>> hoge.encode('utf-8')
'\xe7\x94\x9f\xe5\xbe\x92\xe4\xbc\x9a\xe9\x95\xb7'
utf-8に変換しました。
>>> print hoge.encode('utf-8')
!モジバケ!
この端末はEUC-JPなので表示は文字化けしてしまいます。
>>> hoge.encode('sjis')
'\x90\xb6\x93k\x89\xef\x92\xb7'
>>> print hoge.encode('sjis')
!モジバケ!
sjisも同様です。