Help us understand the problem. What is going on with this article?

strとunicode

More than 5 years have passed since last update.

Python 2.x 系での話です。

コードは、Macの場合はTerminal, Windowsではコマンドプロンプトから python コマンドを実行し、pythonのconsole上で試しています。 Python 2.7.9 です.

str とは?

str とは所謂マルチバイト文字列です. '文字列' の様に書きます.

len(文字列) するとByte数が返ります. coding: utf-8 の場合は 9.

>>> len('いろは')

9

for - in で回すと、バイト毎に処理します.

>>> for c in 'abc':
...    print c

a
b
c
>>> for c in 'いろは':
...    print c

�
�
�
�
�
�
�
�
�

unicode.encode()unicode から str に変換できます.

>>> u'abc'.encode()

'abc'

encodingという概念がある.

>>> u'いろは'.encode('utf-8')

'\xe3\x81\x84\xe3\x82\x8d\xe3\x81\xaf'
>>> u'いろは'.encode('cp932')

'\x82\xa2\x82\xeb\x82\xcd'

実行環境のencodingに依存します. MacのTerminal上で実行すると utf-8 .

>>> 'いろは'

'\xe3\x81\x84\xe3\x82\x8d\xe3\x81\xaf'

Windows7のコマンドプロンプトから実行すると cp932 .

>>> 'いろは'

'\x82\xa2\x82\xeb\x82\xcd'

スクリプトファイルに直接書いた str はファイルのencodingに従う.
ただし、# coding: (エンコーディング名) と一致していないと実行時Errorになる.

#!/usr/bin/env python
# coding: utf-8

print 'いろは'

↑は utf-8 でprintしていますが、CUI環境のencodingが異なる場合は、文字化けします.

unicode とは?

unicode はバイトではなく、文字の単位で文字列を扱います. u'文字列' の様にuを先頭付けます.

len(文字列) すると 文字数 が返ります.

>>> len(u'いろは')

3

for - in で回すと、文字毎に処理します.

>>> for c in u'abc':
...    print c

a
b
c
>>> for c in u'いろは':
...    print c

い
ろ
は

str.decode()str から unicode に変換できます.

>>> 'いろは'.decode('utf-8')

u'\u3044\u308d\u306f'

unicode はencodingが統一されており、開発者は unicode を使う場合、encodingを意識しなくていい.

>>> u'いろはに' + u'ほへと'

u'\u3044\u308d\u306f\u306b\u307b\u3078\u3068'

ただし、スクリプト外部へ出力する場合は必ず str に変換することになります.

>>> print u'いろは'.encode('utf-8')

いろは

unicodestr に変換しなかった場合、pythonのruntimeが自動で変換しますが、変換に使うencodingは実行環境に依ります.
よくあるのは、日本語が混じっている strcoding: ascii で変換しようとして UnicodeEncodeError 例外が発生するケースです...

>>> print u'いろは'

Traceback (most recent call last):
  File "<input>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)

変換しないでうまくいくかどうかは、実行環境に依存します.
スクリプト外部に出す時は、ちゃんと意識して unicode --> str に変換してやるのがいいです.

unicode, str の使い分け

スクリプト内部では、unicode に統一するのがBestと思います.

sys.args 等、ライブラリから取得した str は直ぐに unicode に変換します。
逆に、スクリプト外部に文字列を出す時 (例:print) は、出す直前で unicode --> str に変換してやります.

strunicode を混ぜて使うと、pythonのruntimeが strunicode に変換しようとします.
この時、UnicodeDecodeError が発生して悩まされる事が多いです.

>>> 'いろはに' + u'ほへと'

Traceback (most recent call last):
  File "<input>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe3 in position 0: ordinal not in range(128)

strのencodingが分からない時...

スクリプト外部から取得した str のencodingが分からない時、
私は以下のコードで unicode に変換しています.

def toUnicode(encodedStr):
    '''
    :return: an unicode-str.
    '''
    if isinstance(encodedStr, unicode):
        return encodedStr

    for charset in [u'cp932', u'utf-8', u'euc-jp', u'shift-jis', u'iso2022-jp']:
        try:
            return encodedStr.decode(charset)
        except:
            pass
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away