1: 2016-12-03 (土) 15:47:41 njf |
2: 2016-12-03 (土) 16:20:07 njf |
| *PythonのUnicodeに関する問題 [#xb7d4a12] | | *PythonのUnicodeに関する問題 [#xb7d4a12] |
| + | |
| + | PythonでUnicodeをあつかうのはかなりやっかいです。 |
| + | バージョン3では改善されましたが、バージョン2系ではUnicodeとstr型の二つに互換性がなく、つねにその文字列がstr型なのか、Unicodeなのか意識していないとエラーが出ます。 |
| + | コンソール画面にテキストを表示する、というようなごく簡単な処理ですらエラーが出ます。 |
| + | |
| + | バージョン3以降を使えばよいのですが、ライブラリの対応状況などもありバージョン2系を使うことも多いのが実情です。 |
| + | |
| + | そんなときのUnicodeの取り扱いについて紹介します。 |
| | | |
| *Unicodeを実際に使うには [#e84d1365] | | *Unicodeを実際に使うには [#e84d1365] |
- | # -*- coding: utf-8 -*- | |
| | | |
- | *まとめ [#e3cdb0f9] | + | まず、ソースコードにUnicode文字列を書くためには、以下のコメントをソースファイルの先頭付近に入れておく必要があります。 |
| + | |
| + | # -*- coding: utf-8 -*- |
| + | |
| + | これにより、Pythonはそのファイルでutf-8の文字コードが使われていると判断します。 |
| + | ないとエラーになります。 |
| + | |
| + | 実際にutf-8の文字列をソースに書くときは、 |
| + | |
| + | utfString = u"これはutfです" |
| + | |
| + | というように、先頭に「u」をつけます。 |
| + | |
| + | 標準出力でUnicodeを出力するなら、以下のように出力前に変換してやる必要があります。 |
| + | こうしないとエラーとなります。 |
| + | |
| + | import sys |
| + | |
| + | sys.stdout = codecs.getwriter('utf_8')(sys.stdout) |
| + | |
| + | 標準入力や標準エラー出力も同様です。 |
| + | |
| + | sys.stdin = codecs.getreader('utf-8')(sys.stdin) |
| + | sys.stderr = codecs.getwriter('utf-8')(sys.stderr) |
| + | |
| + | Unicodeとstrを変換するには、Unicode->strはdecode、str->Unicodeはencodeメソッドを使います。 |
| + | |
| + | utfString = u"これはUnicodeです" |
| + | strString = "これはstrです" |
| + | |
| + | |
| + | encodedUtf = utfString.encode("utf_8") #utfをstr |
| + | decodedStr = strString.decode("utf_8") #strをutf |
| + | |
| + | print type(encodedUtf) |
| + | print type(decodedStr) |
| + | |
| + | 結果 |
| + | <type 'str'> |
| + | <type 'unicode'> |
| + | |
| + | 逆にするとエラーとなります。 |
| + | |
| + | 現実には使っているライブラリなどの引数や戻り値が、どれがunicodeなのかstrなのかいちいち覚えていられないので、エラーが出たらencodeかdecodeを行う、といった対応になります。 |
| + | |
| + | unicode、strどちらかわからない、またはどちらの可能性もあるとき、必ずunicodeの結果がほしいという場合には、isinstanceを使って以下のような関数を定義すると便利です。 |
| + | |
| + | def convertToUtf(s): |
| + | if isinstance(s,unicode): |
| + | return s |
| + | return s.decode("utf_8") |
| + | |
| + | するといつでもunicode文字列が得られます。strについても同様の関数が定義できるでしょう。 |
| + | |
| + | 実際にバージョン2系で開発していると、Unicode関連のエラーはかなりイラッとさせられます。 |
| + | |
| + | UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128) |
| + | |
| + | このエラーを何度見たことかわからないくらいです。 |
| + | |
| + | |
| + | 根本解決として、早めにバージョン3以降に移るのがおすすめです。 |