1: 2016-12-03 (土) 15:47:41 njf[6] [7] [8] | 2: 2016-12-03 (土) 16:20:07 njf[6] [9] [10] | ||
---|---|---|---|
Line 1: | Line 1: | ||
*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以降に移るのがおすすめです。 |
(This host) = https://njf.jp